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

events: refactor key and make the event message available to handlers #5769

Merged
merged 5 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions changes.d/5769.feat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Include task messages and workflow port as appropriate in emails configured by "mail events".
89 changes: 34 additions & 55 deletions cylc/flow/id.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
<id: w//c>
>>> Tokens(workflow='w', cycle='c')['job']

# Make a copy (note Tokens are mutable):
# Make a copy (note Tokens are immutable):
>>> tokens.duplicate()
<id: ~u/w//c/t/01>
>>> tokens.duplicate(job='02') # make changes at the same time
Expand Down Expand Up @@ -118,9 +118,10 @@
dict.__init__(self, **kwargs)

def __setitem__(self, key, value):
if key not in self._KEYS:
raise ValueError(f'Invalid token: {key}')
dict.__setitem__(self, key, value)
raise Exception('Tokens objects are not mutable')

def update(self, other):
raise Exception('Tokens objects are not mutable')

def __getitem__(self, key):
try:
Expand Down Expand Up @@ -151,6 +152,9 @@
id_ = self.id
return f'<id: {id_}>'

def __hash__(self):
return hash(tuple(self.values()))

def __eq__(self, other):
if not isinstance(other, self.__class__):
return False
Expand All @@ -159,6 +163,12 @@
for key in self._KEYS
)

def __lt__(self, other):
return self.id < other.id
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trying to figure out the utility of this beyond different cycles or submissions of the same task.. I guess I'll find out (?), maybe a requirement for use in dicts or sets?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think something was sorting tokens somewhere, possibly to get cycles/tasks in order in emails.


def __gt__(self, other):
return self.id > other.id

Check warning on line 170 in cylc/flow/id.py

View check run for this annotation

Codecov / codecov/patch

cylc/flow/id.py#L170

Added line #L170 was not covered by tests

def __ne__(self, other):
if not isinstance(other, self.__class__):
return True
Expand Down Expand Up @@ -336,62 +346,20 @@
>>> tokens = Tokens()
>>> tokens.is_null
True
>>> tokens['job_sel'] = 'x'
>>> tokens.is_null
>>> tokens.duplicate(job_sel='x').is_null
True
>>> tokens['job'] = '01'
>>> tokens.is_null
>>> tokens.duplicate(job='01').is_null
False

"""
return not any(
self[key] for key in self._REGULAR_KEYS
)

def update_tokens(
self,
tokens: 'Optional[Tokens]' = None,
**kwargs
) -> None:
"""Update the tokens dictionary.

Similar to dict.update but with an optional Tokens argument.

Examples:
>>> tokens = Tokens('x')
>>> tokens.update_tokens(workflow='y')
>>> tokens
<id: y>
>>> tokens.update_tokens(Tokens('z'))
>>> tokens
<id: z>
>>> tokens.update_tokens(Tokens('a'), cycle='b')
>>> tokens
<id: a//b>

"""
if tokens:
for key, value in tokens.items():
self[key] = value
for key, value in kwargs.items():
self[key] = value

def update(self, other):
"""dict.update.

Example:
>>> tokens = Tokens(workflow='w')
>>> tokens.update({'cycle': 'c'})
>>> tokens.id
'w//c'

"""
return self.update_tokens(**other)

def duplicate(
self,
tokens: 'Optional[Tokens]' = None,
**kwargs
*tokens_list,
**kwargs,
) -> 'Tokens':
"""Duplicate a tokens object.

Expand All @@ -408,17 +376,28 @@
>>> id(tokens1) == id(tokens2)
False

Make a copy and modify it:
Make a copy with a modification:
>>> tokens1.duplicate(cycle='1').id
'~u/w//1'

Original not changed
The Original is not changed:
>>> tokens1.id
'~u/w'

Arguments override in definition order:
>>> Tokens.duplicate(
... tokens1,
... Tokens(cycle='c', task='a', job='01'),
... task='b'
... ).id
'~u/w//c/b/01'

"""
ret = Tokens(self)
ret.update_tokens(tokens, **kwargs)
return ret
_kwargs = {}
for tokens in (self, *tokens_list):
_kwargs.update(tokens)
_kwargs.update(kwargs)
return Tokens(**_kwargs)


# //cycle[:sel][/task[:sel][/job[:sel]]]
Expand Down
8 changes: 5 additions & 3 deletions cylc/flow/id_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ async def parse_ids_async(

# infer the run number if not specified the ID (and if possible)
if infer_latest_runs:
_infer_latest_runs(*tokens_list, src_path=src_path)
_infer_latest_runs(tokens_list, src_path=src_path)

_validate_number(
*tokens_list,
Expand Down Expand Up @@ -409,12 +409,14 @@ def _validate_workflow_ids(*tokens_list, src_path):
detect_both_flow_and_suite(src_path)


def _infer_latest_runs(*tokens_list, src_path):
def _infer_latest_runs(tokens_list, src_path):
for ind, tokens in enumerate(tokens_list):
if ind == 0 and src_path:
# source workflow passed in as a path
continue
tokens['workflow'] = infer_latest_run_from_id(tokens['workflow'])
tokens_list[ind] = tokens.duplicate(
workflow=infer_latest_run_from_id(tokens['workflow'])
)
pass


Expand Down
1 change: 0 additions & 1 deletion cylc/flow/scripts/completion_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,6 @@ async def list_in_workflow(tokens: Tokens, infer_run=True) -> t.List[str]:
# list possible IDs
cli_detokenise(
tokens.duplicate(
tokens=None,
# use the workflow ID provided on the CLI to allow
# run name inference
workflow=input_workflow,
Expand Down
Loading
Loading