diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000..bf27765f --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,60 @@ +FROM continuumio/miniconda3:24.9.2-0 + +USER root + +ARG USERNAME=vscode +ARG USER_UID=1000 +ARG USER_GID=1000 +ENV USERNAME=${USERNAME} +ENV USER_UID=${USER_UID} +ENV USER_GID=${USER_GID} + +RUN apt-get update -q \ + && apt-get install -q -y --no-install-recommends \ + build-essential \ + ripgrep \ + pandoc \ + adduser \ + git \ + grep \ + curl \ + wget \ + vim + +RUN conda install -y python=3.9 \ + && pip install --no-cache-dir pipx \ + && pipx reinstall-all + +RUN conda install -c conda-forge gh jupyterlab + +COPY requirements.txt /requirements.txt + +RUN python3 -m pip install -r requirements.txt + +RUN python3 -m pip install --upgrade flake8-pytest-importorskip click==8.0.4 black==24.4.2 flake8==4.0.1 + +RUN groupadd -g ${USER_GID} ${USERNAME} && \ + adduser --disabled-password --uid ${USER_UID} --gid ${USER_GID} --gecos "" ${USERNAME} && \ + echo "${USERNAME} ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers + +USER $USERNAME + +# FROM mcr.microsoft.com/devcontainers/miniconda:1-3 +# +# # Copy environment.yml (if found) to a temp location so we update the environment. Also +# # copy "noop.txt" so the COPY instruction does not fail if no environment.yml exists. +# COPY environment.yml* .devcontainer/noop.txt /tmp/conda-tmp/ +# RUN if [ -f "/tmp/conda-tmp/environment.yml" ]; then umask 0002 && /opt/conda/bin/conda env update -n base -f /tmp/conda-tmp/environment.yml; fi \ +# && rm -rf /tmp/conda-tmp +# +# COPY requirements.txt /requirements.txt +# +# RUN conda install -y python=3.9 \ +# && pip install --no-cache-dir pipx \ +# && pipx reinstall-all +# +# +# # [Optional] Uncomment this section to install additional OS packages. +# # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ +# # && apt-get -y install --no-install-recommends + \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..d85b8169 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,81 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/miniconda +{ + "name": "Hatchet Python 3.9", + "build": { + "context": "..", + "dockerfile": "Dockerfile" + }, + // "features": { + // // "ghcr.io/devcontainers/features/git:1": { + // // "ppa": true, + // // "version": "os-provided" + // // }, + // // "ghcr.io/devcontainers/features/git-lfs:1": { + // // "autoPull": true, + // // "version": "latest" + // // }, + // "ghcr.io/devcontainers/features/github-cli:1": { + // "installDirectlyFromGitHubRelease": true, + // "version": "latest" + // } + // // "ghcr.io/devcontainers/features/python:1": { + // // "installTools": true, + // // "toolsToInstall": "autopep8,yapf,pydocstyle,pycodestyle,bandit,pytest,pylint", + // // "enableShared": true, + // // "installJupyterlab": true, + // // "version": "3.9" + // // }, + // // "ghcr.io/devcontainers-extra/features/act:1": { + // // "version": "latest" + // // }, + // // "ghcr.io/devcontainers-extra/features/curl-apt-get:1": {}, + // // "ghcr.io/devcontainers-extra/features/fd:1": { + // // "version": "latest" + // // }, + // // "ghcr.io/devcontainers-extra/features/fzf:1": { + // // "version": "latest" + // // }, + // // "ghcr.io/devcontainers-extra/features/ripgrep:1": { + // // "version": "latest" + // // }, + // // "ghcr.io/devcontainers-extra/features/wget-apt-get:1": {} + // }, + // Configure tool-specific properties. + "customizations": { + "vscode": { + "extensions": [ + "ms-python.python", + "ms-python.black-formatter", + "ms-python.flake8", + "dbaeumer.vscode-eslint", + "ms-python.debugpy", + "ms-toolsai.jupyter" + ], + "settings": { + "python.defaultInterpreterPath": "/opt/conda/bin/python3", + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter", + "editor.formatOnSave": true + }, + "python.formatting.provider": "black", + "python.formatting.blackPath": "/opt/conda/bin/black", + "black-formatter.path": [ + "/opt/conda/bin/black" + ] + } + } + }, + "remoteEnv": { + "PATH": "/opt/conda/bin:${containerEnv:PATH}", + "EDITOR": "/usr/bin/vim" + } + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "echo \"export PATH=$CURRENT_PYTHON_BINDIR:\\$PATH\" >> ~/.bashrc" + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..f33a02cd --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for more information: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +# https://containers.dev/guide/dependabot + +version: 2 +updates: + - package-ecosystem: "devcontainers" + directory: "/" + schedule: + interval: weekly diff --git a/hatchet/graph.py b/hatchet/graph.py index 91524d29..5555ccdc 100644 --- a/hatchet/graph.py +++ b/hatchet/graph.py @@ -3,10 +3,15 @@ # # SPDX-License-Identifier: MIT +import sys from collections import defaultdict -from collections.abc import Iterable from typing import Any, Dict, List, Optional, Set, Tuple, Union +if sys.version_info >= (3, 9): + from collections.abc import Iterable +else: + from typing import Iterable + from .node import Node, traversal_order, node_traversal_order diff --git a/hatchet/graphframe.py b/hatchet/graphframe.py index 5e1ff5e3..ffddcc8f 100644 --- a/hatchet/graphframe.py +++ b/hatchet/graphframe.py @@ -8,10 +8,14 @@ import sys import traceback from collections import defaultdict -from collections.abc import Callable, Iterable from typing import Any, Dict, List, Optional, Set, Tuple, Union, cast from io import TextIOWrapper +if sys.version_info >= (3, 9): + from collections.abc import Callable, Iterable +else: + from typing import Callable, Iterable + import multiprocess as mp import numpy as np import pandas as pd diff --git a/hatchet/node.py b/hatchet/node.py index f1205642..7c76c3c9 100644 --- a/hatchet/node.py +++ b/hatchet/node.py @@ -3,9 +3,14 @@ # # SPDX-License-Identifier: MIT +import sys from functools import total_ordering from typing import Any, Dict, List, Optional, Set, Tuple, Union -from collections.abc import Iterable + +if sys.version_info >= (3, 9): + from collections.abc import Iterable +else: + from typing import Iterable from .frame import Frame diff --git a/hatchet/query/compat.py b/hatchet/query/compat.py index a2a96d6d..8408d20b 100644 --- a/hatchet/query/compat.py +++ b/hatchet/query/compat.py @@ -7,9 +7,14 @@ import sys import warnings -from collections.abc import Callable from typing import List, Optional, Union, cast, TYPE_CHECKING +if sys.version_info >= (3, 9): + from collections.abc import Callable +else: + from typing import Callable + + from ..node import Node from .query import Query from .compound import ( diff --git a/hatchet/query/object_dialect.py b/hatchet/query/object_dialect.py index cd0ed641..9e5e120d 100644 --- a/hatchet/query/object_dialect.py +++ b/hatchet/query/object_dialect.py @@ -13,7 +13,11 @@ import re import sys from typing import Dict, List, Tuple, Union -from collections.abc import Callable, Iterable + +if sys.version_info >= (3, 9): + from collections.abc import Callable, Iterable +else: + from typing import Callable, Iterable from .errors import InvalidQueryPath, InvalidQueryFilter, MultiIndexModeMismatch from ..node import Node diff --git a/hatchet/query/query.py b/hatchet/query/query.py index d3be624e..3eb8e2ea 100644 --- a/hatchet/query/query.py +++ b/hatchet/query/query.py @@ -3,8 +3,13 @@ # # SPDX-License-Identifier: MIT +import sys from typing import List, Tuple, Union -from collections.abc import Callable, Iterator + +if sys.version_info >= (3, 9): + from collections.abc import Callable, Iterator +else: + from typing import Callable, Iterator from .errors import InvalidQueryPath diff --git a/hatchet/query/string_dialect.py b/hatchet/query/string_dialect.py index 6b5f5292..c5d90b2f 100644 --- a/hatchet/query/string_dialect.py +++ b/hatchet/query/string_dialect.py @@ -4,10 +4,9 @@ # SPDX-License-Identifier: MIT from numbers import Real -import re +import re # noqa: F401 import sys -from collections.abc import Callable -from typing import Any, Dict, Optional, List, Union, TYPE_CHECKING +from typing import Any, Dict, Optional, List, Union import pandas as pd # noqa: F401 from pandas.api.types import is_numeric_dtype, is_string_dtype # noqa: F401 import numpy as np # noqa: F401 @@ -15,6 +14,11 @@ from textx.exceptions import TextXError import warnings +if sys.version_info >= (3, 9): + from collections.abc import Callable +else: + from typing import Callable + from .errors import InvalidQueryPath, InvalidQueryFilter, RedundantQueryFilterWarning from .query import Query @@ -728,7 +732,9 @@ def _parse_num_eq(self, obj: Any) -> List[Optional[str]]: This condition will always be false. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -751,7 +757,9 @@ def _parse_num_eq(self, obj: Any) -> List[Optional[str]]: This condition will always be false. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -800,7 +808,9 @@ def _parse_num_eq_multi_idx(self, obj: Any) -> List[Optional[str]]: This condition will always be false. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -823,7 +833,9 @@ def _parse_num_eq_multi_idx(self, obj: Any) -> List[Optional[str]]: This condition will always be false. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -870,7 +882,9 @@ def _parse_num_lt(self, obj: Any) -> List[Optional[str]]: This condition will always be false. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -893,7 +907,9 @@ def _parse_num_lt(self, obj: Any) -> List[Optional[str]]: This condition will always be false. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -935,7 +951,9 @@ def _parse_num_lt_multi_idx(self, obj: Any) -> List[Optional[str]]: This condition will always be false. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -958,7 +976,9 @@ def _parse_num_lt_multi_idx(self, obj: Any) -> List[Optional[str]]: This condition will always be false. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -1005,7 +1025,9 @@ def _parse_num_gt(self, obj: Any) -> List[Optional[str]]: This condition will always be true. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -1028,7 +1050,9 @@ def _parse_num_gt(self, obj: Any) -> List[Optional[str]]: This condition will always be true. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -1070,7 +1094,9 @@ def _parse_num_gt_multi_idx(self, obj: Any) -> List[Optional[str]]: This condition will always be true. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -1093,7 +1119,9 @@ def _parse_num_gt_multi_idx(self, obj: Any) -> List[Optional[str]]: This condition will always be true. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -1140,7 +1168,9 @@ def _parse_num_lte(self, obj: Any) -> List[Optional[str]]: This condition will always be false. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -1163,7 +1193,9 @@ def _parse_num_lte(self, obj: Any) -> List[Optional[str]]: This condition will always be false. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -1205,7 +1237,9 @@ def _parse_num_lte_multi_idx(self, obj: Any) -> List[Optional[str]]: This condition will always be false. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -1228,7 +1262,9 @@ def _parse_num_lte_multi_idx(self, obj: Any) -> List[Optional[str]]: This condition will always be false. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -1275,7 +1311,9 @@ def _parse_num_gte(self, obj: Any) -> List[Optional[str]]: This condition will always be true. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -1298,7 +1336,9 @@ def _parse_num_gte(self, obj: Any) -> List[Optional[str]]: This condition will always be true. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -1340,7 +1380,9 @@ def _parse_num_gte_multi_idx(self, obj: Any) -> List[Optional[str]]: This condition will always be true. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ @@ -1363,7 +1405,9 @@ def _parse_num_gte_multi_idx(self, obj: Any) -> List[Optional[str]]: This condition will always be true. The statement that triggered this warning is: {} - """.format(obj), + """.format( + obj + ), RedundantQueryFilterWarning, ) return [ diff --git a/hatchet/readers/caliper_native_reader.py b/hatchet/readers/caliper_native_reader.py index 04ae2e63..5e2bb969 100644 --- a/hatchet/readers/caliper_native_reader.py +++ b/hatchet/readers/caliper_native_reader.py @@ -7,8 +7,13 @@ import pandas as pd import numpy as np import os +import sys from typing import Any, Dict, List, Optional, Tuple, Union, cast -from collections.abc import Callable + +if sys.version_info > (3, 9): + from collections.abc import Callable +else: + from typing import Callable import caliperreader as cr @@ -180,12 +185,9 @@ def read_metrics(self, ctx: str = "path") -> List[pd.DataFrame]: or item in self.string_attributes ): try: - node_dict[item] = ( - cast( - Callable, - self.__cali_type_dict[attr_type], - )(record[item]), - ) + node_dict[item] = cast( + Callable, self.__cali_type_dict[attr_type] + )(record[item]) if item not in self.record_data_cols: self.record_data_cols.append(item) except ValueError as e: diff --git a/hatchet/readers/caliper_reader.py b/hatchet/readers/caliper_reader.py index e8ae25f3..6c616ccd 100644 --- a/hatchet/readers/caliper_reader.py +++ b/hatchet/readers/caliper_reader.py @@ -10,9 +10,13 @@ import os import math from typing import Any, Dict, List, Union, cast -from collections.abc import Callable from io import TextIOWrapper +if sys.version_info >= (3, 9): + from collections.abc import Callable +else: + from typing import Callable + import pandas as pd import numpy as np diff --git a/hatchet/readers/hpctoolkit_reader_latest.py b/hatchet/readers/hpctoolkit_reader_latest.py index d201912b..c76065e2 100644 --- a/hatchet/readers/hpctoolkit_reader_latest.py +++ b/hatchet/readers/hpctoolkit_reader_latest.py @@ -231,7 +231,9 @@ def _store_cct_node( "node": node, "name": ( # f"{frame['type']}: {frame['name']}" - frame["name"] if frame["name"] != 1 else "entry" + frame["name"] + if frame["name"] != 1 + else "entry" ), } diff --git a/hatchet/readers/literal_reader.py b/hatchet/readers/literal_reader.py index 8f2b5f71..76dfba2e 100644 --- a/hatchet/readers/literal_reader.py +++ b/hatchet/readers/literal_reader.py @@ -3,8 +3,13 @@ # # SPDX-License-Identifier: MIT +import sys from typing import Any, Dict, List, cast -from collections.abc import Iterable + +if sys.version_info >= (3, 9): + from collections.abc import Iterable +else: + from typing import Iterable import pandas as pd diff --git a/hatchet/readers/tau_reader.py b/hatchet/readers/tau_reader.py index 8cebab25..4d50cbe4 100644 --- a/hatchet/readers/tau_reader.py +++ b/hatchet/readers/tau_reader.py @@ -6,9 +6,15 @@ import re import os import glob +import sys from typing import Any, Dict, List, Tuple, Union, cast -from collections.abc import Iterable import pandas as pd + +if sys.version_info >= (3, 9): + from collections.abc import Iterable +else: + from typing import Iterable + import hatchet.graphframe from hatchet.node import Node from hatchet.graph import Graph diff --git a/hatchet/readers/timemory_reader.py b/hatchet/readers/timemory_reader.py index cf4ec115..4628a46d 100644 --- a/hatchet/readers/timemory_reader.py +++ b/hatchet/readers/timemory_reader.py @@ -57,9 +57,9 @@ def __init__( self.include_nid = True self.multiple_ranks = False self.multiple_threads = False - self.callpath_to_node_dict: Dict[ - Tuple, Dict[str, Any] - ] = {} # (callpath, rank, thread): + self.callpath_to_node_dict: Dict[Tuple, Dict[str, Any]] = ( + {} + ) # (callpath, rank, thread): self.callpath_to_node: Dict[Tuple[str, ...], Node] = {} # (callpath): # the per_thread and per_rank settings make sure that