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

Provide support for dynamically generated classes and __init__ options for IDE autocompletion, etc #1548

Open
lbianchi-lbl opened this issue Dec 12, 2024 · 2 comments
Assignees
Labels
Priority:Normal Normal Priority Issue or PR

Comments

@lbianchi-lbl
Copy link
Contributor

  • The way ProcessBlock subclasses are dynamically created through the @declare_process_block_class decorator is not compatible with tools that rely on static analysis of the code
  • This includes pylint, which prompted my initial analysis of the problem (see FIXME for details), and ultimately required the creation of a (fairly complex) pylint plugin
  • This also includes code IDEs, which severely limits the hints that can be provided to the user, in turn limiting the usability of IDAES as a platform
  • Changing the current API to one that's more friendly to static analysis is not a viable option because of backward compatibility concerns and the amount of effort it would require
  • To address this, I'm currently investigating a solutions based on type stub files (.pyi), which are companion files distributed alongside the code that allow providing type annotation information without modifying the actual code
@lbianchi-lbl lbianchi-lbl self-assigned this Dec 12, 2024
@ksbeattie ksbeattie added the Priority:Normal Normal Priority Issue or PR label Dec 12, 2024
@aspitarl
Copy link

There is a similar issue with pandas/xarray accessor methods and IDE autocomplete. Finding out about stubs led me to this recent package which solves that issue for xarray: https://pypi.org/project/accessor-stubs/. The project description gives a good overview of the problem. It fixed my autocomplete issue by overwriting the .pyi files in a package xarray-stubs in my virtual environment (thanks for the tip!)

Perhaps a similar solution could autogenerate the ProcessBlock stubs. I think it is a similar problem, as xarray accessors are defined using decorators. Though it looks as if there is a more generalized stub generation tool built into mypy.

@aspitarl
Copy link

I worked on this a bit and was able to improve the autocompletion in my own project. Here's what I learned in case it is useful.

I have a local package tsm (thermal storage media) of idaes models with a structure similar to idaes.models_extra . I was able to use mypy stubgen to go through this folder and generate stubs for all of my files into a local stubs directory. I get files containing something like:

---stubs/tsm/flowsheets/sens_ess.pyi---

class SensibleSystemFlowsheetData(FlowsheetBlockData):
    SM: SensibleSM

This does not work for the normal reasons above. I tried doing some find and replace to remove the 'Data' from the end, but this would not work for 'go to definition' as there is no tie to the original code. but I found adding a line like this above the class declaration worked well:

---stubs/tsm/flowsheets/sens_ess.pyi---

SensibleSystemFlowsheet = SensibleSystemFlowsheetData

class SensibleSystemFlowsheetData(FlowsheetBlockData):
    SM: SensibleSM

I am doing this with a shell script and sed, let me know if sharing that would be helpful.

When creating an instance like fs = SensibleSystemFlowsheet() both autocomplete and 'go to definition' work well, at least in my local package for which the stubs were generated. I could get farther and into the top level of idaes classes by adding type definitions to my class defnitions. for example:

---tsm/flowsheets/sens_ess.py---

@declare_process_block_class("SensibleSystemFlowsheet")
class SensibleSystemFlowsheetData(FlowsheetBlockData):
    SM: SensibleSM
    feed: unit_models.feed.FeedData
    compressor: unit_models.pressure_changer.CompressorData
    turbine: unit_models.pressure_changer.TurbineData
    product: unit_models.product.ProductData

This allows for access to, for example, m.fs.compressor.efficiency_isentropic but not m.fs.compressor.inlet. I think to get 'further in' stubs will have to be generated for idaes itself. In any case this is already a significant improvement for navigating around in my own custom models.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Priority:Normal Normal Priority Issue or PR
Projects
None yet
Development

No branches or pull requests

3 participants