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

Add internal API typehints #303

Merged
merged 82 commits into from
Jun 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
a0ecd55
internal typehints batch 1
ankona Jun 6, 2023
c6d22e5
convert returncode to int type
ankona Jun 6, 2023
34b4146
omit/fix from batch 1
ankona Jun 6, 2023
66df566
typehints batch 2
ankona Jun 7, 2023
b13efc4
typehints batch 3
ankona Jun 7, 2023
2799edf
local launcher typehints
ankona Jun 7, 2023
89db941
lsf/pbs/slurm launcher typehints
ankona Jun 7, 2023
f4a07f2
error typehints
ankona Jun 7, 2023
66c86ea
typehints batch 4, generator & friends
ankona Jun 8, 2023
034a598
typehints batch 5, control, entrypoints, generator, utils
ankona Jun 8, 2023
f6c341e
jobmanager typehints
ankona Jun 8, 2023
d8d416c
job/jobmanager typehints 2
ankona Jun 8, 2023
5f9c3b7
DANGER: typehints for controller and everything it touches
ankona Jun 8, 2023
10e3db6
_core.config typehints fixes
ankona Jun 12, 2023
29ec4f5
smartsim.settings typehints
ankona Jun 12, 2023
c0d30bb
smarsim.ml.data typehints
ankona Jun 12, 2023
8066b0a
tf.data, tf.utils typehints
ankona Jun 12, 2023
7e2ba5b
ml.torch typehint start
ankona Jun 12, 2023
415dff7
_core.utils.redis type ignore
ankona Jun 12, 2023
24b6d48
ml.torch fix incorrect null check for typehinted nullable
ankona Jun 13, 2023
2d65d29
Reverse mypy config to blacklist instead of whitelist
ankona Jun 13, 2023
f74afac
undo incorrect redis conf merge
ankona Jun 13, 2023
8267319
fix t.List[ vs list[ bugs
ankona Jun 13, 2023
aebe3a1
fix another t.List issue
ankona Jun 13, 2023
e5c2682
Update changelog notes for typehints
ankona Jun 13, 2023
d94e7b0
minor fixes per review comments
ankona Jun 14, 2023
79d1fe4
comment & docstring cleanup
ankona Jun 14, 2023
6e3ca14
tighten base class / concrete class usage in Steps
ankona Jun 14, 2023
f0f1f63
Revert some optional args for consistency/clarity
ankona Jun 14, 2023
896e80d
Merge remote-tracking branch 'upstream/develop' into typehints22
ankona Jun 15, 2023
38f9217
use literal for db engine name args
ankona Jun 16, 2023
64ddd77
fix dict value typehint
ankona Jun 16, 2023
6ab6745
_core._cli, _core._install typehints
ankona Jun 16, 2023
f34bfd1
fix formatting per review
ankona Jun 16, 2023
91ac505
tweak changelog formatting to avoid bad html gen
ankona Jun 16, 2023
42a4ac9
fix unnecessary casting per review
ankona Jun 16, 2023
67744df
swap comparison operators from object to t.Any
ankona Jun 16, 2023
e0bb920
remove local launcher check from loop
ankona Jun 16, 2023
22106c6
Fix incorrect error text
ankona Jun 16, 2023
2d3153c
reduce cyclomatic complexity
ankona Jun 16, 2023
aede87e
fix version rename bug
ankona Jun 16, 2023
0d1c6b2
update incorrect docstring
ankona Jun 16, 2023
cf60661
remove extraneous null check
ankona Jun 16, 2023
3d7803b
treat job id as str
ankona Jun 16, 2023
252be6c
Fix incorrect rtype on signal handlers
ankona Jun 16, 2023
17fd40a
Remove deprecated type check
ankona Jun 16, 2023
982c3a7
fix docstring drift
ankona Jun 16, 2023
af40410
fix docstring drift
ankona Jun 16, 2023
5a53cf7
Adjust entityfiles null handling
ankona Jun 16, 2023
85f4a0a
tighten t.Any to str
ankona Jun 16, 2023
0559f53
avoid nullable return value
ankona Jun 16, 2023
a406746
tweak to return non-nullable string
ankona Jun 16, 2023
4d2995e
avoid indent, reduce cyclomatic complexity
ankona Jun 16, 2023
01fe78b
Avoid deprecated abstractproperty
ankona Jun 16, 2023
315de9b
Remove no-op __init__
ankona Jun 16, 2023
8189eac
Remove old "unassigned" default value for step_id
ankona Jun 16, 2023
e627744
formatting fix
ankona Jun 16, 2023
bb63a34
remove empty trailing comment
ankona Jun 16, 2023
09db3b1
tighten set typehint
ankona Jun 16, 2023
ea10b5b
fix formatting
ankona Jun 16, 2023
0be9bb4
avoid unnecessary t.Union
ankona Jun 16, 2023
71508c2
rename for internal method
ankona Jun 16, 2023
80f2567
fix variable re-definition
ankona Jun 20, 2023
28394e3
raise runtime error when bash not found
ankona Jun 20, 2023
0abdb5f
Add missing run_settings property
ankona Jun 20, 2023
c29ee21
Make step_settings arg non-nullable in Step init
ankona Jun 20, 2023
747d4fc
clean up _get_smartsim_status duplication, move mapping to StepInfo prop
ankona Jun 20, 2023
7e33065
narrow typehint for env dictionary
ankona Jun 20, 2023
3add880
tighten generics typehints
ankona Jun 20, 2023
0bd1097
remove unnecessary hint
ankona Jun 20, 2023
83b8680
remove extraneous coalesce
ankona Jun 20, 2023
20a3bbf
Add cluster hint back in
ankona Jun 20, 2023
c924c57
separate installation check for clarity
ankona Jun 20, 2023
8eb4392
simplify backend install check return value
ankona Jun 20, 2023
11066ba
avoid None|int|str input to `int(...)`
ankona Jun 20, 2023
529cc9d
docstring fixes
ankona Jun 20, 2023
664e676
Fix incorrect typehint on container arguments
ankona Jun 21, 2023
5710ad7
Fix bug excluding default singularity cmd string
ankona Jun 21, 2023
03192d8
Fix circular import for container
ankona Jun 21, 2023
89a1e94
Use property to avoid repetitive null checks
ankona Jun 21, 2023
f6b3586
remove unnecessary hint following isinstance
ankona Jun 21, 2023
fa9db5c
Tweak _build_run_settings_lsf for non-nullable LSF make_mpmd argument
ankona Jun 21, 2023
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
20 changes: 11 additions & 9 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,28 +34,30 @@ A full list of changes and detailed notes can be found below:
- Relax the coloredlogs version
- Update Fortran tutorials for SmartRedis
- Add support for multiple network interface binding in Orchestrator and Colocated DBs
- Add typehints and static analysis

Detailed notes

- Typehints have been added. A makefile target `make check-mypy` executes static
analysis with mypy. (PR295_, PR303_)
- Simplify code in `random_permutations` parameter generation strategy (PR300_)
- Remove wait time associated with Experiment launch summary (PR298_)
- Update Redis conf file to conform with Redis v7.0.5 conf file (PR293_)
- Migrate from redis-py-cluster to redis-py for cluster status checks (PR292_)
- Update full test suite to no longer require a tensorflow wheel to be available
at test time. (PR291_)
- Correct spelling of colocated in doc strings (PR290_)
- Deprecated launcher-specific orchestrators, constants, and ML utilities
were removed. (PR289_)
- Deprecated launcher-specific orchestrators, constants, and ML
utilities were removed. (PR289_)
- Relax the coloredlogs version to be greater than 10.0 (PR288_)
- Update the Github Actions runner image from `macos-10.15`` to `macos-12``. The
former began deprecation in May 2022 and was finally removed in May 2023. (PR285_)
- The Fortran tutorials had not been fully updated to show how to handle return/error
codes. These have now all been updated. (PR284_)
- Orchestrator and Colocated DB now accept a list of interfaces to bind to. The
argument name is still `interface` for backward compatibility reasons. (PR281_)
- Typehints have been added to public APIs. A makefile target to execute static
analysis with mypy is available `make check-mypy`. (PR295_)
former began deprecation in May 2022 and was finally removed in May 2023. (PR285_)
- The Fortran tutorials had not been fully updated to show how to handle
return/error codes. These have now all been updated. (PR284_)
- Orchestrator and Colocated DB now accept a list of interfaces to bind to. The
argument name is still `interface` for backward compatibility reasons. (PR281_)

.. _PR303: https://github.com/CrayLabs/SmartSim/pull/303
.. _PR300: https://github.com/CrayLabs/SmartSim/pull/300
.. _PR298: https://github.com/CrayLabs/SmartSim/pull/298
.. _PR293: https://github.com/CrayLabs/SmartSim/pull/293
Expand Down
34 changes: 15 additions & 19 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,25 +72,6 @@ files = [
"smartsim"
]
plugins = []
ignore_errors = true

[[tool.mypy.overrides]]
# Ignore packages that are not used or not typed
module = [
"coloredlogs",
"smartredis",
"smartredis.error"
]
ignore_missing_imports = true
ignore_errors = true

[[tool.mypy.overrides]]
module = [
"smartsim.database.*",
"smartsim.entity.*",
"smartsim.experiment"
]

ignore_errors=false

# Strict fn defs
Expand All @@ -102,3 +83,18 @@ disallow_untyped_decorators = true
# Safety/Upgrading Mypy
warn_unused_ignores = true
# warn_redundant_casts = true # not a per-module setting?

[[tool.mypy.overrides]]
# Ignore packages that are not used or not typed
module = [
"coloredlogs",
"smartredis",
"smartredis.error",
"redis.cluster",
"keras",
"torch",
"smartsim._core.launcher.step.*", # hints incomplete
ankona marked this conversation as resolved.
Show resolved Hide resolved
"smartsim.ml.torch.*", # must solve/ignore inheritance issues
]
ignore_missing_imports = true
ignore_errors = true
45 changes: 28 additions & 17 deletions smartsim/_core/_cli/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@
from pathlib import Path

import pkg_resources
import typing as t
from tabulate import tabulate

from smartsim._core._cli.utils import color_bool, pip_install
from smartsim._core._install import builder
from smartsim._core._install.buildenv import BuildEnv, SetupError, Version_, Versioner
from smartsim._core._install.buildenv import BuildEnv, SetupError, Version_, Versioner, DbEngine
from smartsim._core._install.builder import BuildError
from smartsim._core.config import CONFIG
from smartsim._core.utils.helpers import installed_redisai_backends
Expand All @@ -48,7 +49,8 @@
# may be installed into a different directory.


def _install_torch_from_pip(versions, device="cpu", verbose=False):

def _install_torch_from_pip(versions: Versioner, device: str = "cpu", verbose: bool = False) -> None:

packages = []
end_point = None
Expand Down Expand Up @@ -76,7 +78,7 @@ def _install_torch_from_pip(versions, device="cpu", verbose=False):


class Build:
def __init__(self):
def __init__(self) -> None:
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
Expand Down Expand Up @@ -154,11 +156,13 @@ def __init__(self):
else:
logger.info("Checking for build tools...")
self.build_env = BuildEnv()

if self.verbose:
logger.info("Build Environment:")
env = self.build_env.as_dict()
print(tabulate(env, headers=env.keys(), tablefmt="github"), "\n")
env_vars = list(env.keys())
print(tabulate(env, headers=env_vars, tablefmt="github"), "\n")

if self.keydb:
self.versions.REDIS = Version_("6.2.0")
self.versions.REDIS_URL = "https://github.com/EQ-Alpha/KeyDB"
Expand All @@ -170,10 +174,11 @@ def __init__(self):
)

if self.verbose:
db_name = "KEYDB" if self.keydb else "REDIS"
db_name: DbEngine = "KEYDB" if self.keydb else "REDIS"
logger.info("Version Information:")
vers = self.versions.as_dict(db_name=db_name)
print(tabulate(vers, headers=vers.keys(), tablefmt="github"), "\n")
version_names = list(vers.keys())
print(tabulate(vers, headers=version_names, tablefmt="github"), "\n")

# REDIS/KeyDB
self.build_database()
Expand Down Expand Up @@ -201,7 +206,7 @@ def __init__(self):

logger.info("SmartSim build complete!")

def build_database(self):
def build_database(self) -> None:
# check database installation
database_name = "KeyDB" if self.keydb else "Redis"
database_builder = builder.DatabaseBuilder(
Expand All @@ -218,8 +223,14 @@ def build_database(self):
logger.info(f"{database_name} build complete!")

def build_redis_ai(
self, device, torch=True, tf=True, onnx=False, torch_dir=None, libtf_dir=None
):
self,
device: str,
torch: bool = True,
tf: bool = True,
onnx: bool = False,
torch_dir: t.Union[str, Path, None] = None,
libtf_dir: t.Union[str, Path, None] = None
) -> None:

# make sure user isn't trying to do something silly on MacOS
if self.build_env.PLATFORM == "darwin" and device == "gpu":
Expand Down Expand Up @@ -268,8 +279,8 @@ def build_redis_ai(

rai_builder = builder.RedisAIBuilder(
build_env=self.build_env(),
torch_dir=str(torch_dir) if torch_dir else None,
libtf_dir=str(libtf_dir) if libtf_dir else None,
torch_dir=str(torch_dir) if torch_dir else "",
libtf_dir=str(libtf_dir) if libtf_dir else "",
build_torch=torch,
build_tf=tf,
build_onnx=onnx,
Expand Down Expand Up @@ -313,14 +324,14 @@ def build_redis_ai(
)
logger.info("ML Backends and RedisAI build complete!")

def infer_torch_device(self):
def infer_torch_device(self) -> str:
backend_torch_path = f"{CONFIG.lib_path}/backends/redisai_torch"
device = "cpu"
if Path(f"{backend_torch_path}/lib/libtorch_cuda.so").is_file():
device = "gpu"
return device

def install_torch(self, device="cpu"):
def install_torch(self, device: str = "cpu") -> None:
"""Torch shared libraries installed by pip are used in the build
for SmartSim backends so we download them here.
"""
Expand Down Expand Up @@ -353,7 +364,7 @@ def install_torch(self, device="cpu"):
logger.error(msg) # error because this is usually fatal
logger.info(f"Torch {self.versions.TORCH} installed in Python environment")

def check_onnx_install(self):
def check_onnx_install(self) -> None:
"""Check Python environment for ONNX installation"""
if not self.versions.ONNX:
py_version = sys.version_info
Expand All @@ -380,7 +391,7 @@ def check_onnx_install(self):
except SetupError as e:
logger.warning(str(e))

def check_tf_install(self):
def check_tf_install(self) -> None:
"""Check Python environment for TensorFlow installation"""

try:
Expand All @@ -399,7 +410,7 @@ def check_tf_install(self):
except SetupError as e:
logger.warning(str(e))

def check_backends_install(self):
def check_backends_install(self) -> None:
"""Checks if backends have already been installed.
Logs details on how to proceed forward
if the RAI_PATH environment variable is set or if
Expand Down
4 changes: 2 additions & 2 deletions smartsim/_core/_cli/clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@


class Clean:
def __init__(self, clean_all=False):
def __init__(self, clean_all: bool = False) -> None:
parser = argparse.ArgumentParser(
description="Remove previous ML runtime installation"
)
Expand All @@ -52,7 +52,7 @@ def __init__(self, clean_all=False):
clobber = args.clobber or clean_all
self.clean(_all=clobber)

def clean(self, _all=False):
def clean(self, _all: bool = False) -> None:
"""Remove pre existing installations of ML runtimes

:param _all: Remove all non-python dependencies
Expand Down
16 changes: 8 additions & 8 deletions smartsim/_core/_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
from smartsim._core._cli.utils import get_install_path


def _usage():
def _usage() -> str:
usage = [
"smart <command> [<args>]\n",
"Commands:",
Expand All @@ -49,7 +49,7 @@ def _usage():


class SmartCli:
def __init__(self):
def __init__(self) -> None:
parser = argparse.ArgumentParser(
description="SmartSim command line interface", usage=_usage()
)
Expand All @@ -67,23 +67,23 @@ def __init__(self):
sys.exit(0)
getattr(self, args.command)()

def build(self):
def build(self) -> None:
Build()
sys.exit(0)

def clean(self):
def clean(self) -> None:
Clean()
sys.exit(0)

def clobber(self):
def clobber(self) -> None:
Clean(clean_all=True)
sys.exit(0)

def site(self):
def site(self) -> None:
print(get_install_path())
sys.exit(0)

def dbcli(self):
def dbcli(self) -> None:
bin_path = get_install_path() / "_core" / "bin"
for option in bin_path.iterdir():
if option.name in ("redis-cli", "keydb-cli"):
Expand All @@ -93,5 +93,5 @@ def dbcli(self):
sys.exit(1)


def main():
def main() -> None:
SmartCli()
19 changes: 10 additions & 9 deletions smartsim/_core/_cli/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import subprocess
import typing as t
from pathlib import Path

from smartsim._core._install.buildenv import SetupError
Expand All @@ -36,7 +37,7 @@
logger = get_logger("Smart", fmt=smart_logger_format)


def get_install_path():
def get_install_path() -> Path:
try:
import smartsim as _
except (ImportError, ModuleNotFoundError):
Expand All @@ -50,27 +51,27 @@ def get_install_path():
return package_path


def color_bool(trigger=True):
def color_bool(trigger: bool = True) -> str:
_color = "green" if trigger else "red"
return colorize(str(trigger), color=_color)


def pip_install(packages, end_point=None, verbose=False):
def pip_install(packages: t.List[str], end_point: t.Optional[str] = None, verbose: bool = False) -> None:
"""Install a pip package to be used in the SmartSim build
Currently only Torch shared libraries are re-used for the build
"""
# form pip install command
cmd = ["python", "-m", "pip", "install"]
cmd.extend(packages)
if end_point:
packages.append(f"-f {end_point}")
packages = " ".join(packages)
cmd.extend(["-f", end_point])

# form pip install command
cmd = ["python", "-m", "pip", "install", packages]
cmd = " ".join(cmd)
cmd_arg = " ".join(cmd)

if verbose:
logger.info(f"Installing packages {packages}...")
proc = subprocess.Popen(
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
cmd_arg, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
_, err = proc.communicate()
returncode = int(proc.returncode)
Expand Down
Loading