diff --git a/.vscode/settings.json b/.vscode/settings.json index 8dd0ae8..a0a88fd 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,7 +3,7 @@ "python.testing.pyTestEnabled": true, "python.testing.unittestEnabled": false, "python.testing.nosetestsEnabled": false, - "python.pythonPath": "/anaconda/envs/lsr/bin/python", + "python.pythonPath": "/anaconda/envs/aiida-workshop/bin/python", "python.linting.pylintEnabled": false, "python.linting.flake8Enabled": true, "python.linting.enabled": true diff --git a/docs/source/conf.py b/docs/source/conf.py index 25072dd..20f6b22 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -16,50 +16,22 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # +import inspect +import json import os import sys import urllib -import json +from types import FunctionType + +from sphinx.ext.autosummary import Autosummary +# from sphinx.ext.autosummary import get_documenter +from docutils.parsers.rst import directives +# from sphinx.util.inspect import safe_getattr # sys.path.insert(0, os.path.abspath('.')) sys.path.insert(0, os.path.abspath('../..')) import jsonextended # noqa: E402 -git_history = urllib.request.urlopen( - 'https://api.github.com/repos/chrisjsewell/jsonextended/releases') -git_history = git_history.read().decode('utf-8') -git_history_json = json.loads(git_history) - -ordered_releases = {} -for rel in git_history_json: - rversion = rel['tag_name'].replace("v", "").split(".") + ["0"] - major = float(".".join(rversion[0:2])) - minor = float(".".join(rversion[2:4])) - if major not in ordered_releases: - ordered_releases[major] = {} - ordered_releases[major][minor] = { - "version": rel['tag_name'], "header": rel['name'], "body": rel["body"]} - -with open('releases.rst', 'w') as f: - f.write('Releases\n') - f.write('---------\n') - f.write('\n') - for major in reversed(sorted(list(ordered_releases.keys()))): - header = True - for minor in sorted(list(ordered_releases[major].keys())): - rel = ordered_releases[major][minor] - title_text = ' '.join([rel['version'], '-', rel['header'], '\n']) - f.write(title_text) - if header: - f.write('~' * len(title_text)) - header = False - else: - f.write('+' * len(title_text)) - f.write('\n') - for line in rel['body'].split('\n'): - f.write(' '.join([line, '\n'])) - f.write('\n') - # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. @@ -220,84 +192,121 @@ ("py:class", "numpy.ndarray"), ("py:class", "pint.quantity._Quantity"), ("py:class", "builtins.set"), - ] +] + + +def create_releases_page(): + try: + git_history = urllib.request.urlopen( + 'https://api.github.com/repos/chrisjsewell/jsonextended/releases') + except urllib.error.HTTPError: + return + git_history = git_history.read().decode('utf-8') + git_history_json = json.loads(git_history) + + ordered_releases = {} + for rel in git_history_json: + rversion = rel['tag_name'].replace("v", "").split(".") + ["0"] + major = float(".".join(rversion[0:2])) + minor = float(".".join(rversion[2:4])) + if major not in ordered_releases: + ordered_releases[major] = {} + ordered_releases[major][minor] = { + "version": rel['tag_name'], + "header": rel['name'], + "body": rel["body"]} + + with open('releases.rst', 'w') as f: + f.write('Releases\n') + f.write('---------\n') + f.write('\n') + for major in reversed(sorted(list(ordered_releases.keys()))): + header = True + for minor in sorted(list(ordered_releases[major].keys())): + rel = ordered_releases[major][minor] + title_text = ' '.join( + [rel['version'], '-', rel['header'], '\n']) + f.write(title_text) + if header: + f.write('~' * len(title_text)) + header = False + else: + f.write('+' * len(title_text)) + f.write('\n') + for line in rel['body'].split('\n'): + f.write(' '.join([line, '\n'])) + f.write('\n') + + +create_releases_page() + + +class AutoFunctionSummary(Autosummary): + """ + adapted from: + https://github.com/markovmodel/PyEMMA/blob/devel/doc/source/conf.py#L285 + and discussed here: + https://stackoverflow.com/questions/20569011/python-sphinx-autosummary-automated-listing-of-member-functions + + """ + option_spec = { + 'functions': directives.unchanged, + 'classes': directives.unchanged, + 'toctree': directives.unchanged, + 'nosignatures': directives.unchanged + } + + required_arguments = 1 + + @staticmethod + def get_functions(mod): + + def is_function_local(obj): + return (isinstance(obj, FunctionType) + and obj.__module__ == mod.__name__) + + members = inspect.getmembers(mod, predicate=is_function_local) + return [name for name, value in members + if not name.startswith('_')] + + @staticmethod + def get_classes(mod): + + def is_class_local(obj): + return (inspect.isclass(obj) + and obj.__module__ == mod.__name__) + + members = inspect.getmembers(mod, predicate=is_class_local) + return [name for name, value in members + if not name.startswith('_')] + + def run(self): + + mod_path = self.arguments[0] + + (package_name, mod_name) = mod_path.rsplit('.', 1) + pkg = __import__(package_name, globals(), locals(), [mod_name]) + mod = getattr(pkg, mod_name) + + if 'classes' in self.options: + klasses = self.get_classes(mod) + self.content = ["~%s.%s" % ( + mod_path, klass) for klass in klasses + if not klass.startswith('_')] + if 'functions' in self.options: + functions = self.get_functions(mod) + content = ["~%s.%s" % (mod_path, func) for func in functions + if not func.startswith('_')] + if self.content: + self.content += content + else: + self.content = content + try: + pass + finally: + return super(AutoFunctionSummary, self).run() -# adapted from: -# https://github.com/markovmodel/PyEMMA/blob/devel/doc/source/conf.py#L285 -# and discussed here: -# https://stackoverflow.com/questions/20569011/python-sphinx-autosummary-automated-listing-of-member-functions def setup(app): # app.connect('autodoc-skip-member', skip_deprecated) - try: - from sphinx.ext.autosummary import Autosummary - # from sphinx.ext.autosummary import get_documenter - from docutils.parsers.rst import directives - # from sphinx.util.inspect import safe_getattr - # import re - import inspect - from types import FunctionType - - class AutoFunctionSummary(Autosummary): - - option_spec = { - 'functions': directives.unchanged, - 'classes': directives.unchanged, - 'toctree': directives.unchanged, - 'nosignatures': directives.unchanged - } - - required_arguments = 1 - - @staticmethod - def get_functions(mod): - - def is_function_local(obj): - return (isinstance(obj, FunctionType) - and obj.__module__ == mod.__name__) - - members = inspect.getmembers(mod, predicate=is_function_local) - return [name for name, value in members - if not name.startswith('_')] - - @staticmethod - def get_classes(mod): - - def is_class_local(obj): - return (inspect.isclass(obj) - and obj.__module__ == mod.__name__) - - members = inspect.getmembers(mod, predicate=is_class_local) - return [name for name, value in members - if not name.startswith('_')] - - def run(self): - - mod_path = self.arguments[0] - - (package_name, mod_name) = mod_path.rsplit('.', 1) - pkg = __import__(package_name, globals(), locals(), [mod_name]) - mod = getattr(pkg, mod_name) - - if 'classes' in self.options: - klasses = self.get_classes(mod) - self.content = ["~%s.%s" % ( - mod_path, klass) for klass in klasses - if not klass.startswith('_')] - if 'functions' in self.options: - functions = self.get_functions(mod) - content = ["~%s.%s" % (mod_path, func) - for func in functions - if not func.startswith('_')] - if self.content: - self.content += content - else: - self.content = content - try: - pass - finally: - return super(AutoFunctionSummary, self).run() - - app.add_directive('autofuncsummary', AutoFunctionSummary) - except BaseException as e: - raise e + app.add_directive('autofuncsummary', AutoFunctionSummary) diff --git a/docs/source/releases.rst b/docs/source/releases.rst new file mode 100644 index 0000000..099c39c --- /dev/null +++ b/docs/source/releases.rst @@ -0,0 +1,155 @@ +Releases +--------- + +v0.7.0 - Improved edict.filter_keyvals and added edict.filter_keyfuncs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +- added "OR"/"AND" `logic` parameter +- removed `errors` parameter from edict.filter_keyvals (instead use edict.filter_keyfuncs) + +v0.7.1 - added deep_copy option to edict functions +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + +v0.7.2 - corrected filter_keyvals for dict_like siblings +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +- added additional tests + +v0.7.3 - added plugin class contextmanager ++++++++++++++++++++++++++++++++++++++++++++++ + + +v0.7.4 - added fraction.Fraction encoder plugin ++++++++++++++++++++++++++++++++++++++++++++++++++ + + +v0.7.6 - bug fix for mock path read context ++++++++++++++++++++++++++++++++++++++++++++++ + + +v0.7.7 - added allow_other_keys for plugin.decoders ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + +0.7.8 - add sdist to pypi (required for conda-forge) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + +v0.7.9 - add files required by setup.py to manifest (for sdist) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + +v0.6.0 - Improvements to LazyLoad +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +- in `edict.LazyLoad` + - changed `ignore_prefixes` -> `ignore_regexes` for greater flexibility + - added logging (at debug level) for each file parsed (helpful for longer loading times) + - added better exception handling for file parsing (to help with debugging) +- added `edict.dump` in order to better mirror standard `json` module (its exactly the same as `edict.to_json`) + + + + +v0.6.1 - added remove_lkey to edict.apply and parse_errors to LazyLoad +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + +v0.6.2 - added .yaml parser plugin +++++++++++++++++++++++++++++++++++++ + + +v0.6.3 - edict.remove_paths; allow list of path keys +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + +v0.6.4 - edict.merge added list_of_dicts option ++++++++++++++++++++++++++++++++++++++++++++++++++ + + +v0.5.0 - Major Improvements to MockPath +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +split off into separate package +paths relative to base +index +handle maketemp of folder + +v0.5.1 - API Documentation update ++++++++++++++++++++++++++++++++++++ + + +v0.5.2 - Minor improvement +++++++++++++++++++++++++++++ + + +v0.5.3 - Minor Bug Fix +++++++++++++++++++++++++ + + +v0.5.4 - Minor improvement +++++++++++++++++++++++++++++ +- added byte decoding to mock path write class + +v0.5.5 - Minor improvements of MockPath ++++++++++++++++++++++++++++++++++++++++++ +added stat and chmod (dummy) methods + +v0.5.6 - Minor improvements of MockPath ++++++++++++++++++++++++++++++++++++++++++ + + +v0.5.7 - Reorder Documentation of Versions +++++++++++++++++++++++++++++++++++++++++++++ + + +v0.4.0 - Apply functions +~~~~~~~~~~~~~~~~~~~~~~~~~~ +- added apply and combine_apply functions +- refactored edict to avoid deepcopy recursion (flatten, unflatten) + + + + +v0.4.1 - General functionality improvement +++++++++++++++++++++++++++++++++++++++++++++ +- added more support for list of dict structures +- option to keep siblings when filtering by keyval +- added wildcard option to remove_keys and value plus/minus error to filter_keyvals + + + + + + + + + + + +v0.4.2 - Added ReadTheDoc Site +++++++++++++++++++++++++++++++++ + + +v0.4.3 - minor bug fixes and improvements ++++++++++++++++++++++++++++++++++++++++++++ + + +v0.4.4 - Addition of Diff Evaluator ++++++++++++++++++++++++++++++++++++++ +`edict.diff`, which can optionally use numpy.allclose to assess arrays of floating point numbers + +v0.4.5 - Minor improvements ++++++++++++++++++++++++++++++ + + +v0.4.6 - Minor improvements of MockPath ++++++++++++++++++++++++++++++++++++++++++ + + +v0.3.7 - pprint improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + improved pprint +- treat items in list of dicts as heirarchical +- compress_lists option +- round_floats option + +Also added ipynb parser +