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

Type hinting and misc changes #417

Merged
merged 26 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b62be29
sles15 is now default platform, added to docs reflecting this and oth…
mranst Sep 11, 2024
c2a77f4
swell_static_files_user in config now used in appropriate tasks (#360)
mranst Sep 11, 2024
f9b50f2
addressed potential error on abort caused by undefined logger call
mranst Sep 11, 2024
ccb93d6
renamed datetime utility to avoid hinting confusion with base package…
mranst Sep 11, 2024
d03c7ed
type hinting for all python methods (#349)
mranst Sep 11, 2024
99b5f6d
removed unnecessary pass of logger to functions copy_platform_files a…
mranst Sep 13, 2024
e277b8a
type hinting in run_geos_executable uses Optional
mranst Sep 13, 2024
5b000ff
Hinting changes, Logger properly type hinted, pd.DataFrame now used, …
mranst Sep 13, 2024
dc846ce
Update docs/configuring_cylc.md
mranst Sep 13, 2024
ee9852b
added proper hinting for SilentUndefined instance in jinja2.py
mranst Sep 13, 2024
3fab899
proper syntax for linking docs
mranst Sep 13, 2024
69a7d6d
Merge remote-tracking branch 'refs/remotes/origin/hinting-misc' into …
mranst Sep 13, 2024
a8ff454
direct type hinting for FileHandler objects
mranst Sep 13, 2024
a7655d1
added Optional typing where appropriate
mranst Sep 13, 2024
5f93e20
added missing type hint in run_jedi_hofx_executable.py, fixed missing…
mranst Sep 13, 2024
2895e5e
Merge branch 'GEOS-ESM:develop' into hinting-misc
mranst Sep 13, 2024
256595d
more types in hint
mranst Sep 13, 2024
27ad6ce
more precise type hinting
mranst Sep 13, 2024
4ff8fe8
Merge remote-tracking branch 'refs/remotes/origin/hinting-misc' into …
mranst Sep 13, 2024
ba8b009
Resolved code test error
mranst Sep 13, 2024
e4d5cf1
more specific type hinting per mypy
mranst Sep 16, 2024
50bd771
corrected logger instance in type hint
mranst Sep 16, 2024
812990d
Revised type hinting
mranst Sep 16, 2024
c109c28
Revised datetime typing, other refinements
mranst Sep 16, 2024
f4903b4
Further revised type hinting
mranst Sep 17, 2024
5173bcb
Update src/swell/utilities/render_jedi_interface_files.py
mranst Sep 17, 2024
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
2 changes: 2 additions & 0 deletions docs/configuring_cylc.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ Additionally `cylc` uses a file called `$HOME/.cylc/flow/global.cylc` to control
**WARNING:**
The contents of the above two files will be platform specific.
---

See [Configuring Cylc Discover](platforms/configuring_cylc_discover.md) for instructions on configuring cylc for Discover.
4 changes: 2 additions & 2 deletions docs/examples/description.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ experiment_id: {suite_name}-suite
```

`swell create` also contains argument inputs. For instance, `-p` or `--platform` allows
user to pick which platform they would like to run on.
user to pick which platform they would like to run on. If unspecified, swell will run on SLES15 by default.

```bash
swell create 3dvar -p nccs_discover_sles15
Expand Down Expand Up @@ -113,4 +113,4 @@ dependencies. For each suite, this will have a different structure and different

`experiment.yaml`: This is the key configuration file that dictates the inputs for contain configuration variables that will be used for different scripts in the workflow.

For each JEDI bundle type (i.e., fv3-jedi, soca) and suite (3dvar, hofx etc.) in this section, we will display the `experiment.yaml` and talk about details.
For each JEDI bundle type (i.e., fv3-jedi, soca) and suite (3dvar, hofx etc.) in this section, we will display the `experiment.yaml` and talk about details.
4 changes: 3 additions & 1 deletion docs/installing_swell.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,6 @@ cd swell
pip install --prefix=/path/to/install/swell/ .
```

To make the software useable ensure `/path/to/install/swell/bin` is in the `$PATH`. Also ensure that `/path/to/install/swell/lib/python<version>/site-packages` is in the `$PYTHONPATH`, where `<version>` denotes the version of Python used for the install, e.g. `3.9`.
To make the software usable ensure `/path/to/install/swell/bin` is in the `$PATH`. Also ensure that `/path/to/install/swell/lib/python<version>/site-packages` is in the `$PYTHONPATH`, where `<version>` denotes the version of Python used for the install, e.g. `3.9`.

Swell makes use of additional packages which are located in shared directories on Discover, such as under `/discover/nobackup/projects/gmao`. When installed correctly, many of these libraries should be visible in the `$PYTHONPATH`.
61 changes: 51 additions & 10 deletions src/swell/deployment/create_experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import shutil
import sys
import yaml
from typing import Union, Optional

from swell.deployment.prepare_config_and_suite.prepare_config_and_suite import \
PrepareExperimentConfigAndSuite
Expand All @@ -27,8 +28,13 @@
# --------------------------------------------------------------------------------------------------


def clone_config(configuration, experiment_id, method, platform, advanced):

def clone_config(
configuration: str,
experiment_id: str,
method: str,
platform: str,
advanced: bool
) -> str:
# Create a logger
logger = Logger('SwellCloneExperiment')

Expand Down Expand Up @@ -59,7 +65,14 @@ def clone_config(configuration, experiment_id, method, platform, advanced):
# --------------------------------------------------------------------------------------------------


def prepare_config(suite, method, platform, override, advanced, slurm):
def prepare_config(
suite: str,
method: str,
platform: str,
override: Union[dict, str, None],
advanced: bool,
slurm: str
) -> str:

# Create a logger
# ---------------
Expand Down Expand Up @@ -136,13 +149,21 @@ def prepare_config(suite, method, platform, override, advanced, slurm):

# Return path to dictionary file
# ------------------------------

return experiment_dict_string_comments


# --------------------------------------------------------------------------------------------------


def create_experiment_directory(suite, method, platform, override, advanced, slurm):
def create_experiment_directory(
suite: str,
method: str,
platform: str,
override: str,
advanced: bool,
slurm: Optional[str]
) -> None:

# Create a logger
# ---------------
Expand Down Expand Up @@ -190,7 +211,7 @@ def create_experiment_directory(suite, method, platform, override, advanced, slu
copy_platform_files(logger, exp_suite_path, platform)

if os.path.exists(os.path.join(swell_suite_path, 'eva')):
copy_eva_files(logger, swell_suite_path, exp_suite_path)
copy_eva_files(swell_suite_path, exp_suite_path)

# Set the swell paths in the modules file and create csh versions
# ---------------------------------------------------------------
Expand All @@ -217,7 +238,10 @@ def create_experiment_directory(suite, method, platform, override, advanced, slu
# --------------------------------------------------------------------------------------------------


def copy_eva_files(logger, swell_suite_path, exp_suite_path):
def copy_eva_files(
swell_suite_path: str,
exp_suite_path: str
) -> None:

# Repo eva files
eva_directory = os.path.join(swell_suite_path, 'eva')
Expand All @@ -236,7 +260,11 @@ def copy_eva_files(logger, swell_suite_path, exp_suite_path):
# --------------------------------------------------------------------------------------------------


def copy_platform_files(logger, exp_suite_path, platform=None):
def copy_platform_files(
logger: Logger,
exp_suite_path: str,
platform: Optional[str] = None
) -> None:

# Copy platform related files to the suite directory
# --------------------------------------------------
Expand All @@ -256,7 +284,11 @@ def copy_platform_files(logger, exp_suite_path, platform=None):
# --------------------------------------------------------------------------------------------------


def template_modules_file(logger, experiment_dict, exp_suite_path):
def template_modules_file(
logger: Logger,
experiment_dict: dict,
exp_suite_path: str
) -> None:

# Modules file
# ------------
Expand Down Expand Up @@ -309,7 +341,10 @@ def template_modules_file(logger, experiment_dict, exp_suite_path):
# --------------------------------------------------------------------------------------------------


def create_modules_csh(logger, exp_suite_path):
def create_modules_csh(
logger: Logger,
exp_suite_path: str
) -> None:

# Modules file
# ------------
Expand Down Expand Up @@ -357,7 +392,13 @@ def create_modules_csh(logger, exp_suite_path):
# --------------------------------------------------------------------------------------------------


def prepare_cylc_suite_jinja2(logger, swell_suite_path, exp_suite_path, experiment_dict, platform):
def prepare_cylc_suite_jinja2(
logger: Logger,
swell_suite_path: str,
exp_suite_path: str,
experiment_dict: dict,
platform: str
) -> None:

# Open suite file from swell
# --------------------------
Expand Down
16 changes: 13 additions & 3 deletions src/swell/deployment/launch_experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,13 @@

class DeployWorkflow():

def __init__(self, suite_path, experiment_name, no_detach, log_path):
def __init__(
self,
suite_path: str,
experiment_name: str,
no_detach: bool,
log_path: str
) -> None:

self.logger = Logger('DeployWorkflow')
self.suite_path = suite_path
Expand All @@ -29,7 +35,7 @@ def __init__(self, suite_path, experiment_name, no_detach, log_path):

# ----------------------------------------------------------------------------------------------

def cylc_run_experiment(self): # NB: Could be a factory based on workflow_manager
def cylc_run_experiment(self) -> None: # NB: Could be a factory based on workflow_manager

# Move to the suite path
os.chdir(self.suite_path)
Expand Down Expand Up @@ -93,7 +99,11 @@ def cylc_run_experiment(self): # NB: Could be a factory based on workflow_manag
# --------------------------------------------------------------------------------------------------


def launch_experiment(suite_path, no_detach, log_path):
def launch_experiment(
suite_path: str,
no_detach: bool,
log_path: str
) -> None:

# Get the path to where the suite files are located
# -------------------------------------------------
Expand Down
6 changes: 3 additions & 3 deletions src/swell/deployment/platforms/platforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
# --------------------------------------------------------------------------------------------------


def platform_path():
def platform_path() -> str:

return os.path.join(get_swell_path(), 'deployment', 'platforms')


# --------------------------------------------------------------------------------------------------


def get_platforms():
def get_platforms() -> list:

# Get list of supported platforms
platforms = [dir for dir in os.listdir(platform_path())
Expand All @@ -41,7 +41,7 @@ def get_platforms():
# --------------------------------------------------------------------------------------------------


def login_or_compute(platform):
def login_or_compute(platform) -> str:

# Open the properties file
properties_file = os.path.join(platform_path(), 'properties.yaml')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import re
import sys
from typing import Union

import questionary
from questionary import Choice
Expand All @@ -20,7 +21,7 @@

class GetAnswerCli:

def get_answer(self, key, val):
def get_answer(self, key: str, val: dict) -> str:
# Set questionary variable
widget_type = val['type']
quest = val['prompt']
Expand Down Expand Up @@ -60,14 +61,14 @@ def get_answer(self, key, val):

# ----------------------------------------------------------------------------------------------

def make_string_widget(self, quest, default, prompt):
def make_string_widget(self, quest: str, default: str, prompt: questionary.text) -> str:
answer = prompt(f"{quest} [{default}]", default=default).ask()

return answer

# ----------------------------------------------------------------------------------------------

def make_int_widget(self, quest, default, prompt):
def make_int_widget(self, quest: str, default: str, prompt: questionary.text) -> str:
default = str(default)
answer = prompt(f"{quest} [{default}]",
validate=lambda text: True if text.isdigit()
Expand All @@ -78,7 +79,12 @@ def make_int_widget(self, quest, default, prompt):

# ----------------------------------------------------------------------------------------------

def make_float_widget(self, quest, default, prompt):
def make_float_widget(
self,
quest: str,
default: str,
prompt: questionary.text
) -> str:
default = str(default)
answer = prompt(f"{quest} [{default}]",
validate=lambda text: True if text.isdigit()
Expand All @@ -89,7 +95,15 @@ def make_float_widget(self, quest, default, prompt):

# ----------------------------------------------------------------------------------------------

def make_drop_widget(self, method, quest, options, default, prompt):
def make_drop_widget(
self,
method: str,
quest: str,
options: list,
default: str,
prompt: questionary.text
) -> Union[str, list]:

default = str(default)
choices = [str(x) for x in options]
answer = prompt(quest, choices=choices, default=default).ask()
Expand All @@ -98,14 +112,25 @@ def make_drop_widget(self, method, quest, options, default, prompt):

# ----------------------------------------------------------------------------------------------

def make_boolean(self, quest, default, prompt):
def make_boolean(
self,
quest: str,
default: str,
prompt: questionary.text
) -> str:

answer = prompt(quest, default=default, auto_enter=False).ask()

return answer

# ----------------------------------------------------------------------------------------------

def make_datetime(self, quest, default, prompt):
def make_datetime(
self,
quest: str,
default: str,
prompt: questionary.text
) -> str:

class dtValidator(questionary.Validator):
def validate(self, document):
Expand All @@ -124,7 +149,12 @@ def validate(self, document):

# ----------------------------------------------------------------------------------------------

def make_duration(self, quest, default, prompt):
def make_duration(
self,
quest: str,
default: str,
prompt: questionary.text
) -> str:

class durValidator(questionary.Validator):
def validate(self, document):
Expand Down Expand Up @@ -157,7 +187,14 @@ def validate(self, document):

# ----------------------------------------------------------------------------------------------

def make_check_widget(self, quest, options, default, prompt):
def make_check_widget(
self,
quest: str,
options: list,
default: Union[str, list],
prompt: questionary.text
) -> str:

choices = options.copy()

if isinstance(default, list):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@
# --------------------------------------------------------------------------------------------------


from typing import Union
from datetime import datetime as dt


class GetAnswerDefaults:

def get_answer(self, key, val):
def get_answer(self, key: str, val: dict) -> Union[int, float, str, dt]:
return val['default_value']

# --------------------------------------------------------------------------------------------------
Loading
Loading