Skip to content

Commit

Permalink
Merge pull request #4 from watertap-org/cli-output
Browse files Browse the repository at this point in the history
Add CLI flags for output and version info
  • Loading branch information
lbianchi-lbl authored May 15, 2024
2 parents b5efb29 + 5003c8c commit 04a6672
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 10 deletions.
9 changes: 8 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ name: Test getinfo.py

on:
push:
branches: [main]
pull_request:

jobs:

Expand Down Expand Up @@ -39,4 +41,9 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- if: ${{ !matrix.unavailable }}
run: python getinfo.py
run: |
python getinfo.py --help
python getinfo.py --version
python getinfo.py
python getinfo.py -o stdout
python getinfo.py -o getinfo-output.json
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,5 @@ For the sake of example, let's consider the scenario in which you encounter an i
![](docs/images/copy-path.png)
3. In the same terminal/console window where the failure occurred, type `python ` followed by the path to the downloaded `getinfo.py` file, e.g. `python "C:\Users\user\Downloads\getinfo.py"`. If the terminal/console window isn't open anymore, open a new one trying to reproduce the conditions when the failure occurred (e.g. same working directory, Conda environment, etc)
![](docs/images/run.png)
4. Copy the output and paste it where needed, e.g. a GitHub issue or a Slack support message. In this particular example, inspecting the **getinfo** output would help an experienced developer spot an incompatibility between the installed versions of `Pyomo` and `idaes-pse` (the `Pyomo` version is too old)
4. After collecting various types of information, **getinfo** will save the collected data in JSON format. By default, the output is saved to a JSON file in the current working directory (the name is displayed in the logging), which can be opened with any text editor and/or attached to e.g. a GitHub issue or a Slack support message. In this particular example, inspecting the **getinfo** output would help an experienced developer spot an incompatibility between the installed versions of `Pyomo` and `idaes-pse` (the `Pyomo` version is too old)
![](docs/images/output.png)
60 changes: 52 additions & 8 deletions getinfo.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import argparse
import collections
import datetime
import json
Expand All @@ -6,6 +7,7 @@
import importlib.metadata
import inspect
import locale
import logging
import os
import platform
import shutil
Expand All @@ -27,7 +29,9 @@
)


__version__ = "0.24.1.25"
__version__ = "v0.24.1.25"

_log = logging.getLogger("getinfo")


class _Node:
Expand Down Expand Up @@ -260,6 +264,7 @@ def _for_collector(obj: Collector, data: dict=None, parent=None):
data = {}
key = get_key(obj)
subdata = data[key] = {}
_log.info("Collecting from: %s", key)
for collected in obj.collect():
populate(collected, data=subdata, parent=parent)

Expand Down Expand Up @@ -621,7 +626,6 @@ def getinfo_watertap():
def getinfo_platform():
yield from (
locale.getlocale,
locale.getpreferredencoding,
platform.platform,
platform.system,
platform.machine,
Expand Down Expand Up @@ -649,20 +653,60 @@ def _to_jsonable(obj: object):
return str(obj)


def _display(obj):
return print(
json.dumps(obj, indent=4, default=_to_jsonable)
)
def _get_default_file_name(prefix: str = ".getinfo-output") -> str:
ts = datetime.datetime.utcnow()
return f"{prefix}-{ts.isoformat()}"


# created in the global scope to facilitate debugging
DATA = {}


def main():
def main(args=None):

parser = _build_cli_parser()
cli_opts = parser.parse_args(args)
logging.basicConfig(level=logging.INFO)
_log.info(parser.prog)
_log.debug(cli_opts)

_log.info("Start collecting information")
root = Module(target=__name__, prefix="getinfo_")
populate(root, DATA)
_display(DATA)
_log.info("Collection complete")

output_str = json.dumps(DATA, indent=4, default=_to_jsonable)
n_lines = output_str.count("\n")
output_dest = cli_opts.output
if output_dest in {"stdout"}:
_log.info("output (%d lines) will be written to stdout", n_lines)
print(output_str)
else:
path = Path(output_dest) if output_dest else Path(_get_default_file_name()).with_suffix(".json")
path = path.resolve()
written = path.write_text(output_str)
_log.info("output (%d lines) has been written to %s (%d B)", n_lines, os.fspath(path), written)


def _build_cli_parser() -> argparse.ArgumentParser:
p = argparse.ArgumentParser(prog=f"getinfo {__version__}")
p.add_argument(
"-o",
"--output",
dest="output",
help="""
Where the output will be written to. Can be a path to a file or `stdout`.
If this flag is not specified (default), an autogenerated filename will be used.
""",
default="",
)
p.add_argument(
"-v",
"--version",
action="version",
version=__version__,
)
return p


if __name__ == '__main__':
Expand Down

0 comments on commit 04a6672

Please sign in to comment.