Skip to content

Feat: Added Model sharing through links #2727

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Sahil-Chhoker
Copy link
Collaborator

@Sahil-Chhoker Sahil-Chhoker commented Mar 18, 2025

Summary

This PR provides a basic model sharing through a button on the solara web-interface. It uses PyCafe to generate links.

Motive

As explained in #2724. Closes #2724.

Implementation

A new module named model_share.py is added to mesa that handles the link generating and a new button labeled "Open on PyCafe" on the solara's AppBar, that redirects to the generated link that contains all the files your model uses. Strict naming convention is followed for autodetection i.e. model.py, agents.py and app.py.

image

Additional Notes

There are many uncertainties and assumptions in this implementation like the button only works if you are present in that directory and I am unsure about if this is even the correct approach to handle this. But having a draft to work with will make things easier that's why this PR is opened. Please list your opinions.

Summary by CodeRabbit

  • New Features
    • Introduced functionality to generate a shareable link for your Python code and its dependencies, with options to customize included files.
    • Added an "Open on PyCafe" button to the visualization interface, which opens the generated link in a new browser tab.

Copy link

Performance benchmarks:

Model Size Init time [95% CI] Run time [95% CI]
BoltzmannWealth small 🔵 -0.5% [-1.1%, +0.1%] 🔵 -0.7% [-0.9%, -0.5%]
BoltzmannWealth large 🔵 -0.7% [-1.7%, +0.1%] 🔵 -1.2% [-2.2%, -0.3%]
Schelling small 🔵 -0.1% [-0.3%, +0.0%] 🔵 -0.3% [-0.4%, -0.2%]
Schelling large 🔵 -0.0% [-0.4%, +0.3%] 🔵 -2.2% [-3.0%, -1.5%]
WolfSheep small 🔵 -0.6% [-1.0%, -0.3%] 🔵 -0.2% [-0.4%, -0.0%]
WolfSheep large 🔵 -1.0% [-1.3%, -0.7%] 🔵 -0.3% [-0.7%, +0.2%]
BoidFlockers small 🔵 -0.4% [-1.1%, +0.3%] 🔵 -1.5% [-1.6%, -1.3%]
BoidFlockers large 🔵 -0.5% [-0.9%, -0.1%] 🔵 -1.2% [-1.6%, -0.9%]

Copy link
Member

@EwoutH EwoutH left a comment

Choose a reason for hiding this comment

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

Wow this is really cool! Can we also add this button to our Readthedocs examples?

I think this is worth experimenting this, so green checkmark from me. I will leave the merge to another maintainer.

Copy link
Member

Choose a reason for hiding this comment

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

Is this the most logical place for this file? (also looking at my co-maintainers)

@EwoutH EwoutH added the feature Release notes label label Mar 22, 2025
@tpike3
Copy link
Member

tpike3 commented Mar 23, 2025

@Sahil-Chhoker This is very cool!

My initial thoughts, to which I am not tied) would be

  • Make it a "Share with PYCAFE" (Thinking is for those that dont know py.cafe it gives a more obvious use of the button)
  • With the uncertainties I would not make it a default button, we dont want a users visualization to break for a feature they may not want. We should advertise though, so would need to add it to the visualization tutorial and default on all examples. Maybe a Boolean kwarg?
  • With the regards to the location, I am thinking in the docs. This is about sharing Mesa/ models/ approaches which is effectively what the docs does, but can go either way

Regardless, this is a great idea and feature!

@Sahil-Chhoker
Copy link
Collaborator Author

Thanks for your reply @tpike3

  • Make it a "Share with PYCAFE" (Thinking is for those that dont know py.cafe it gives a more obvious use of the button)

Makes sense, will do!

  • With the uncertainties I would not make it a default button, we dont want a users visualization to break for a feature they may not want. We should advertise though, so would need to add it to the visualization tutorial and default on all examples. Maybe a Boolean kwarg?

It makes sense to not make it a default button, but some things I want to clear are that the viz. won't break even if the button does not work as expected, in such case on clicking on the button an empty solara pycafe project opens.
And another thing I want to propose is that we should have a shared account on PyCafe for Mesa, and we can host every example in the main repo their and add their respective links. Since the button functionality works great when you are in the current working directory, it can be a user only button (if this even makes any sense).

  • With the regards to the location, I am thinking in the docs. This is about sharing Mesa/ models/ approaches which is effectively what the docs does, but can go either way

Makes sense, will do!

Copy link

coderabbitai bot commented Apr 4, 2025

Walkthrough

The changes introduce a new module in mesa/model_share.py that provides shareable link generation for Python code and its dependencies via the py.cafe service. The module defines the get_pycafe_link function, which builds a JSON object from provided files, requirements, and optionally autodetected Python files, compresses and encodes this data, and returns a URL. Additionally, the mesa/visualization/solara_viz.py file now features an "Open on PyCafe" button that utilizes this function to generate and open the shareable link in a new browser tab.

Changes

File(s) Changed Change Summary
mesa/model_share.py Added new module with get_pycafe_link and _scan_python_files functions to generate shareable PyCafe links for code and dependencies.
mesa/visualization/solara_viz.py Integrated a new "Open on PyCafe" button in the UI that calls get_pycafe_link to generate a shareable link and opens it in a new browser tab.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant V as SolaraViz Component
    participant M as model_share Module

    U->>V: Click "Open on PyCafe" button
    V->>M: Call get_pycafe_link(files, requirements, autodetect)
    M-->>V: Return PyCafe URL
    V->>U: Open URL in new browser tab
Loading

Assessment against linked issues

Objective Addressed Explanation
Sharing of Models through links (#2724)

Poem

I'm just a bunny with a joyful hop,
Hop-skipping code where the ideas never stop.
I crafted a link that makes sharing so grand,
Hop into py.cafe with a gentle command.
Cheers from my fluffy ears to your clever command!

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Sahil-Chhoker
Copy link
Collaborator Author

Sahil-Chhoker commented Apr 4, 2025

@coderabbitai full review

Copy link

coderabbitai bot commented Apr 4, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

coderabbitai bot commented Apr 4, 2025

✅ Actions performed

Full review triggered.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
mesa/visualization/solara_viz.py (1)

134-141: Button functionality looks good, consider renaming for clarity

The implementation of the "Open on PyCafe" button is properly integrated into the AppBar and correctly uses the get_pycafe_link function with autodetect_files=True. The button styling and target="_blank" attribute ensure a good user experience.

Based on the PR comments, consider renaming this to "Share with PYCAFE" as suggested by reviewer tpike3 to make its purpose clearer for users unfamiliar with PyCafe.

 solara.Button(
-            label="Open on PyCafe",
+            label="Share with PYCAFE",
             color="blue",
             attributes={
                 "href": get_pycafe_link(autodetect_files=True),
                 "target": "_blank",
             },
         )
mesa/model_share.py (2)

77-87: Consider enhancing _scan_python_files function

The _scan_python_files function is currently limited to specific filenames in the current directory. Consider enhancing it to:

  1. Support recursive directory scanning (Python modules can be in subdirectories)
  2. Allow customizing the list of file patterns to scan
-def _scan_python_files(directory_path: str = ".") -> list[str]:
-    """Scan a directory for specific Python files (model.py, app.py, agents.py)."""
-    path = Path(directory_path)
-    python_files = [
-        str(file)
-        for file in path.glob("*.py")
-        if file.name in ["model.py", "app.py", "agents.py"]
-    ]
-
-    return python_files
+def _scan_python_files(directory_path: str = ".", 
+                       file_patterns: list[str] = None, 
+                       recursive: bool = False) -> list[str]:
+    """Scan a directory for specific Python files.
+    
+    Args:
+        directory_path: Path to the directory to scan
+        file_patterns: List of filename patterns to include (defaults to model.py, app.py, agents.py)
+        recursive: Whether to scan subdirectories recursively
+        
+    Returns:
+        List of Python file paths matching the patterns
+    """
+    path = Path(directory_path)
+    if file_patterns is None:
+        file_patterns = ["model.py", "app.py", "agents.py"]
+        
+    pattern = "**/*.py" if recursive else "*.py"
+    python_files = [
+        str(file)
+        for file in path.glob(pattern)
+        if file.name in file_patterns
+    ]
+
+    return python_files

1-87: Add unit tests for the new model_share module

The static analysis shows that many lines in this file aren't covered by tests. It's important to add comprehensive unit tests for this functionality to ensure it works correctly and prevent regressions in the future.

Test cases should cover:

  1. Basic functionality with manually specified files
  2. Auto-detection of files
  3. Error handling (missing files, invalid parameters)
  4. URL generation with different types of input

Consider using mocking to test file operations without depending on actual files.

Would you like me to help create a basic test file structure for this module?

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 47-47: mesa/model_share.py#L47
Added line #L47 was not covered by tests


[warning] 49-49: mesa/model_share.py#L49
Added line #L49 was not covered by tests


[warning] 51-54: mesa/model_share.py#L51-L54
Added lines #L51 - L54 were not covered by tests


[warning] 57-58: mesa/model_share.py#L57-L58
Added lines #L57 - L58 were not covered by tests


[warning] 60-60: mesa/model_share.py#L60
Added line #L60 was not covered by tests


[warning] 62-63: mesa/model_share.py#L62-L63
Added lines #L62 - L63 were not covered by tests

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5166670 and e6df076.

📒 Files selected for processing (2)
  • mesa/model_share.py (1 hunks)
  • mesa/visualization/solara_viz.py (2 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
mesa/visualization/solara_viz.py (1)
mesa/model_share.py (1)
  • get_pycafe_link (11-74)
🪛 GitHub Check: codecov/patch
mesa/model_share.py

[warning] 47-47: mesa/model_share.py#L47
Added line #L47 was not covered by tests


[warning] 49-49: mesa/model_share.py#L49
Added line #L49 was not covered by tests


[warning] 51-54: mesa/model_share.py#L51-L54
Added lines #L51 - L54 were not covered by tests


[warning] 57-58: mesa/model_share.py#L57-L58
Added lines #L57 - L58 were not covered by tests


[warning] 60-60: mesa/model_share.py#L60
Added line #L60 was not covered by tests


[warning] 62-63: mesa/model_share.py#L62-L63
Added lines #L62 - L63 were not covered by tests

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build (windows, 3.13)
🔇 Additional comments (2)
mesa/model_share.py (2)

11-36: Function signature and documentation look good

The function signature with optional parameters and clear type hints is well designed. The docstrings follow a good format with proper description, arguments explanation, examples, and return value description.


65-74: JSON encoding looks well implemented

The JSON encoding, compression, and URL creation logic is appropriately implemented using standard libraries. The compression with gzip and base64 encoding is a good practice to shorten the URL while maintaining the data integrity.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (1)
mesa/model_share.py (1)

1-87: 💡 Verification agent

🧩 Analysis chain

Add unit tests to improve code coverage.

The static analysis shows several uncovered lines in this module. Adding unit tests would improve reliability and prevent regressions.


🏁 Script executed:

#!/bin/bash
# Check for existing test files that might be related to model_share.py

echo "Checking for existing test files for model_share.py:"
fd -t f "test_.*model_share.*\.py" || echo "No existing test files found"

echo -e "\nChecking Mesa test structure:"
fd -t f "test_.*\.py" . -d 1 | head -n 5

Length of output: 269


Action Required: Add Unit Tests for mesa/model_share.py

The static analysis confirms that there are no existing unit tests covering this module. To improve code coverage and prevent regressions, please add tests that verify:

  • The behavior of get_pycafe_link in both scenarios:
    • When file paths are provided via the files parameter.
    • When using autodetection with autodetect_files=True.
  • The functionality of _scan_python_files, ensuring it correctly filters for "model.py", "app.py", and "agents.py".

Adding these tests will help ensure that key code paths are exercised and improve overall reliability.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 47-47: mesa/model_share.py#L47
Added line #L47 was not covered by tests


[warning] 49-49: mesa/model_share.py#L49
Added line #L49 was not covered by tests


[warning] 51-54: mesa/model_share.py#L51-L54
Added lines #L51 - L54 were not covered by tests


[warning] 57-58: mesa/model_share.py#L57-L58
Added lines #L57 - L58 were not covered by tests


[warning] 60-60: mesa/model_share.py#L60
Added line #L60 was not covered by tests


[warning] 62-63: mesa/model_share.py#L62-L63
Added lines #L62 - L63 were not covered by tests

♻️ Duplicate comments (2)
mesa/model_share.py (2)

37-43: 🛠️ Refactor suggestion

Add parameter validation to prevent conflicting options.

The function currently doesn't validate that files and autodetect_files aren't both specified, which could lead to unexpected behavior.

 requirements = (
     requirements or "mesa\nmatplotlib\nnumpy\nnetworkx\nsolara\naltair\npandas"
 )

+# Validate parameters
+if autodetect_files and files:
+    raise ValueError("Cannot specify both 'files' and 'autodetect_files=True'")
+
+if not autodetect_files and not files:
+    raise ValueError("Must provide either 'files' or set 'autodetect_files=True'")
+
 app = ""
 file_list = []

44-64: 🛠️ Refactor suggestion

Add error handling for file operations.

The current implementation doesn't handle potential file access errors, which could cause the function to fail unexpectedly.

 if autodetect_files:
     all_files = _scan_python_files()
     for file in all_files:
-        with open(file) as f:
-            if file.endswith("app.py"):
-                app += f.read()
-            else:
-                file_dict = {}
-                file_dict["name"] = os.path.basename(file)
-                file_dict["content"] = f.read()
-                file_list.append(file_dict)
+        try:
+            with open(file) as f:
+                if file.endswith("app.py"):
+                    app += f.read()
+                else:
+                    file_dict = {}
+                    file_dict["name"] = os.path.basename(file)
+                    file_dict["content"] = f.read()
+                    file_list.append(file_dict)
+        except (IOError, OSError) as e:
+            print(f"Warning: Could not read file {file}: {e}")
 else:
     for file in files:
-        with open(files[file]) as f:
-            file_content = f.read()
-            if file == "app.py":
-                app += file_content
-            else:
-                file_dict = {"name": file, "content": file_content}
-                file_list.append(file_dict)
+        try:
+            with open(files[file]) as f:
+                file_content = f.read()
+                if file == "app.py":
+                    app += file_content
+                else:
+                    file_dict = {"name": file, "content": file_content}
+                    file_list.append(file_dict)
+        except (IOError, OSError) as e:
+            print(f"Warning: Could not read file {files[file]}: {e}")
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 47-47: mesa/model_share.py#L47
Added line #L47 was not covered by tests


[warning] 49-49: mesa/model_share.py#L49
Added line #L49 was not covered by tests


[warning] 51-54: mesa/model_share.py#L51-L54
Added lines #L51 - L54 were not covered by tests


[warning] 57-58: mesa/model_share.py#L57-L58
Added lines #L57 - L58 were not covered by tests


[warning] 60-60: mesa/model_share.py#L60
Added line #L60 was not covered by tests


[warning] 62-63: mesa/model_share.py#L62-L63
Added lines #L62 - L63 were not covered by tests

🧹 Nitpick comments (3)
mesa/visualization/solara_viz.py (1)

134-141: Consider renaming the button to "Share with PYCAFE" for clarity.

The button functionality is well-implemented, but as mentioned in the PR feedback from user tpike3, the label "Open on PyCafe" might not be clear enough for users unfamiliar with PyCafe. Changing it to "Share with PYCAFE" would better communicate the button's purpose.

 solara.Button(
-    label="Open on PyCafe",
+    label="Share with PYCAFE",
     color="blue",
     attributes={
         "href": get_pycafe_link(autodetect_files=True),
         "target": "_blank",
     },
 )
mesa/model_share.py (2)

65-74: Consider adding compression level control for URLs with large codebases.

For projects with substantial code, the URL might become very long. Adding compression level control could help optimize the URL length.

 json_object = {"code": app, "requirements": requirements, "files": file_list}
 json_text = json.dumps(json_object)
 # Compress using gzip to make the url shorter
-compressed_json_text = gzip.compress(json_text.encode("utf8"))
+# Use high compression level (9 is maximum) for potentially large codebases
+compressed_json_text = gzip.compress(json_text.encode("utf8"), compresslevel=9)
 # Encode in base64
 base64_text = base64.b64encode(compressed_json_text).decode("utf8")
 c = quote(base64_text)
 url = f"https://py.cafe/snippet/solara/v1#c={c}"

77-87: Consider expanding file detection to include more Python files.

The current implementation only looks for three specific filenames, which might be too restrictive for some projects with different naming conventions.

 def _scan_python_files(directory_path: str = ".") -> list[str]:
-    """Scan a directory for specific Python files (model.py, app.py, agents.py)."""
+    """Scan a directory for Python files to include in the PyCafe share.
+    
+    Looks for key model files first (model.py, app.py, agents.py), then includes
+    other Python files that might be dependencies.
+    """
     path = Path(directory_path)
-    python_files = [
+    # Primary files that are expected for Mesa models
+    primary_files = [
         str(file)
         for file in path.glob("*.py")
         if file.name in ["model.py", "app.py", "agents.py"]
     ]
+    
+    # If no primary files found, include all Python files in the directory
+    if not primary_files:
+        return [str(file) for file in path.glob("*.py")]
+    
+    return primary_files
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5166670 and e6df076.

📒 Files selected for processing (2)
  • mesa/model_share.py (1 hunks)
  • mesa/visualization/solara_viz.py (2 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
mesa/visualization/solara_viz.py (1)
mesa/model_share.py (1)
  • get_pycafe_link (11-74)
🪛 GitHub Check: codecov/patch
mesa/model_share.py

[warning] 47-47: mesa/model_share.py#L47
Added line #L47 was not covered by tests


[warning] 49-49: mesa/model_share.py#L49
Added line #L49 was not covered by tests


[warning] 51-54: mesa/model_share.py#L51-L54
Added lines #L51 - L54 were not covered by tests


[warning] 57-58: mesa/model_share.py#L57-L58
Added lines #L57 - L58 were not covered by tests


[warning] 60-60: mesa/model_share.py#L60
Added line #L60 was not covered by tests


[warning] 62-63: mesa/model_share.py#L62-L63
Added lines #L62 - L63 were not covered by tests

🔇 Additional comments (2)
mesa/visualization/solara_viz.py (1)

40-40: LGTM! Appropriate import statement added.

The import statement correctly references the new get_pycafe_link function from the model_share module.

mesa/model_share.py (1)

11-36: Function signature and documentation look good.

The function signature is clear with well-documented parameters and return type. The docstring is comprehensive and includes a helpful example.

label="Open on PyCafe",
color="blue",
attributes={
"href": get_pycafe_link(autodetect_files=True),
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for link generation.

The current implementation assumes get_pycafe_link will always succeed, but file operations might fail if the required files aren't found or are inaccessible. Consider implementing error handling to provide a graceful fallback.

 solara.Button(
     label="Open on PyCafe",
     color="blue",
     attributes={
-        "href": get_pycafe_link(autodetect_files=True),
+        "href": _get_pycafe_link_with_fallback(),
         "target": "_blank",
     },
 )

+# Add this helper function elsewhere in the file
+def _get_pycafe_link_with_fallback():
+    try:
+        return get_pycafe_link(autodetect_files=True)
+    except Exception as e:
+        _mesa_logger.warning(f"Failed to generate PyCafe link: {e}")
+        return "https://py.cafe/snippet/solara/v1"  # Fallback to empty project
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"href": get_pycafe_link(autodetect_files=True),
solara.Button(
label="Open on PyCafe",
color="blue",
attributes={
- "href": get_pycafe_link(autodetect_files=True),
+ "href": _get_pycafe_link_with_fallback(),
"target": "_blank",
},
)
# Add this helper function elsewhere in the file
def _get_pycafe_link_with_fallback():
try:
return get_pycafe_link(autodetect_files=True)
except Exception as e:
_mesa_logger.warning(f"Failed to generate PyCafe link: {e}")
return "https://py.cafe/snippet/solara/v1" # Fallback to empty project

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Release notes label
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Sharing of Models through links
3 participants