Skip to content

change args to user_info and fix docstring #253

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

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions news/skip_creation_config.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
**Added:**

* functionality to run `get_user_info` without execution interruption

**Changed:**

* <news item>

**Deprecated:**

* <news item>

**Removed:**

* <news item>

**Fixed:**

* <news item>

**Security:**

* <news item>
104 changes: 58 additions & 46 deletions src/diffpy/utils/tools.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import importlib.metadata
import json
import os
from copy import copy
from pathlib import Path

user_info_imsg = (
"No global configuration file was found containing "
"information about the user to associate with the data.\n"
"By following the prompts below you can add your name and email to this file on the current "
"computer and your name will be automatically associated with subsequent diffpy data by default.\n"
"This is not recommended on a shared or public computer. "
"You will only have to do that once.\n"
"For more information, please refer to www.diffpy.org/diffpy.utils/examples/toolsexample.html."
)

def clean_dict(obj):

def _clean_dict(obj):
Copy link
Contributor Author

@yucongalicechen yucongalicechen Dec 20, 2024

Choose a reason for hiding this comment

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

made this function private

"""
Remove keys from the dictionary where the corresponding value is None.

Expand All @@ -27,7 +36,7 @@ def clean_dict(obj):
return obj


def stringify(obj):
def _stringify(obj):
"""
Convert None to an empty string.

Expand All @@ -44,7 +53,7 @@ def stringify(obj):
return obj if obj is not None else ""


def load_config(file_path):
def _load_config(file_path):
"""
Load configuration from a .json file.

Expand All @@ -71,67 +80,70 @@ def load_config(file_path):
def _sorted_merge(*dicts):
merged = {}
for d in dicts:
d = _clean_dict(d)
Copy link
Contributor Author

@yucongalicechen yucongalicechen Dec 20, 2024

Choose a reason for hiding this comment

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

add a step here so we don't need to pass in _clean_dict(d) for every d

merged.update(d)
return merged


def _create_global_config(args):
def _get_config_info(user_info):
global_config = _load_config(Path().home() / "diffpyconfig.json")
local_config = _load_config(Path().cwd() / "diffpyconfig.json")
if global_config or local_config:
return _sorted_merge(global_config, local_config, user_info)
return None


def _create_global_config(user_info):
print(user_info_imsg)
username = input(
f"Please enter the name you would want future work to be credited to " f"[{args.get('username', '')}]: "
).strip() or args.get("username", "")
email = input(f"Please enter the your email " f"[{args.get('email', '')}]: ").strip() or args.get("email", "")
return_bool = False if username is None or email is None else True
with open(Path().home() / "diffpyconfig.json", "w") as f:
f.write(json.dumps({"username": stringify(username), "email": stringify(email)}))
print(
f"You can manually edit the config file at {Path().home() / 'diffpyconfig.json'} using any text editor.\n"
f"Or you can update the config file by passing new values to get_user_info(), "
f"see examples here: https://www.diffpy.org/diffpy.utils/examples/toolsexample.html"
f"Please enter the name you would want future work to be credited to "
f"[{user_info.get('username', '')}]: "
).strip() or user_info.get("username", "")
email = input(f"Please enter the your email " f"[{user_info.get('email', '')}]: ").strip() or user_info.get(
"email", ""
Copy link
Contributor Author

Choose a reason for hiding this comment

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

name change from args to user_info

)
return return_bool
config = {"username": _stringify(username), "email": _stringify(email)}
if username and email:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The function originally returns a bool that passes back to get_user_info to see if we need to create a global config file. If user only input none or one of username / email, an empty global config file will be created. I simplified the logic here so that we only create a global config file if both username and email are present. Does this make sense though?

with open(Path().home() / "diffpyconfig.json", "w") as f:
f.write(json.dumps(config))
print(
f"You can manually edit the config file at "
f"{Path().home() / 'diffpyconfig.json'} using any text editor.\n"
f"Or you can update the config file by passing new values to get_user_info(), "
f"see examples here: https://www.diffpy.org/diffpy.utils/examples/toolsexample.html."
)
return config


def get_user_info(args=None):
def get_user_info(user_info=None, skip_config_creation=False):
"""
Get username and email configuration.
Retrieve or create user configuration (username and email).

First attempts to load config file from global and local paths.
If neither exists, creates a global config file.
It prioritizes values from args, then local, then global.
Removes invalid global config file if creation is needed, replacing it with empty username and email.
Workflow:
1. Loads config from global and local paths, prioritizing user_info, then local, then global.
2. If no config files are found and skip_config_creation is False, prompts the user for input.
Creates a global config file only if both username and email are valid.
3. If no config files and skip_config_creation is True, uses user_info (even if empty).

Parameters
----------
args argparse.Namespace
The arguments from the parser, default is None.
user_info dict or None
A dictionary containing the user input, default is None.

Returns
-------
dict or None:
The dictionary containing username and email with corresponding values.

"""
config_bool = True
global_config = load_config(Path().home() / "diffpyconfig.json")
local_config = load_config(Path().cwd() / "diffpyconfig.json")
if global_config is None and local_config is None:
print(
"No global configuration file was found containing "
"information about the user to associate with the data.\n"
"By following the prompts below you can add your name and email to this file on the current "
"computer and your name will be automatically associated with subsequent diffpy data by default.\n"
"This is not recommended on a shared or public computer. "
"You will only have to do that once.\n"
"For more information, please refer to www.diffpy.org/diffpy.utils/examples/toolsexample.html"
)
config_bool = _create_global_config(args)
global_config = load_config(Path().home() / "diffpyconfig.json")
config = _sorted_merge(clean_dict(global_config), clean_dict(local_config), clean_dict(args))
if config_bool is False:
os.remove(Path().home() / "diffpyconfig.json")
config = {"username": "", "email": ""}

return config
config = _get_config_info(user_info)
if config:
return config
if not skip_config_creation:
return _create_global_config(user_info)
return {
"username": _stringify(user_info.get("username", "")),
"email": _stringify(user_info.get("email", "")),
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

simplified the workflow here



def get_package_info(package_names, metadata=None):
Expand Down
Loading
Loading