Skip to content

Tighten up type of Deploy._process_exports#155

Open
rswarbrick wants to merge 1 commit intolowRISC:masterfrom
rswarbrick:process-exports-type
Open

Tighten up type of Deploy._process_exports#155
rswarbrick wants to merge 1 commit intolowRISC:masterfrom
rswarbrick:process-exports-type

Conversation

@rswarbrick
Copy link
Copy Markdown
Contributor

@rswarbrick rswarbrick commented Apr 2, 2026

Firstly, the stricter return type is needed because the CovMerge constructor updates self.exports (which is generated with that function). We also know the key and value types, so we may as well give them as well.

The rest of the change is more complicated and a little ugly (we're confusing Pyright on purpose!). The trick is to pass the value that we wrote to self.exports from the hjson file as an argument to _process_exports. Doing it like this avoids Pyright trying to check that the field is both a list of dictionaries and a merged dictionary.

Firstly, the stricter return type is needed because the CovMerge
constructor updates self.exports (which is generated with that
function). We also know the key and value types, so we may as well
give them as well.

The rest of the change is more complicated and a little ugly (we're
confusing Pyright on purpose!). The trick is to pass the value that we
wrote to self.exports from the hjson file as an argument to
_process_exports. Doing it like this avoids Pyright trying to check
that the field is both a list of dictionaries and a merged dictionary.

Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
exports_list: object = self.exports
if not isinstance(exports_list, list):
raise TypeError("Loaded exports value should be a list of dicts.")
self.exports: dict[str, str] = self._process_exports(exports_list)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks reasonable - below I've suggested an alternative pattern which may feel like a bit less of a dance around the type checker, but I'll leave it up to you if you prefer this or your existing solution:

def __init__(self, ...):
    self.exports: list[dict[str, str]] = []
    self.merged_exports: dict[str, str] = {}
    # ... self._define_attrs() then set_attrs, check_attrs, subst_vars, etc. ...
    self.merged_export = self._process_exports(self.exports)
    self.exports.clear()  # if we're being really paranoid about memory usage (likely unnecessary)
    # ...

def get_job_spec(self) -> "JobSpec":
    # ...
        exports=self.merged_exports,
    # ...

)

def _process_exports(self) -> Mapping:
def _process_exports(self, exports_list: list[dict[str, str]]) -> dict[str, str]:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Minor nit:

Suggested change
def _process_exports(self, exports_list: list[dict[str, str]]) -> dict[str, str]:
def _process_exports(self, exports_list: Iterable[Mapping[str, str]]) -> dict[str, str]:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants