-
Notifications
You must be signed in to change notification settings - Fork 7
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
Create a report programmatically #334
Comments
|
Thank you for your thoughtful input. I'd like to propose some considerations to help us iterate on this design:
We should design with scalability in mind. How can we structure this to allow the Report feature to grow and evolve? Addressing only small bits of information at the Project level may limit our future options. Besides layout, a Report might include metadata like creation date, author, description, or version. It could also have methods for data processing, rendering in different formats, or integration with other systems.
A Project should have zero to many Reports. Also, I would like to add that a Report is a higher-level concept with more domain value than just a Layout. I propose renaming Layout to Report, with layout being a field within the Report object. This better reflects the domain model we're working with. |
Thanks for your response, that clears it up. A Report is clearly bigger than just a Layout. To us, Report sounds like it should be a dataclass, because it is a domain object. It should not have access to the persistence layer like class Report:
layout: Layout
def __init__(self, layout: Layout): ...
report = Report(layout=...) and then we can get/put Reports from a Project like this: class Project:
...
def put_report(self, key: str, report: Report): ...
def get_report(...): ...
def delete_report(...): ...
... And modifying the layout of a report should be done with something like: report = project.get_report(key)
report.layout = new_layout
project.put_report(key, report) or maybe like project.put_report(key, Report(layout=new_layout)) We note that in the proposal, One other thing that doesn't really make sense to us is the intent to mix Items and Reports in the same key system. For instance, what should |
Note: If it is a domain object, then the user cannot access it behind a service. Also, domain objects do not have to be dataclasses (anemic domain model), they can and should have behaviors (rich domain model). We can try your more consistent proposal, but I would like @MarieS-WiMLDS to chime her opinion.
The idea is that items, like reports are organized by the user in the same (experiments) space. Currently, the only means of organization we have is the convention of using the Thus, |
If I understand correctly where you agree already:
Now about the discussion. I like the layout aspect because it's reproducible. About the classes & methods of reports and projects. I'd like to be able to interact directly with the report object, without having to go through the project, it's more consistent with how I represent these objects in my head. A report is an object of its own, and it's weird to me to have to go through another object which has to transfer the request. Therefore, here is a possible solution: class Report:
layout: Layout
project: Project
def __init__(self, layout: Layout, project: Project): ...
def update(self, layout):
self.project.put_report() # or something similar and then we can create/update/delete Reports from a Project like this: class Project:
...
def create_report(self, key: str): ...
def get_report(...): ...
def delete_report(...): ...
# hidden method
def put_report(self, key: str, report: Report):
... And modifying the layout of a report should be done with something like: report = project.create_report(key)
report.update(layout = new_layout) How do it seems? |
This is something I forgot to ask about initially: how does project.put_report(key, Report(layout=my_layout)) |
It's completely something you can add in |
But then, according to your proposed implementation, that last snippet wouldn't work: it would need to be project.put_report(key, Report(layout=layout, project=project)) which is really weird |
Summary of conversation with @MarieS-WiMLDSA Report object should be linked to a Project at some point, and we'd rather do this once, at the Report creation ( Having to call upon Similarly, the idea that Example user flow: project = Project()
# Put some items in the project
project.put(...)
project.put(...)
# Create a Report in the UI with some key
# This will rely on `project.create_report(key)`
# Get the report to modify it from code
report = project.get_report(key)
# Change the layout of the report from code
# This automatically refreshes the UI
report.set_layout(layout) |
Given recent discussions (see 2024-09-20 workshop with Gaël), it would be good to discuss the semantic value of Reports and how it fits to avoid potential conflicts with future developments. Some facts:
So, what are our options? I can suggest several ones:
This is great to have this discussion because it shows we are gradually bringing the gap between prototyping and reporting. |
After discussion, we decide to:
@augustebaum could you please draft the latest version of the API taking in account these new elements? |
Do not to address in this PR; reflection on API design Just my feeling: @tuscland its a bit weird to me to mix items and views in the same API. I think user will be confused too. There is |
Right now I believe this is good, here's why. We should prioritize user experience. The primary goal for skore is to help DS store their results and track them. Automating view creation is secondary. If we get negative feedback (confusing API), we will address this issue. |
Addresses the backend part of #334: - Replace `Layout` by the new `View` object, a DTO containing a `Layout`. - Add `Project.put_view()` - Add `Project.get_view()` - Add `Project.delete_view()` - Add `Project.list_view_keys()` This PR does not change the skore-ui API; this will come in a future PR. --------- Co-authored-by: Thomas S. <thomas@probabl.ai>
Addresses the backend part of #334: - Replace `Layout` by the new `View` object, a DTO containing a `Layout`. - Add `Project.put_view()` - Add `Project.get_view()` - Add `Project.delete_view()` - Add `Project.list_view_keys()` This PR does not change the skore-ui API; this will come in a future PR. --------- Co-authored-by: Thomas S. <thomas@probabl.ai>
Consequently to #303 refactoring, we want to separate reports from the hierarchal organization of items, and provide storage for reports.
New Project APIs:
In the following APIs,
key
has the same value as anItem
key, i.e. the/
character is conventionnaly used as a path separator.Project.create_report(key)
Create a new report at
key
.key
already exists a warning message is logged.key
already exists, an error is raised.Report
object is returned.Project.get_report(key)
Returns the report at
key
. If the report does not exist, an error is raised. Otherwise, theReport
object is returned.Project.delete_report(key)
Deletes the report at
key
. If a report atkey
does not exists, a warning message is logged.Project.list_reports()
Returns a list of all report keys.
Report API
Report.set_layout(layout)
Sets the report layout as a list of layout objects. A layout object is a dictionary with the following key/value pairs:
key:
, the key of the item to display in the reportsize:
, the size of presented item with possible values "small", "medium", "large"Report.get_layout()
Returns the layout of the report.
Report.to_html()
Export the report as a self contained HTML document.
The text was updated successfully, but these errors were encountered: