Skip to content

Commit

Permalink
Run prettier
Browse files Browse the repository at this point in the history
  • Loading branch information
jtpio committed Mar 15, 2021
1 parent 1f45876 commit b0b6476
Show file tree
Hide file tree
Showing 25 changed files with 283 additions and 278 deletions.
47 changes: 27 additions & 20 deletions available-methods.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
There doesn't seem to be a canonical list of all the functions availiable to Widget objects for either python or typescript. so here is a list of many functions with some questionable commentary by yours truly.


# typescript:

For widgets on the typescript side useful to look at the file where `WidgetModel`, `DOMWidgetModel`, `WidgetView` and `DOMWidgetView` are defined:

https://github.com/jupyter-widgets/ipywidgets/blob/6be18d9b75353f7b4a1c328c6ea06d8959f978f6/packages/base/src/widget.ts

The model view framework is based off [backbone.js](https://backbonejs.org/#) which provides the methods to do things like listen to changes in the model https://backbonejs.org/#Events

backbonejs provides:

```
on
off
Expand All @@ -18,6 +19,7 @@ listenTo
stopListening
listenToOnce
```

and `WidgetModel` adds `on_some_change` to this list. see defintion [here](https://github.com/jupyter-widgets/ipywidgets/blob/6be18d9b75353f7b4a1c328c6ea06d8959f978f6/packages/base/src/widget.ts#L528)
With documentation:

Expand All @@ -26,11 +28,13 @@ With documentation:
An example taken from ipycanvas: https://github.com/martinRenou/ipycanvas/blob/7c738b2640d1d87207970740a8f2b7f16a72457f/src/widget.ts#L72

in the `CanvasModel` extends `DOMWidgetModel`:

```javascript
this.on_some_change(['width', 'height'], this.resizeCanvas, this);
this.on('change:sync_image_data', this.syncImageData.bind(this));
this.on('msg:custom', this.onCommand.bind(this));
```

the [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind) is useful to make `this` refer to the Canvas object rather than the object of event.

These listening methods can be used (and maybe should only be used with - bc i don't understand how to extend) with the backbonejs builtin events:
Expand All @@ -54,31 +58,32 @@ https://backbonejs.org/#Events-catalog
- **route** (router, route, params) — Fired by history when any route has been matched.
- **all** — this special event fires for any triggered event, passing the event name as the first argument followed by all trigger arguments.


of these `change` is probably far and away the most useful.
of these `change` is probably far and away the most useful.

### Views
WidgetViews also add:
- **callbacks** Create msg callbacks for a comm msg. Used in the `touch` method. Probably don't use this yourself
- **send** Send a custom msg associated with this view.
- **touch** Use the view method touch instead of model.save_changes to associate the changes with the current view, thus associating any response messages with the view’s cell. (from low level widget tutorial)

WidgetViews also add:

- **callbacks** Create msg callbacks for a comm msg. Used in the `touch` method. Probably don't use this yourself
- **send** Send a custom msg associated with this view.
- **touch** Use the view method touch instead of model.save_changes to associate the changes with the current view, thus associating any response messages with the view’s cell. (from low level widget tutorial)

### Typescript Miscellany

every view( maybe only DOMWidgetViews?) has a `this.el` which corresponds to the the DOM element to which the view belongs. From backbone documentation:
> **elview.el:**
All views have a DOM element at all times (the el property), whether they've already been inserted into the page or not. In this fashion, views can be rendered at any time, and inserted into the DOM all at once, in order to get high-performance UI rendering with as few reflows and repaints as possible.

> **elview.el:**
> All views have a DOM element at all times (the el property), whether they've already been inserted into the page or not. In this fashion, views can be rendered at any time, and inserted into the DOM all at once, in order to get high-performance UI rendering with as few reflows and repaints as possible.
`initialize` is a function that is called at the end the constructor by all backbone objects (both model and view). FOr model:

> constructor / initializenew Model([attributes], [options])
When creating an instance of a model, you can pass in the initial values of the attributes, which will be set on the model. If you define an initialize function, it will be invoked when the model is created.
> When creating an instance of a model, you can pass in the initial values of the attributes, which will be set on the model. If you define an initialize function, it will be invoked when the model is created.
for a view:
> constructor / initializenew View([options])
There are several special options that, if passed, will be attached directly to the view: model, collection, el, id, className, tagName, attributes and events. If the view defines an initialize function, it will be called when the view is first created. If you'd like to create a view that references an element already in the DOM, pass in the element as an option: new View({el: existingElement})

> constructor / initializenew View([options])
> There are several special options that, if passed, will be attached directly to the view: model, collection, el, id, className, tagName, attributes and events. If the view defines an initialize function, it will be called when the view is first created. If you'd like to create a view that references an element already in the DOM, pass in the element as an option: new View({el: existingElement})
Iterating over the views owned by a model:

Expand All @@ -98,26 +103,26 @@ callback argument isn't necessary, just that in this case its being used to appl

It's probably better for each view to register a callback with `this.model.on` than to use this as doing so is simpler. I had gravitated towards this because I was worried that the callbacks would continue to be called even after that view was inaccesible - but it turns out this is not the case.


# python

defined in this file: https://github.com/jupyter-widgets/ipywidgets/blob/6be18d9b75353f7b4a1c328c6ea06d8959f978f6/ipywidgets/widgets/widget.py
which is ultimately a subclass of [traitlets.HasTraits](https://traitlets.readthedocs.io/en/stable/api.html?highlight=HasTraits#traitlets-api-reference)
**class methods and staticmethods**

- **close_all(cls)** - closes all widgets of a certain class i think?
- **on_widget_constructed(callback)** - Registers a callback to be called when a widget is constructed.
The callback must have the following signature:
callback(widget)"""
The callback must have the following signature:
callback(widget)"""
- **handle_comm_opened(comm, msg)** - heck if know what this does - don't plan on using.
- **get_manager_state(drop_defaults=False, widgets=None):** - "Returns the full state for a widget manager for embedding
:param drop_defaults: when True, it will not include default value
:param widgets: list with widgets to include in the state (or all widgets when None)"" - either this or `get_state` are probably useful for embedding the widget standalone. Use this to get the contents of the script at the bottom of my comment https://github.com/QuantStack/ipycytoscape/issues/80#issuecomment-635470671

:param drop_defaults: when True, it will not include default value
:param widgets: list with widgets to include in the state (or all widgets when None)"" - either this or `get_state` are probably useful for embedding the widget standalone. Use this to get the contents of the script at the bottom of my comment https://github.com/QuantStack/ipycytoscape/issues/80#issuecomment-635470671

Other functions. Things that seem potentially useful are in bold

- `open` - "Open a comm to the frontend if one isn't already open" idk when this is necessary
- **`model_id`** - get the model id of the widget
- **`close`** - "Closes the underlying comm. When the comm is closed, all of the widget views are automatically removed from the front-end."
- **`close`** - "Closes the underlying comm. When the comm is closed, all of the widget views are automatically removed from the front-end."
- `send_state` -"Sends the widget state, or a piece of it, to the front-end, if it exists."
- **`get_state`** - get the widget state. I imagine this being useful for doing something like having a function to embed the widget standalone. Like i discuss here: https://github.com/QuantStack/ipycytoscape/issues/80#issuecomment-635470671 use this function to get the contents of the bottom script tag. Maybe this is for the python side of state, and the manager_state gives the embeddable state?
- `set_state` - "Called when a state is received from the front-end."
Expand All @@ -130,12 +135,14 @@ Other functions. Things that seem potentially useful are in bold
The [DOMWidget](https://github.com/jupyter-widgets/ipywidgets/blob/6be18d9b75353f7b4a1c328c6ea06d8959f978f6/ipywidgets/widgets/domwidget.py) gets a few extra methods and attributes.

Attributes:

- `tabbable` - Is widget tabbable
- `tooltip` - tooltup caption - unclear what this is tooltip for? defaults to None which is probably why I don't think i've seen an example of this
- `layout` dictionary - the [docs](https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Styling.html) for this are far and away the most complete section of documentation

**Methods**:

- `add_class` - "Adds a class to the top level element of the widget. Doesn't add the class if it already exists."
- `remove_class` - "Removes a class from the top level element of the widget. Doesn't remove the class if it doesn't exist."
- `remove_class` - "Removes a class from the top level element of the widget. Doesn't remove the class if it doesn't exist."
- `focus` - 'focus on widgets'
- `blur` - "[blur](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/blur) the widget" - I think this name is meant to evoke `defocus` because what it does is remove keyboard focus from the widget - this is the name from javascript though, not ipywidgets.
12 changes: 6 additions & 6 deletions connecting-widgets/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ module.exports = {
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended'
'plugin:prettier/recommended',
],
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module'
sourceType: 'module',
},
plugins: ['@typescript-eslint'],
rules: {
Expand All @@ -19,10 +19,10 @@ module.exports = {
'@typescript-eslint/quotes': [
'error',
'single',
{ avoidEscape: true, allowTemplateLiterals: false }
{ avoidEscape: true, allowTemplateLiterals: false },
],
curly: ['error', 'all'],
eqeqeq: 'error',
'prefer-arrow-callback': 'error'
}
};
'prefer-arrow-callback': 'error',
},
};
11 changes: 7 additions & 4 deletions connecting-widgets/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

# connecting-widgets

Exploring how to give access of a widget's typescript model to a different widget. To give `widget1` access to `widget2` the technique is to:
Expand All @@ -9,14 +8,12 @@ Exploring how to give access of a widget's typescript model to a different widge

**Important questions:**

Q: Is this good practice? - A: I have no idea
Q: Is this good practice? - A: I have no idea

Q: Is this the best way to achieve this? - A: This is the only way I could think of


## Development Installation


```bash
# First install the python package. This will also build the JS packages.
pip install -e ".[test, examples]"
Expand All @@ -43,17 +40,23 @@ you might also need another flag instead of `--sys-prefix`, but we won't cover t
of those flags here.

### How to see your changes

#### Typescript:

To continuously monitor the project for changes and automatically trigger a rebuild, start Jupyter in watch mode:

```bash
jupyter lab --watch
```

And in a separate session, begin watching the source directory for changes:

```bash
npm run watch
```

After a change wait for the build to finish and then refresh your browser and the changes should take effect.

#### Python:

If you make a change to the python code then you will need to restart the notebook kernel to have it take effect.
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
// Entry point for the notebook bundle containing custom model definitions.
//
define(function() {
"use strict";
define(function () {
'use strict';

window['requirejs'].config({
map: {
'*': {
'connecting-widgets': 'nbextensions/connecting_widgets/index',
},
}
});
// Export the required load_ipython_extension function
return {
load_ipython_extension : function() {}
};
window['requirejs'].config({
map: {
'*': {
'connecting-widgets': 'nbextensions/connecting_widgets/index',
},
},
});
// Export the required load_ipython_extension function
return {
load_ipython_extension: function () {},
};
});
38 changes: 15 additions & 23 deletions connecting-widgets/tests/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,34 @@ module.exports = function (config) {
reporters: ['mocha', 'karma-typescript'],
client: {
mocha: {
timeout : 10000, // 10 seconds - upped from 2 seconds
retries: 3 // Allow for slow server on CI.
}
timeout: 10000, // 10 seconds - upped from 2 seconds
retries: 3, // Allow for slow server on CI.
},
},
files: [
{ pattern: "tests/src/**/*.ts" },
{ pattern: "src/**/*.ts" },
],
exclude: [
"src/extension.ts",
],
files: [{ pattern: 'tests/src/**/*.ts' }, { pattern: 'src/**/*.ts' }],
exclude: ['src/extension.ts'],
preprocessors: {
'**/*.ts': ['karma-typescript']
'**/*.ts': ['karma-typescript'],
},
browserNoActivityTimeout: 31000, // 31 seconds - upped from 10 seconds
port: 9876,
colors: true,
singleRun: true,
logLevel: config.LOG_INFO,


karmaTypescriptConfig: {
tsconfig: 'tests/tsconfig.json',
reports: {
"text-summary": "",
"html": "coverage",
"lcovonly": {
"directory": "coverage",
"filename": "coverage.lcov"
}
'text-summary': '',
html: 'coverage',
lcovonly: {
directory: 'coverage',
filename: 'coverage.lcov',
},
},
bundlerOptions: {
transforms: [
require("karma-typescript-es6-transform")()
]
}
}
transforms: [require('karma-typescript-es6-transform')()],
},
},
});
};
20 changes: 5 additions & 15 deletions connecting-widgets/tests/src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,26 @@

import expect = require('expect.js');

import {
// Add any needed widget imports here (or from controls)
} from '@jupyter-widgets/base';
import // Add any needed widget imports here (or from controls)
'@jupyter-widgets/base';

import {
createTestModel
} from './utils.spec';

import {
ExampleModel, ExampleView
} from '../../src/'
import { createTestModel } from './utils.spec';

import { ExampleModel, ExampleView } from '../../src/';

describe('Example', () => {

describe('ExampleModel', () => {

it('should be createable', () => {
let model = createTestModel(ExampleModel);
expect(model).to.be.an(ExampleModel);
expect(model.get('value')).to.be('Hello World');
});

it('should be createable with a value', () => {
let state = { value: 'Foo Bar!' }
let state = { value: 'Foo Bar!' };
let model = createTestModel(ExampleModel, state);
expect(model).to.be.an(ExampleModel);
expect(model.get('value')).to.be('Foo Bar!');
});

});

});
Loading

0 comments on commit b0b6476

Please sign in to comment.