JupyterLab: How to trigger a call back function to python backend from Javascript front end - jupyter-notebook

I am trying to build a JupyterLab Widget extension
I create an 'example.js' file that holds a button execute and an 'example.py' which holds model information.
When I run the code bellow,
import ExampleWidget
from ExampleWidet import example
example.RunTool()
Creates a button,
I want to execute another python function in the backend from the button click event.
I am not able to find a way to implement this part please help.
thanks
Update
Python Code:
from ipywidgets import VBox, widget_serialization
from traitlets import Unicode, List, Dict, Instance
from ._frontend import module_name, module_version
#from .basewidget import BaseWidget
class ExampleUIOutput(UIOutput):
"""
Widget used to render Python output in a UI
"""
_model_name = Unicode('ExampleUIOutputModel').tag(sync=True)
_model_module = Unicode(module_name).tag(sync=True)
_model_module_version = Unicode(module_version).tag(sync=True)
_view_name = Unicode('ExampleUIOutputView').tag(sync=True)
_view_module = Unicode(module_name).tag(sync=True)
_view_module_version = Unicode(module_version).tag(sync=True)
name = Unicode('Python Results').tag(sync=True)
def __init__(self, **kwargs):
# Initialize the child widget container
self.appendix = VBox()
UIOutput.__init__(self, **kwargs)
Javascript Code:
export class ExampleUIOutputModel extends UIOutputModel {
defaults() {
return Object.assign(Object.assign({}, super.defaults()), { _model_name: ExampleUIOutputModel.model_name, _model_module: ExampleUIOutputModel.model_module, _model_module_version: ExampleUIOutputModel.model_module_version, _view_name: ExampleUIOutputModel.view_name, _view_module: ExampleUIOutputModel.view_module, _view_module_version: ExampleUIOutputModel.view_module_version, name: 'Python Results' });
}
}
ExampleUIOutputModel.model_name = 'ExampleUIOutputModel';
ExampleUIOutputModel.model_module = MODULE_NAME;
ExampleUIOutputModel.model_module_version = MODULE_VERSION;
ExampleUIOutputModel.view_name = 'ExampleUIOutputView';
ExampleUIOutputModel.view_module = MODULE_NAME;
ExampleUIOutputModel.view_module_version = MODULE_VERSION;
ExampleUIOutputModel.serializers = Object.assign(Object.assign({}, UIOutputModel.serializers), { appendix: {
deserialize: (value, manager) => unpack_models(value, manager)
} });
export class ExampleUIOutputView extends UIOutputView {
constructor() {
super(...arguments);
}
render() {
const Hello = document.createElement('button')
this.el.append(Hello)
Hello.addEventListener("click", function() {
console.log('Hello World');
}, false);
}
}
Utilities:
I have a python file Utils.py with the code for example
def HelloWorld(name):
print('Hello '+name)
I want when I click the button it executes this python code or any other python code.

Related

How to pass my viewmodel to a class that does not extend activity

How to pass my viewmodel to a class that does not extend activity
I'm calling my viewmodel like this:
in my EntryAbstract class
where am I going wrong
val FrutasViewModel = ViewModelProvider.NewInstanceFactory().create(FrutasViewModel::class.java)
FrutasViewModel.frutaData.value.forEach { item->
itens.add(ShoppingCart
(id=item.id,photo=item.photo,
name=item.name,quantidade=item.quantidade
,categoria = item.categoria,descricao = item.descricao
,unidade=item.unidade,kilo = item.kilo
))
}
my viewmodel:
package com.example.quitanda.models
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
class FrutasViewModel(
private val frutasServices: Services,
):ViewModel() {
private val _frutasData: MutableStateFlow<List<ShoppingCart>> = MutableStateFlow<List<ShoppingCart>>(listOf<ShoppingCart>(ShoppingCart()))
val frutaData: StateFlow<List<ShoppingCart>>
get() = _frutasData
fun getFrutas(){
viewModelScope.launch {
try {
val frutas = frutasServices.getFruta()
_frutasData.value = frutas
}catch (e:Exception){
Log.d("Service error",e.toString())
}
}
}
}
My service:
package com.example.quitanda.models
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.http.GET
interface Services {
#GET("/category/7")
suspend fun getFruta(
//#Query("apikey")
//apikey:String = "333b4285"
): List<ShoppingCart>
}
val retrofit: Retrofit = Retrofit.Builder()
.baseUrl("http://localhost:4000/")
.addConverterFactory(MoshiConverterFactory.create())
.build()
val frutasServices: Services = retrofit.create(Services::class.java)
My model:
package com.example.quitanda.models
import android.os.Parcelable
import com.squareup.moshi.Json
import kotlinx.parcelize.Parcelize
#Parcelize
data class ShoppingCart(
var count:Int=0,
#field:Json(name="product_title")
var name:String="",
#field:Json(name="product_id")
var id:Int=0,
#field:Json(name="photo_photo")
var photo:String="",
#field:Json(name="product_quant")
var quantidade:Int=0,
#field:Json(name="category_name")
var categoria:String="",
#field:Json(name="product_description")
var descricao:String="",
#field:Json(name="product_price_un")
var unidade:String="",
#field:Json(name="product_price_kg")
var kilo:String="",
var tipos:String=""): Parcelable
When I try to run my code it gives the following error
Does anyone have any idea how to fix this
who can help I am grateful
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.quitanda, PID: 11031
java.lang.RuntimeException: Cannot create an instance of class com.example.quitanda.models.FrutasViewModel
I wouldn't recommend doing what you're trying to achieve, because what Android did, is that they've abstracted how viewmodels are scoped, to give you developers the power to easily handle things like orientation-change.
In practice this means, that android views, such as Activity/Fragment implement a ViewModelStoreOwner which contains a ViewModelStore, which handles the scoping and retrieves the correct ViewModel instance based on context.
TL;DR: If you want an android arch.viewmodel then create it in your Activity/Fragment and pass it to the EntryAbstract, though chances are you just need some of the data, which could be set individually for better separation of concerns

javafx binding from list property to arbitrary object property

I am trying to get a class to have a property bound to another class's list property, where the 1st property is derived from a summarizing calculation over the objects in the list. The code below is a simplified version of my production code. (The production code is doing a summary over DateTime objects -- the essential part of the code below is the binding between a list and an object property (here, it is a String for simplicity).)
I have tried various things. One approach was using addListener on the list in the Summary class below but I was running into weird bugs with the listener callback making updates on the Summary object. After doing a bunch of reading I think that a binding between the summary string and the list is more appropriate but I don't know exactly how to hook up the binding to the property?
package com.example.demo.view
import javafx.beans.Observable
import javafx.beans.binding.StringBinding
import javafx.beans.property.SimpleIntegerProperty
import javafx.beans.property.SimpleListProperty
import javafx.beans.property.SimpleStringProperty
import javafx.collections.FXCollections
import tornadofx.View
import tornadofx.button
import tornadofx.label
import tornadofx.vbox
class Thing(x: Int) {
val xProperty = SimpleIntegerProperty(x)
val yProperty = SimpleStringProperty("xyz")
}
class Collection {
private var things = FXCollections.observableList(mutableListOf<Thing>()) {
arrayOf<Observable>(it.xProperty)
}
val thingsProperty = SimpleListProperty<Thing>(things)
fun addThing(thing: Thing) {
things.add(thing)
}
}
class Summary(var collection: Collection) {
val summaryBinding = object : StringBinding() {
// The real code is more practical but
// this is just a minimal example.
override fun computeValue(): String {
val sum = collection.thingsProperty.value
.map { it.xProperty.value }
.fold(0, { total, next -> total + next })
return "There are $sum things."
}
}
// How to make this property update when collection changes?
val summaryProperty = SimpleStringProperty("There are ? things.")
}
class MainView : View() {
val summary = Summary(Collection())
override val root = vbox {
label(summary.summaryProperty)
button("Add Thing") {
summary.collection.addThing(Thing(5))
}
}
}
Keep in mind that I made this answer based on your minimal example:
class Thing(x: Int) {
val xProperty = SimpleIntegerProperty(x)
var x by xProperty
val yProperty = SimpleStringProperty("xyz")
var y by yProperty
}
class MainView : View() {
val things = FXCollections.observableList(mutableListOf<Thing>()) {
arrayOf<Observable>(it.xProperty)
}
val thingsProperty = SimpleListProperty<Thing>(things)
val totalBinding = integerBinding(listProperty) {
value.map { it.x }.fold(0, { total, next -> total + next })
}
val phraseBinding = stringBinding(totalBinding) { "There are $value things." }
override val root = vbox {
label(phraseBinding)
button("Add Thing") {
action {
list.add(Thing(5))
}
}
}
}
I removed your other classes because I didn't see a reason for them based on the example. If the collection class has more functionality than holding a list property in your real project, then add just add it back in. If not, then there's no reason to give a list its own class. The summary class is really just two bindings (or one if you have no need to separate the total from the phrase). I don't see the need to give them their own class either unless you plan on using them in multiple views.
I think your biggest problem is that you didn't wrap your button's action in action {}. So your code just added a Thing(5) on init and had no action set.
P.S. The var x by xProperty stuff will only work if you import tornadofx.* for that file.

Aurelia creating a Binding Behaviour that wraps SignalBindingBehaviour

I've currently got a simple Value Converter which uses momentjs to convert Dates to strings:
export class MomentValueConverter {
public toView(value: Date, format: string): string {
return moment(value).format(format);
}
}
However, wherever I use it I end up having to combine it with the aurelia-translation-signal so that its updated if the user changes the current language.
${fileSaved | moment:'ll LTS' & signal:'aurelia-translation-signal'}
How do I instead create a Binding Behavior that automatically takes care of the signalling from aurelia-translation-signal?
Then I could use it like:
${fileSaved & moment:'ll LTS'}
There is a good example in aurelia-i18n library, https://github.com/aurelia/i18n/blob/master/src/t.js#L89-L122
import {ValueConverter} from 'aurelia-binding';
import {SignalBindingBehavior} from 'aurelia-templating-resources';
export class TBindingBehavior {
static inject = [SignalBindingBehavior];
constructor(signalBindingBehavior) {
this.signalBindingBehavior = signalBindingBehavior;
}
bind(binding, source) {
// bind the signal behavior
this.signalBindingBehavior.bind(binding, source, 'aurelia-translation-signal');
// rewrite the expression to use the TValueConverter.
// pass through any args to the binding behavior to the TValueConverter
let sourceExpression = binding.sourceExpression;
// do create the sourceExpression only once
if (sourceExpression.rewritten) {
return;
}
sourceExpression.rewritten = true;
let expression = sourceExpression.expression;
sourceExpression.expression = new ValueConverter(
expression,
't',
sourceExpression.args,
[expression, ...sourceExpression.args]);
}
unbind(binding, source) {
// unbind the signal behavior
this.signalBindingBehavior.unbind(binding, source);
}
}
UPDATE: Signals are internally supported by value converters already http://aurelia.io/docs/binding/value-converters#signalable-value-converters
import {signalBindings} from 'aurelia-framework';
signalBindings('locale-changed');
export class FlightTimeValueConverter {
signals = ['locale-changed'];
toView(date) {
return date.toLocaleString(window.currentLocale);
}
}

How to trigger a function only once in case of a mouseEvent

I am trying to make a simple mp3 player using flash. The songs are loaded using an XML file which contains the song list. I have "play" button with the instance name "PlayBtn". I have an actionscript file named "playctrl", the content of which are listed below:
package classes
{
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.events.*;
import flash.events.MouseEvent;
import flash.net.URLRequest;
public class playctrl
{
private var MusicLoading:URLRequest;
private var music:Sound;
private var sc:SoundChannel;
private var currentSound:Sound;
private static var CurrentPos:Number;
private var xml:XML;
private var songlist:XMLList;
private static var currentIndex:Number;
public function playctrl()
{
music = new Sound();
currentSound= music;
CurrentPos = 0;
currentIndex = 0;
}
public function success(e:Event):void
{
xml = new XML(e.target.data);
songlist = xml.song;
MusicLoading = new URLRequest(songlist[0].file);
music.load(MusicLoading);
}
public function playSong(e:Event):void
{
if(sc != null)
sc.stop();
sc = currentSound.play(CurrentPos);
trace("HELLO !!!");
}
}
}
I have a second file named "play.as", the content of which is listed below:
import classes.playctrl;
var obj:playctrl = new playctrl();
var XMLLoader:URLLoader = new URLLoader(); //XML Loader
XMLLoader.addEventListener(Event.COMPLETE, obj.success);
XMLLoader.load(new URLRequest("playlist.xml"));
PlayBtn.addEventListener(MouseEvent.CLICK, obj.playSong);
However on clicking the play button, I notice that the function playSong() is called 7-8 times(check by printing an error msg. inside the function) resulting in overlapped audio output and the player crashing as a result. The function should be called only once when the MouseEvent.CLICK is triggered. Please help ...
interestingly, sound object doesn't have a built-in "isPlaying" boolean property (strange), so you could just create your own.
var isPlaying:Boolean
function playSong():void
{
if(!isPlaying)
sound.play();
}
function stopSong():void
{
if(isPlaying)
{
channel.stop();
isPlaying = false;
}
just a note: by convention, class names are capitalized camel case while instance names are uncapitalized camel case. so your playctrl.as class file should (or could) be PlayCtrl.as, and your PlayBtn instance should (or could) be playBtn.
Edit:
The title of your question is a bit misleading, the answer I gave you is a solution to the question expressed in the title.
Looking at your code, I would look at separating the concerns, on one hand you want to load the song data, on the other hand you want to control the sounds. I would implement separate classes for each concern. If you create a separate class for your player control, you'll be able to dispatch event within that class without the event bubbling all over your app and calling your functions several times.
//Previous answer
You could do this by implementing a Boolean that would be set when the sound is stopped or played.
In any case here's another way to filter unwanted clicks
private function playSong(event:MouseEvent ):void
{
// set up a conditional to identify your button ,
// here's an example...
if( event.currentTarget.name is "PlayBtn" )
{
//do whatever
//then...
event.stopImmediatePropagation();
}
}
This being said, in your case , it sounds like a bit of a quick fix since a MouseEvent shouldn't trigger the play function several times...
It would make sense to debug your code in order to understand why several events are dispatched after a Mouse click
private var _isPlaying:Boolean;
public function playSong(e:Event):void
{
if(sc != null)
{
sc.stop();
_isPlaying = false;
}
if( !_isPlaying )
{
sc = currentSound.play(CurrentPos);
_isPlaying = true;
trace("HELLO !!!");
}
}

How to use SequenceRunner with FlexUnit 4

In the FlexUnit wiki I've read about the very interesting SequenceRunner that was contributed by the Fluint folks. Now I am trying to run a test that is very similar to the example, however when executing the run() Method of the SequenceRunner instance, I get this exception:
Cannot add asynchronous functionality to methods defined by Test,Before or After that are not marked async
Error: Cannot add asynchronous functionality to methods defined by Test,Before or After that are not marked async
at org.flexunit.async::AsyncLocator$/getCallableForTest()[C:\Users\dmoor e\Documents\_Production\Flex Unit 4\GIT\FlexUnit4\src\org\flexunit\async\AsyncLocator.as:82]
at org.fluint.sequence::SequenceWaiter/setupListeners()[C:\Users\dmoore\ Documents\_Production\Flex Unit 4\GIT\FlexUnit4\src\org\fluint\sequence\SequenceWaiter.as:100]
at org.fluint.sequence::SequenceRunner/continueSequence()[C:\Users\dmoor e\Documents\_Production\Flex Unit 4\GIT\FlexUnit4\src\org\fluint\sequence\SequenceRunner.as:177]
at org.fluint.sequence::SequenceRunner/run()[C:\Users\dmoore\Documents\_ Production\Flex Unit 4\GIT\FlexUnit4\src\org\fluint\sequence\SequenceRunner.as:124]
Has anyone used the SequenceRunner with FlexUnit 4 already. The [Test(async)] annotation is already present.
Here is a complete, very simple example test case class.
package test
{
import flash.events.Event;
import org.flexunit.asserts.assertEquals;
import org.fluint.sequence.SequenceRunner;
import org.fluint.sequence.SequenceWaiter;
public class test_case
{
[Test(async)]
public function test_function():void
{
var counter:Object = { count: 0}
var sr:SequenceRunner = new SequenceRunner(this);
sr.addStep(new SequenceWaiter(new TestWaiterTarget(counter), "myEvent", 50000));
sr.addStep(new SequenceWaiter(new TestWaiterTarget(counter), "myEvent", 5000))
sr.addAssertHandler(test_function_handler, counter);
sr.run();
}
private function test_function_handler(event:Event, passthroughData:*):void
{
assertEquals(passthroughData.count, 2);
}
}
}
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.TimerEvent;
import flash.utils.Timer;
class TestWaiterTarget extends EventDispatcher
{
var timer:Timer = new Timer(250, 1);
private var _counter:Object;
public function TestWaiterTarget(counter)
{
_counter = counter;
timer.addEventListener(TimerEvent.TIMER_COMPLETE, timer_timerCompleteHandler);
timer.start();
}
private function timer_timerCompleteHandler(event:TimerEvent):void
{
_counter.count++;
dispatchEvent(new Event("myEvent"));
}
}
Thanks to Michael Labriola, who responded to my question in the Adobe Forum I was finally able to make it running. Note that the documentation of SequenceRunner in the Wiki is outdated and partially wrong.
Do not inherit from any TestCase class.
Skip the asyncHandler for CREATION_COMPLETE in the setUp. Rather add a SequenceWaiter in the test that waits for the CREATION_COMPLETE event of the component
The test must be marked as asynchronous test, so add the [Test(async)] Metadata to test cases that use SequenceRunner.

Resources