Skip to content

Comments

Jupyterlab extension for logging into a Marble node#1

Open
alexandercyu wants to merge 32 commits intomainfrom
marble-extension
Open

Jupyterlab extension for logging into a Marble node#1
alexandercyu wants to merge 32 commits intomainfrom
marble-extension

Conversation

@alexandercyu
Copy link
Contributor

Adds a button to the Jupyter Lab toolbar that will add a cell to the top of a Jupyter notebook with prepopulated code. The code will create and display a login interface that allows the user to choose a node to log in to and enter their login credentials.

Add Get Marble Session button to notebook toolbar
- Add code cell with pre-filled code
- run the cell (currently doens't seem to be running but the return on the function runCells implies it is running)
Style input fields for node ID, username, and password
- convert python input and password fields to jupyterlab widgets
- add submit button
- display node list as a dropdown list
- change input fields to jupyterlab widgets
-style each input widget and align vertically
- make label for each input widget visible
- add login status widgets (Note: Not displaying properly)
- remove icon for successful login
- remove decorators for output widget capture
- remove metadata form example
- Remove unneeded getpass import
- add text colour to input fields
- remove border (border radius not a valid style key)
- change input field and button colours to use hex code from design
- add error message for when no choice is made for node name
- add conditions to display proper error message according to user 's dropdown choice
Remove Marble design css (moved styling to ipywidgets and Jupyter widgets)
Nicer indentation for json that adds button to notebook toolbar
Remove print statements
Copy link
Collaborator

@mishaschwartz mishaschwartz left a comment

Choose a reason for hiding this comment

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

All of the relevant code should be moved up one directory level: everything under the top-level jupyterlab_marble_extensions folder should be at the top level of the repo.

Copy link
Collaborator

Choose a reason for hiding this comment

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

don't commit this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

".idea/" added in gitignore under Pycharm heading.

# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
_commit: v4.3.8
_src_path: https://github.com/jupyterlab/extension-template
author_email: test@test.com
Copy link
Collaborator

Choose a reason for hiding this comment

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

add a real email here or leave it blank

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed the email

Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we want to use binder with this? If so we should set up a github token for this action

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think binder will be needed. It was one of the steps in the setup tutorial.

# Changelog

<!-- <START NEW CHANGELOG ENTRY> -->

Copy link
Collaborator

Choose a reason for hiding this comment

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

Add an initial entry here describing your changes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added entry for not automatically installing python packages and an entry for checking for empty credentials before sending request to server.

*/

describe('jupyterlab-marble-extension', () => {
it('should be tested', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

What are some real tests that we can add here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe test if a cell is added to the notebook when the function is run?

'\n payload["credentials"]["password"] = change["new"];' +
'\n ' +
'\n def submit(arg1):' +
'\n userNode = "" ' +
Copy link
Collaborator

Choose a reason for hiding this comment

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

no need to initialize variables here to the empty string

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed variables that are initialized to empty string.

'\n userNode = payload["selectedNode"]' +
'\n url = MarbleClient()[userNode].url + "/magpie/signin" ' +
'\n response = requests.post(url, headers={"Content-Type": "application/json"}, json=payload["credentials"])' +
'\n if("200" in str(response)):' +
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not a safe way to check for a success. The repr of a response object is not stable and could be anything that may or may not contain the status message. Either compare the status_code or ok attributes directly or call raise_for_status()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed success check to checking the response.json().

'\n submitButton = ipywidgets.Button(description="Submit", disabled=False,button_style="", tooltip="Submit", icon=""' +
', style={"font_family":"Helvetica Neue","font_size":"16px", "button_color":"#304FFE", "text_color":"white"} )' +
'\n ' +
'\n loginSuccessLabelOutputWidget = ipywidgets.Output()' +
Copy link
Collaborator

Choose a reason for hiding this comment

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

You can just have one output widget and write the error or success message to that single output.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reduced output widgets to just one and put different output messages to it.

The success and error messages come from the response while the choose another node message is custom.

'\n with passwordOutput:' +
'\n payload["credentials"]["password"] = change["new"];' +
'\n ' +
'\n def submit(arg1):' +
Copy link
Collaborator

Choose a reason for hiding this comment

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

arg1 is not used. To signal that a variable is unused in python, add an underscore before it like _arg

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added underscore to the variable name

'\n loginSuccessLabelWidget = ipywidgets.HBox([ipywidgets.Label(value="Logged into " + userNode + " successfully.", style={"text_color":"green", "font_size":"16px"})]) ' +
'\n loginFailedLabelWidget = ipywidgets.HBox([ipywidgets.Label(value="Error Logging In", style={"text_color":"red", "font_size":"16px"})])' +
'\n ' +
'\n if("selectedNode" in payload and payload["selectedNode"] != "Node ID"):' +
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why don't we also add in a check that username and password are non-empty before we submit the request so that we can tell the users that those values are required as well.

Copy link
Contributor Author

@alexandercyu alexandercyu Jul 24, 2025

Choose a reason for hiding this comment

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

Added checks for username and password to check if they're non-empty.

Added error message for empty username or password.

Error messages for username, password, node name should clear correctly.

Error messages will also stack if a node name is invalid and username or password, or both, are empty.

alexandercyu and others added 11 commits July 22, 2025 14:09
Added Pycharm specific ignore
- output widget messages no longer stack up except in the case of an invalid node name and empty user credentials
- changed request.post() to session.post()
- successful or erroneous login feedback messages is now the one from the server response
- removed variables that are initialized as empty strings
- changed success check condition to use response.json()
- removed unneeded output widgets
- added check for empty credentials
Add changelog items
Changed command name to marble_login
Added test to see if a code cell is added to the top of the notebook (index zero)
Removed command call
@mishaschwartz
Copy link
Collaborator

@alexandercyu you haven't pushed any changes since my last review. If you're working on another branch you need to merge the changes here or else they won't show up on this PR.

@alexandercyu alexandercyu mentioned this pull request Jul 28, 2025
Add blank line to satisfy prettier linting error
alexandercyu and others added 3 commits July 28, 2025 13:39
Added tests (tests in progress)
Comment out test for now (test isn't working)
@alexandercyu
Copy link
Contributor Author

@alexandercyu you haven't pushed any changes since my last review. If you're working on another branch you need to merge the changes here or else they won't show up on this PR.

Merged the changes from updated-example into this branch.

Added new entries for pycharm, yarn, node_modules, and testing specific directories
hatchling Outdated
Copy link
Collaborator

Choose a reason for hiding this comment

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

What is this?!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know. It was part of the extension template from the tutorial: https://jupyterlab.readthedocs.io/en/latest/extension/extension_tutorial.html

This line copies the template from the url: copier copy --trust https://github.com/jupyterlab/extension-template .

src/index.ts Outdated
'\nexcept ImportError as exc:' +
'\n raise Exception("The marble_client package is required to run this cell. Please install it and run this code again.") from exc' +
'\n ' +
'\nfrom marble_client import MarbleClient' +
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is already imported above

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed duplicated import.

'\n client_session = client.this_session()' +
'\nexcept JupyterEnvironmentError:' +
'\n ' +
'\n session = requests.Session()' +
Copy link
Collaborator

Choose a reason for hiding this comment

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

This variable should be the same as in the try block

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed 'client_session = client.this_session()' in the try block to 'session = client.this_session()'.

src/index.ts Outdated
'\n password_widget = ipywidgets.Password(style=input_field_style)' +
'\n password_box_widget = ipywidgets.VBox([password_label_widget, password_widget])' +
'\n ' +
'\n submit_button = ipywidgets.Button(description="Submit", button_style="", tooltip="Submit", icon=""' +
Copy link
Collaborator

Choose a reason for hiding this comment

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

button_style and icon not needed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed button_style and icon from the button definition.

'\n input_field_style = {"description_width":"initial"}' +
'\n login_success_style = {"font_family":"Helvetica Neue","font_size":"16px", "text_color":"green"}' +
'\n error_style = {"font_family":"Helvetica Neue","font_size":"16px", "text_color":"red"}' +
'\n choose_another_node_style = {"font_family":"Helvetica Neue","font_size":"16px", "text_color":"#304FFE"}' +
Copy link
Collaborator

Choose a reason for hiding this comment

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

Think about making the style into a variable to be consistent

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Made the submit button style into a variable.

src/index.ts Outdated
'\n ui_message_output_widget = ipywidgets.Output()' +
'\n ui_message_label_widget = ipywidgets.Label(value="", style=ui_label_style)' +
'\n ui_message_display_box_widget = ipywidgets.HBox([ui_message_label_widget])' +
'\n credential_error_output_widget = ipywidgets.Output()' +
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd recommend just having one output and you can choose what to display in there as needed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reduced to one output widget.

Removed HBox widgets for outputs.

src/index.ts Outdated
'\n response = session.post(url, headers={"Content-Type": "application/json"}, json=payload["credentials"])' +
'\n response_json = response.json()' +
'\n ' +
'\n if(response_json["code"] == 200):' +
Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Now checks response.status_code for 200 response.

Also gets details of response from response.reason if there is no response.json().

- Removed Hbox widgets for displaying output messages, just use label widgets instead.
- reduce output widgets to one
- check for server response using response.status_code instead
- if status_code is 200, then check for magpie specific json and get magpie specific response message.  Otherwise use standard response message
@alexandercyu alexandercyu added the enhancement New feature or request label Jul 29, 2025
Deleted file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants