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

Reformat with black and add PR-check #4

Merged
merged 2 commits into from
Oct 23, 2023
Merged
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
11 changes: 11 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: Linters

on: [pull_request]

jobs:
black:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: psf/black@stable
22 changes: 12 additions & 10 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from setuptools import setup

setup(name='smart_settings',
version='1.1',
description='Smart JSON setting files',
url='https://github.com/mrolinek',
author='Michal Rolinek, MPI-IS Tuebingen, Autonomous Learning',
author_email='[email protected]',
license='MIT',
packages=['smart_settings'],
install_requires=['pyyaml'],
zip_safe=False)
setup(
name="smart_settings",
version="1.1",
description="Smart JSON setting files",
url="https://github.com/mrolinek",
author="Michal Rolinek, MPI-IS Tuebingen, Autonomous Learning",
author_email="[email protected]",
license="MIT",
packages=["smart_settings"],
install_requires=["pyyaml"],
zip_safe=False,
)
2 changes: 1 addition & 1 deletion smart_settings/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .smart_settings import load, loads
from .file_editing import add_key, change_key_name

__all__ = ['load', 'loads']
__all__ = ["load", "loads"]
28 changes: 17 additions & 11 deletions smart_settings/add_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,30 @@
import argparse
import glob

parser = argparse.ArgumentParser(description='Adding a key to many JSON files.')
parser.add_argument(dest='files', type=str, help='Input file(s)')
parser.add_argument(dest='key_name', type=str, help='Name of the key to add')
parser.add_argument(dest='default_value', type=str, help='Default value to assign')
parser.add_argument('--override', action='store_true', help='Override value if key present')
parser = argparse.ArgumentParser(description="Adding a key to many JSON files.")
parser.add_argument(dest="files", type=str, help="Input file(s)")
parser.add_argument(dest="key_name", type=str, help="Name of the key to add")
parser.add_argument(dest="default_value", type=str, help="Default value to assign")
parser.add_argument(
"--override", action="store_true", help="Override value if key present"
)


if __name__ == '__main__':
if __name__ == "__main__":
args = parser.parse_args()

matching_files = glob.glob(args.files, recursive=True)
if not matching_files:
print(f"No files matching {args.files}")
exit(2)

*prefixes, new_key = args.key_name.split('.')
*prefixes, new_key = args.key_name.split(".")
for setting_file in matching_files:
add_key(setting_file, prefixes=prefixes, new_key=new_key,
default_value=eval(args.default_value), override=args.override, conditions=None)


add_key(
setting_file,
prefixes=prefixes,
new_key=new_key,
default_value=eval(args.default_value),
override=args.override,
conditions=None,
)
34 changes: 24 additions & 10 deletions smart_settings/change_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,37 @@
import argparse
import glob

parser = argparse.ArgumentParser(description='Changing a key name in JSON file(s).')
parser.add_argument(dest='files', type=str, help='Input file(s)')
parser.add_argument(dest='key_name', type=str, help='Name of the key to change (with \'.\' syntax for nesting)')
parser.add_argument(dest='new_name', type=str, help='New name of the key (only the suffix -- no \'.\' expected)')
parser.add_argument('--override', action='store_true', help='Override value if key present')
parser = argparse.ArgumentParser(description="Changing a key name in JSON file(s).")
parser.add_argument(dest="files", type=str, help="Input file(s)")
parser.add_argument(
dest="key_name",
type=str,
help="Name of the key to change (with '.' syntax for nesting)",
)
parser.add_argument(
dest="new_name",
type=str,
help="New name of the key (only the suffix -- no '.' expected)",
)
parser.add_argument(
"--override", action="store_true", help="Override value if key present"
)


if __name__ == '__main__':
if __name__ == "__main__":
args = parser.parse_args()

matching_files = glob.glob(args.files, recursive=True)
if not matching_files:
print(f"No files matching {args.files}")
exit(2)

*prefixes, old_key = args.key_name.split('.')
*prefixes, old_key = args.key_name.split(".")
for setting_file in matching_files:
change_key_name(setting_file, prefixes=prefixes, old_name=old_key, new_name=args.new_name, conditions=None)


change_key_name(
setting_file,
prefixes=prefixes,
old_name=old_key,
new_name=args.new_name,
conditions=None,
)
18 changes: 8 additions & 10 deletions smart_settings/dynamic.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,32 @@


def _replace_inside_brackets(string, replace_from, replace_to):
index = string.find('{')
index = string.find("{")
if index == -1:
yield string
return
yield string[:index + 1]
new_index = string[index + 1:].find('}')
yield string[: index + 1]
new_index = string[index + 1 :].find("}")
if new_index == -1:
yield from string[index:]
return
new_index += index + 1
yield string[index + 1:new_index].replace(replace_from, replace_to)
yield string[index + 1 : new_index].replace(replace_from, replace_to)
yield from _replace_inside_brackets(string[new_index:], replace_from, replace_to)


def replace_inside_brackets(string, replace_from, replace_to):
return ''.join(list(_replace_inside_brackets(
string, replace_from, replace_to)))
return "".join(list(_replace_inside_brackets(string, replace_from, replace_to)))


def fstring_in_json(format_string, namespace):
if not isinstance(format_string, str):
return format_string

replaced_dollar_signs = replace_inside_brackets(format_string, '$', 'ENV_')
env_dict = {'ENV_' + key: value for key, value in os.environ.items()}
replaced_dollar_signs = replace_inside_brackets(format_string, "$", "ENV_")
env_dict = {"ENV_" + key: value for key, value in os.environ.items()}
try:
formatted = eval('f\"' + replaced_dollar_signs +
'\"', {**env_dict, **namespace})
formatted = eval('f"' + replaced_dollar_signs + '"', {**env_dict, **namespace})
except BaseException as e:
return format_string

Expand Down
18 changes: 12 additions & 6 deletions smart_settings/file_editing.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ def change_key_name(setting_file, prefixes, old_name, new_name, conditions=None)
if old_name in as_dict:
old_val = as_dict[old_name]
as_dict[new_name] = old_val
print(f"{setting_file}: Key {'.'.join(prefixes+[old_name])} renamed to {'.'.join(prefixes+[new_name])}")
print(
f"{setting_file}: Key {'.'.join(prefixes+[old_name])} renamed to {'.'.join(prefixes+[new_name])}"
)
del as_dict[old_name]
with open(setting_file, "w") as f:
json.dump(orig_dict, f, indent=4)
Expand All @@ -40,13 +42,16 @@ def change_key_name(setting_file, prefixes, old_name, new_name, conditions=None)

def check_correct_conditions(dct, conditions):
for lhs, rhs in conditions.items():
if not rhs == dct.get(lhs, float('nan')): # using that 'nan' is not equal to ANYTHING in Python

if not rhs == dct.get(
lhs, float("nan")
): # using that 'nan' is not equal to ANYTHING in Python
return False
return True


def add_key(setting_file, prefixes, new_key, default_value, override=False, conditions=None):
def add_key(
setting_file, prefixes, new_key, default_value, override=False, conditions=None
):
conditions = conditions or {}

with open(setting_file) as f:
Expand All @@ -68,7 +73,9 @@ def add_key(setting_file, prefixes, new_key, default_value, override=False, cond

if new_key in as_dict:
if override:
print(f"{setting_file}: Overwrote {'.'.join(prefixes+[new_key])}={default_value} (from {as_dict[new_key]})")
print(
f"{setting_file}: Overwrote {'.'.join(prefixes+[new_key])}={default_value} (from {as_dict[new_key]})"
)
as_dict[new_key] = default_value
else:
print(f"{setting_file}: Key {new_key} already present, not overwriting...")
Expand All @@ -80,4 +87,3 @@ def add_key(setting_file, prefixes, new_key, default_value, override=False, cond
with open(setting_file, "w") as f:
json.dump(orig_dict, f, indent=4)
return True

24 changes: 12 additions & 12 deletions smart_settings/param_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,21 @@


class NoDuplicateDict(dict):
""" A dict with prohibiting init from a list of pairs containing duplicates"""
"""A dict with prohibiting init from a list of pairs containing duplicates"""

def __init__(self, *args, **kwargs):
if args and args[0] and not isinstance(args[0], dict):
keys, _ = zip(*args[0])
duplicates = [
item for item,
count in collections.Counter(keys).items() if count > 1]
item for item, count in collections.Counter(keys).items() if count > 1
]
if duplicates:
raise TypeError(
"Keys {} repeated in json parsing".format(duplicates))
raise TypeError("Keys {} repeated in json parsing".format(duplicates))
super().__init__(*args, **kwargs)


class AttributeDict(dict):
""" A dict which allows attribute access to its keys."""
"""A dict which allows attribute access to its keys."""

def __getattr__(self, *args, **kwargs):
try:
Expand All @@ -29,9 +28,10 @@ def __getattr__(self, *args, **kwargs):
raise AttributeError(e)

def __deepcopy__(self, memo):
""" In order to support deepcopy"""
"""In order to support deepcopy"""
return self.__class__(
[(deepcopy(k, memo=memo), deepcopy(v, memo=memo)) for k, v in self.items()])
[(deepcopy(k, memo=memo), deepcopy(v, memo=memo)) for k, v in self.items()]
)

def __setattr__(self, key, value):
self.__setitem__(key, value)
Expand All @@ -44,7 +44,7 @@ def __repr__(self):


class ImmutableAttributeDict(AttributeDict):
""" A dict which allows attribute access to its keys. Forced immutable."""
"""A dict which allows attribute access to its keys. Forced immutable."""

def __delattr__(self, item):
raise TypeError("Setting object not mutable after settings are fixed!")
Expand Down Expand Up @@ -89,13 +89,13 @@ def update_recursive(d, u, overwrite=False):
if isinstance(v, collections.abc.Mapping):
d[k] = update_recursive(d.get(k, {}), v, overwrite)
if isinstance(v, collections.abc.Sequence):
raw_key = removesuffix(k, '*')
raw_key = removesuffix(k, "*")
if raw_key + "*" in d: # append
d[raw_key + "*"] = deepcopy(v + d[raw_key + '*'])
d[raw_key + "*"] = deepcopy(v + d[raw_key + "*"])
elif raw_key in d: # keep original list
pass
else: # key does not exist yet, append
d[k] = v
d[k] = v
elif k not in d or overwrite:
d[k] = v
return d
25 changes: 17 additions & 8 deletions smart_settings/port_cluster_utils_3.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,25 @@
import argparse
import glob

parser = argparse.ArgumentParser(description='Porting JSON file(s) to Cluster utils >=3.0')
parser.add_argument(dest='files', type=str, help='Input file(s)', nargs='+')
parser = argparse.ArgumentParser(
description="Porting JSON file(s) to Cluster utils >=3.0"
)
parser.add_argument(dest="files", type=str, help="Input file(s)", nargs="+")


if __name__ == '__main__':
if __name__ == "__main__":
args = parser.parse_args()

for setting_file in args.files:
change_key_name(setting_file, prefixes=[], old_name='model_dir', new_name='working_dir')
change_key_name(setting_file, prefixes=[], old_name='default_json', new_name='__import__')
change_key_name(setting_file, prefixes=['fixed_params'], old_name='default_json', new_name='__import_promise__')


change_key_name(
setting_file, prefixes=[], old_name="model_dir", new_name="working_dir"
)
change_key_name(
setting_file, prefixes=[], old_name="default_json", new_name="__import__"
)
change_key_name(
setting_file,
prefixes=["fixed_params"],
old_name="default_json",
new_name="__import_promise__",
)
Loading
Loading