Review — Blender Atelier: Sculpt, version 1.1.1 [$]
by Metin SevenStarting with Blender 2.80, Sculpt Mode development has been given a refreshing boost, and the imminent release of Blender 2.81 will bring more Sculpt Mode additions and improvements. Blender's rapid development pace is attracting more and more users to the daily alpha / beta master builds, instead of waiting for the official Blender releases to gain access to new features.
Sculpt Mode development is currently predominantly led by the Spanish coder Pablo Dobarro. But he turns out not to be only talented Spanish developer who is expanding Sculpt Mode. While Pablo is an official Blender developer, Juan Fran Matheu is an independent developer who has created an extensive Blender add-on called Blender Atelier: Sculpt.
Custom Sculpt Mode UI
Blender Atelier: Sculpt provides an impressively comprehensive expansion of Blender's Sculpt Mode tools, and seamlessly combines them with Blender's own new Sculpt Mode features, starting with a custom UI that expands the top-side toolbar with a range of custom sculpting tools, as well as convenient shortcuts to a number of Blender's own Sculpt Mode tools.
The custom UI can also be customized to your personal preferences, and saved for reuse. Some of the custom UI options include:
- Quick Preferences: quickly adjust certain sculpting-related Blender Preferences, such as the Tablet Drag Treshold.
- Options to store your own Sculpt brush library, as well as the ability to easily render a custom brush icon.
- A recently used Sculpt brushes list.
- Right mouse-button / pen button controlled gestures for brush size and strength. Additionally, hold Alt to set the Smooth brush strength (activated by holding Shift). This feature is already very convenient by itself, and you quickly can't live without it anymore.
- Adjustable and storable Dyntopo presets.
- A number of the latest Blender 2.81 sculpting tools — such as mask tools — being easily accessible from the custom UI toolbar.
- An add-on update check.
- And more.
A section of Blender Atelier: Sculpt's custom top toolbar.
If you are accustomed to Blender Sculpt Mode's default top toolbar, you can easily deactivate the custom toolbars in the add-on preferences.
Expanded sculpting toolset
Next to UI customization, Blender Atelier: Sculpt offers a powerful set of tools to expand Sculpt Mode's native tools. There are additional Voxel remeshing options, including Reprojection to the original mesh and quick access to internal and external remeshers, such as Quadriflow and Instant Meshes.
Blender Atelier: Sculpt also offers a useful realtime Insert Object tool that is comparable to the Insert Mesh brushes in ZBrush. The Insert Object is a modal tool that includes powerful options such as post-Remeshing and Boolean operations, optionally even live Booleans, enabling you to subtract the inserted mesh from the main mesh.
Once a tool is activated, it often features on-screen instructions to control the result, such as the size of an inserted object.
Blender Atelier: Sculpt's Insert Object tool and its options.
There are multiple options to extract a mask to a new object, including the option to keep modifiers, so you can adjust some settings like thickness afterwards. There's also a Mesh Detacher, which cuts a masked part from your mesh and closes the underlying gap. If you use the Detach By Mask Islands option, each detached part will be separated to an individual object.
Blender Atelier: Sculpt also includes a Close Gaps tool, closing open areas in your mesh with an acceptable curvature reconstruction based on the surrounding areas. Then there's the Plot-Mesh Deployer, which scatters an object of your choice across the faces or vertices of a masked area. Once deployed, you can make use of several options to influence the result, including randomization options. When you're satisfied you can choose between three options how to establish the result, such as merging it with the main mesh.
The Plot Mesh Deployer in action. Several options are available, including randomization.
One of Blender Atelier: Sculpt's most powerful tools is the Sculpt Notes tool, offering the possibility to draw Annotation strokes on or outside a mesh surface and turn them into extruded shapes, polygon strips, beveled curves and more. This sub-toolset is too comprehensive to discuss in detail, but it is impressively versatile. A few examples:
Turn drawn Annotations into polygon strips, extruded shapes and more by using the Sculpt Notes tool.
Create a mesh using two drawn Annotations, one serving as a path and the other as a profile.
Blender Atelier: Sculpt is so extensive that covering every available option would make this review too lengthy, so let's conclude by summarizing a few more options:
- Rope tool for quick, post-editable, curved cables between two points on a surface.
- Adjustable custom mirror plane.
- Texture Preview, showing your active texture on the surface of your mesh.
- Mass-import of brush textures from a custom folder.
- Incremental Save button with your own suffix (like "_V" for version).
For an in-depth impression of all available options it is recommended to have a look at Blender Atelier: Sculpt's comprehensive online manual which also includes demonstration videos.
Shop links
Blender Atelier: Sculpt is available at Blender Market and Cubebrush.
Conclusion
8.5 Impressively versatile
Blender Atelier: Sculpt is an impressively versatile combination of sculpting tools and Sculpt Mode UI customization options. Because of the many custom UI entries and tool options, the add-on will require some time to get accustomed to, but for serious Sculpt Mode aficionados, Blender Atelier: Sculpt is definitely worth looking into. As the add-on is being actively developed, more functions will undoubtedly follow in the near future.
- Overall rating 8.5
- User Ratings (0 Votes) 0


This service is provided under an "as is" condition. It might change or will be discontinued without prior notice. The maker of this service can't be held liable in any way for any reason.
We limit ourselves to collect the smallest amount of user data that we need to create a seamless experience when using Talk. This data includes RTCICECandidates & RTCSessionDescription which is needed to establish the video call using WebRTC, your name & chat for a messaging experience inside the app. RTCICECandidates & RTCSessionDescription is not stored in any persistent database, it's removed from the server as soon as the user leaves the call by closing the browser window. Your chat messages, video & audio are all 100% peer-to-peer, meaning they never touch our server at all. We also collect your name which will be stored on your browser and used to identify the chat messages you send.
Talk is purely peer-to-peer, which means the user\'s video & audio is not sent to our server at all. We also use Cabin Analytics to track aggregated usage statistics in order to improve our service.
The makers of Talk have no intention of using personally or selling any of the above-mentioned data.


Covid Stores
Login
Admin login
Employee login
Our products
Furniture
Bags
GYM equipment
Appliances
Shoes
Previous
Next
Furniture
Modern grey sofa
9,000,000ugshs
Retro brown leather couch
5,450,000ugshs
Classic velvet bed
5,450,000ugshs
Dinning table
5,450,000ugshs
Bags
Modern grey travel bag
9,000,000ugshs
Travel set
5,450,000ugshs
Gym bag
5,450,000ugshs
Pink travel bag
100,000ugshs
GYM equipment
Yoga mats
9,000,000ugshs
Weights
5,450,000ugshs
Gym Bike
5,450,000ugshs
Gym outfit
150,000ugshs
Shoes
Stilettoes
90,000ugshs
Boots
250,000ugshs
sandals
150,000ugshs
Timberland boots
350,000ugshs
Appliances
LG home theatre
890,000ugshs
TV set
1,250,000ugshs
Microwave
550,000ugshs
Blender
350,000ugshs


--- layout: default title: Schedule permalink: /schedule/ ---
| Date | Description, Course Material |
|---|---|
| week1 | What is the Internet, What is a protocol? The Network Edge, Core, and Access Networks |
| week2 | Physical Media Delay, Loss and throughput in Packet-Switched Networks |
| week3 | Protocol Layers and Their Service Models The structure of the Internet A Brief History of Computer Networking and the Internet |
| week4 | Principles of Application-Layer Protocols The World Wide Web: HTTP |
| week5 | Week 5 Electronic Mail in the Internet The Internet's Directory Service: DNS |
| week6 | Peer-peer systems Socket Programming |
| week7 | Transport-Layer Services and Principles Multiplexing and De-multiplexing Applications Connectionless Transport: UDP |
| week8 | Principles of Reliable of Data Transfer TCP case study |
| week9 | Principles of Congestion Control TCP Congestion Control |
| week10 | Introduction and Network Service Model Routing Principles |
| week11 | Hierarchical Routing IP: the Internet Protocol |
| week12 | Routing in the Internet What is Inside a Router? Software Defined Networks |
| week13 | The Data Link Layer: Introduction, Services Error Detection and Correction Multiple Access Protocols and LANs |
| week14 | LAN Addresses and ARP Ethernet, VLANs A Day in the Life of an HTTP Request |


The content of the column can either be set via the text
attribute,
or via child components inside the column.
The headerText
is used as the row header, and the optional footerText
will be added as a tfoot
element at the end of the table.


Introduction - What Are They?
TYPE is your best friend. It is used to create a 'collection' of objects that share the same parameters and need to be interated through quickly and easily.
Think about SPACE INVADERS. There are many aliens on the screen at one time. Each of these aliens have a few variables that they all need: x and y coordinates plus a variable to control which graphic to display (legs out or legs in). Now, we could make hundreds of variables like invader1x, invader1y, invader2x, invader2y, etc. to control all the aliens, but that wouldn't make much sense would it? You could use an array to track them; invader(number,x,y,graphic), and the loop through them with a FOR ... NEXT loop but that is a lot of work! The TYPE variable collection was created to handle just this sort of need.
TYPE defines an object collection. Each object in that collection inherits its own copy of the variables defined by the TYPE's FIELD command. Each variable of each object in the collection can be read individually and can be easily iterated through quickly. Use the FIELD command to assign the variables you want between the TYPE and END TYPE commands.
If it helps, think of a TYPE collection as a database. Each object is a record of the database, and every variable is a field of the record. Using commands like BEFORE, AFTER, and FOR ... EACH, you can move change the pointer of the 'database' to point to a different record and retrieve/set the variable 'field' values.
Not a database guru? Need another example? Okay. Let's say you are setting up an auditorium for a speech or event and you are putting up hundreds of chairs for the spectators. The chairs have to be in a certain place on the floor, and some will need to be raised up a bit higher than others (visiting dignitaries, the mayor is coming, etc.). So being the computer genius you are, you start figuring out how you can layout the chairs with the least amount of effort. You realize that the floor is checkered, so its really a huge grid! This will make it easy! You just need to number the floor on a piece of graph paper and put into the grid how high each chair should be, based on where the boss told you the important people are to sit. So, for each chair, you will have a row and column on the graph paper (x and y location) and a level to adjust the chair to (height). Good, we are organized. Now, even though we have it all on paper, we still have to do the work of placing all the chairs.  Ah crap! You have them all perfect, and even though it is a simple thing to move a chair one square to the right (after all, their order and height won't change) - you still have to move each and every chair! Should would be nice if you could just wave your hand and say "For each chair in the room, add 1 square to its x location" and have it just magically happen. Alas, in the real world, get busy - you've got a lot of chairs to move!
In Blitz, you could have set up a TYPE called CHAIR, set the TYPE's FIELDS as X, Y, and HEIGHT. You would then create as many chairs as you need with the NEW command (each time you call NEW, it makes a new chair, with its OWN X, Y, and HEIGHT variables) and assign them the X, Y, and HEIGHT values you decide upon.
In our example above, when the boss told you to move the chairs over 1 box, you probably groaned inside. That's a lot of work! In Blitz, we could use four lines of code to adjust all our CHAIR objects to the new position (using FOR ... EACH commands).
Defining A Type
Custom types are defined using the 'Type' keyword. For example:
Type MyType
Field x,y
End TypeCreates a custom type called 'MyType' with 2 fields - x and y.
Fields within a custom type may themselves be of any basic type or custom type. Type tags are used to determine the type of a field. For example:
Type MyType
Field x,y
Field description$
Field delta_x#,delta_y#
End TypeCreating a Type Instance
You can create variables or arrays of custom types using a '.' type tag followed by the type name. For example:
Global mine.MyType Dim all_mine.MyType( 100 )
Before a custom type variable or array element can be used, it must be initialized using the 'New' operator. For example:
mine.MyType=New MyType
The 'New' operator creates an 'object' of type 'MyType', and returns a 'pointer' to the new object. The identifier following the 'New' operator must be a valid custom type name.
The fields within a custom type are accessed using the '\' character. For example: mine\x=100 Print mine\x
Destroying a Type Instance
When you've finished with an object, you should delete it using the 'Delete' command. For example:
Delete mine
This releases the memory used by the object.
Determining Existance
The special keyword 'Null' is used to represent non-existent objects. An object is non-existent if it hasn't been initialized yet using 'New', or has been released using 'Delete'. For example:
mine.MyType=New MyType
If mine<>Null
Print "exists!"
Else
Print "doesn't exist!"
EndIf
Delete mine
If mine<>Null
Print "exists!"
Else
Print "doesn't exist!"
EndIf...will print the following:
exists!
doesn't exist!Each custom type has an associated list of objects known as a 'type list'. When an object is created using 'New', it is automatically added to the type list. When an object is released using 'Delete', it is removed from the type list. This list is dynamic - once an instance has been deleted, its place in the collection is deleted and all the other objects after it will 'move up' in the collection hiearchy.
Iteration Through Type Lists
The 'First', 'Last', 'After' and 'Before' operators allow you to access type lists. The 'First' operator returns the object at the start of the type list. For example:
mine.MyType=First MyTypeThis sets the 'mine.MyType' variable to the first object of custom type 'MyType'.
Similarly, 'Last' returns the object at the end of the list.
If the type list is empty, 'First' and 'Last' return 'Null'.
You can use 'After' to find the object after an object, and 'Before' to find the object before an object.
For example:mine.MyType=First MyType ;mine=first object in the type list
mine=After( mine ) ;mine=second object
mine=After( mine ) ;mine=third object
mine=Before( mine ) ;mine=second object
mine=Before( mine ) ;mine=first again!'After' and 'Before' return 'Null' if there is no such object. For example:
mine.MyType=Last MyType ;mine=last object
mine=After( mine ) ;object after last does not exist!When an object is created using 'New', it is placed at the end of it's type list by default.
However, You can move objects around within the type list using Insert. For example:mine1.MyType=New MyType
mine2.MyType=New MyType
Insert mine2 Before mine1This has the effect of placing the 'mine2' object before the 'mine1' object in the type list.
You can also use 'After' instead of 'Before' with Insert.Here's an example of moving an object to the start of it's type list:
Insert mine Before First MyType
A special form of For...Next allows you to easily iterate over all object of a custom type. For example:
For mine.MyType=Each MyType
NextThis will cause the variable 'mine.MyType' to loop through all existing objects of cutom type MyType.
Finally, the 'Delete Each' command allows you to delete all objects of a particular type. For example:
Delete Each MyType


{{pageTitle}}
Back
ABOUT
Sessions
ALLSESSIONS
SESSIONSBYDAY
{{day.label}}
SESSIONSBYTRACK
{{track.name}}
FAVORITES
NOWNEXT
FEEDBACK
ABOUT
ALLSESSIONS
FAVORITES
NOWNEXT
FEEDBACK
Deutsch
English
SESSIONSBYDAY
{{day.label}}
SESSIONSBYTRACK
{{track.nameAbbr}}


NEW GAME
HIGHSCORES
MUTE
Highest scores in the history:
×
...
Your browser does not support the audio element.


_______________
...............
,,,,,,,,,,,,,,,
---------------
===============
"""""""""""""""
Distance
0
RUN
Hover Clicker Quantity:
0
cost:
10
Click Upgrade Quantity:
0
cost:
10
Idle Clicker 1 Quantity:
0
CPS
cost:
10
Idle Upgrade Quantity:
0
cost:
10
no
no
no


Last week, the party relaxed in Peloria before setting out on their next adventure. This lasted for about half a day before Silk called them into a meeting in a tavern. There, through a telepathic link, he informed them that both Zedar and Faren1 were working with the Orclund2. They are planning on convincing us to teleport into the Orclund to stop it, but would betray us when we arrived and use the orc army to kill us.
Silk told us that he was currently pretending to work with Zedar and Faren, but had the ability to trap Zedar's travelstone. When they teleport us into the Orclund, he could hijack the teleportation and come along himself with some of his bodyguards, which should allow us to reverse the trap and defeat Zedar and Faren. Alternately, we could refuse to teleport into the Orclund, and instead seek out the orcs we had met previously who were trying to break apart the Orclund's fragile alliance.
Faced with this haze of hidden alliances and betrayal around every corner, the party did what came naturally: start a bar fight, and then have a long committee meeting. Silk also introduced them to Talbot's brother, who was one of Silk's bodyguards and had been searching for Talbot for some time. Show up this week to help us figure out what to do!


Module for explaining pipes and all functionalities of custom displaying data on the Angular.
My birthday is {{ birthday | date }}
My birthday is {{ birthday | date:format }}
My chained birthday is {{ birthday | date:'fullDate' | uppercase }}
Super power boost: {{ 2 | exponentialStrength: 10 }}
New hero: can fly
Mutate array


Music
Compositions
Paroxysm (2014)
This was originally written as a harpsichord piece. However, after it was written, I decided that it sounded better on a piano.
MIDI Recording
Score
Drunken Waltz (2014)
I started writing this on a night bus in Vietnam. Part of the inspiration for the piece was the way the bus clumsily wrenched from side to side as it negotiated the unpaved road.
MIDI Recording
Score
Mazurka for Three Guitars (2014)
This piece was the result of a weekly challenge my friends and I established while traveling in Southeast Asia. The challenge was to create something that related to three randomly generated nouns. Here are the three nouns that inspired this piece, along with a description of why each one is relevant:
Polish - The piece is a mazurka, a folk dance of Polish origin.
Draw - The piece can be thought of as a battle between major and minor which ends in a draw.
Disease - I tried to create the musical equivalent of a healthy organism that gradually becomes infiltrated by harmful foreign agents.
Recording
Those Times When You Get to Fly in Your Dreams (2012)
The second piece I wrote for Cardinal Calypso, Stanford's steel drum ensemble. It features six pan players and an electric bass guitar.
Recording
Pan Funk (2011)
The first piece I wrote for Cardinal Calypso. It features three pan players and a drum set.
Recording
Toccata in E Flat Minor (2007)
A piece for solo piano.
Recording
Snow Days (2006)
A piece I wrote for my jazz combo. Features piano, double bass, and tenor saxophone.
Recording
Prelude in E Flat Minor (2006)
A piece for solo piano.
Recording
Sampling
Knees Disease (2014)
A song I produced using samples from "Layla" by Derek and the Dominos and "Come Together" by The Beatles.
Listen to my track here.
Original recordings (YouTube): "Layla", "Come Together"
Nephew's Mallets (2014)
A hip-hop beat I produced using samples from "Doses and Mimosas" by CHERUB.
Listen to my track here.
Original recordings (YouTube): "Doses and Mimosas"
That Rubber (2014)
A hip-hop beat I produced. The most prominent sample is from "Rubberband Man" by The Detroit Spinners. Also featured are samples from "Killing In The Name" by Rage Against the Machine, "Owner of a Lonely Heart" by Yes, "99 Problems" by Jay-Z and "Baptizing Scene" by Reverend W.A. Donaldson and Congregation.
Listen to my track here.
Original recordings (YouTube): "Rubberband Man", "Owner of a Lonely Heart", "99 Problems", "Baptizing Scene"
Seul (2014)
My first attempt at making a hip-hop beat. It features samples from Isao Tomita's cover of "Clair de Lune" by Claude Debussy and "Me Alone" by Gabo.
Listen to my track here.
Original recordings: "Clair de Lune" (YouTube), "Me Alone" (MP3)
Miscellaneous
Don't Know Why (2011)
For one of my sound recording classes at Stanford, I recorded myself playing guitar, bass guitar, drum set, and piano on a cover of "Don't Know Why" by Norah Jones. Arrangement based roughly on Pat Metheny's arrangement for solo baritone guitar.
Listen here.


Test your knowledge of Delta's airport codes in this fast-paced game of airport code action! Keep playing to beat your personal time and master all the delta airport codes! Select your region, or choose all regions to begin.
Africa, Caribbean, Central & South America, and the Middle East
North America (Northeast, Southeast, and Mexico)
North America (Southwest, Midwest, West, and Canada)
Europe, Asia, and Australia
0 Regions Selected
Gameplay tip: This game can be played with either a mouse or keyboard. For keyboard use, use the return key to 'check' your answer, and use the spacebar to activate the hint feature.
QUIT
Question: 01/50| Hints Used: 0
REGIONS INCLUDED IN THIS ROUND:
Africa, Caribbean, Central & South America, and the Middle East


From NILMTK toolkit. Assumes that appliances are aligned in the sets.
Takes an array of true positives, false negatives, true negatives, and false positives. Returns the Accuracy measure where accuracy is tp+tn/(tn+fn+tp+fp)
Takes an array of true positives, false negatives, true negatives, and false positives. Returns the f1 score based on precision and recall.
Returns a dictionary of numpy arrays containing the true positives a ‘tp’, the false negatives as ‘fn’, the true negatives as ‘tn’, and the false positives as ‘fp’. I would like to make this a truth table instead of putting the logic directly in the list comprehension.
Returns a dictionary of numpy arrays containing the true positives a ‘tp’, the false negatives as ‘fn’, the true negatives as ‘tn’, and the false positives as ‘fp’. I would like to make this a truth table instead of putting the logic directly in the list comprehension.
Given a numpy array of true positives, and false positives returns a precision measure. The precision measure is equal to TP/(TP+FP), where TP is a true positive, such that TP=1 when the predicted value was correctly classified as positive and 0 otherwise and FP is a false positive, such that FP = 1 if a value was falsely predicted to be positive and 0 otherwise.
Given a numpy array of true positives, and false negatives returns a sensitivty measure. Then the sensitivity is equal to TP/(TP+FN), where TP is a true positive, such that TP=1 when the predicted value was correctly classified as positive and 0 otherwise and FN is false negative, such that FN = 1 if a value was falsely predicted to be negative and 0 otherwise.
Given a numpy array of true negatives, and false positives returns a specificty measure. The specificity measure is equal to TN/(TN+FP), where TN is a true negative, such that TN=1 when the predicted value was correctly classified as negative and 0 otherwise and FP is a false positive, such that FP = 1 if a value was falsely predicted to be positive and 0 otherwise.


Explore Your Universe 2019
What is EYU?
Exploring Your Universe (EYU) is one of UCLA’s biggest annual events, drawing in thousands of children, parents, and friends from the Los Angeles community to our campus on the first Sunday in November. Organized by UCLA graduate students and run by volunteers, this science fair has been a tradition to provide a day of free science education to all. For ten years, EYU has provided fun, hands-on experiments and presentations to curious minds and young future scientists alike.
EYU 2019 was one of the main events in celebrating UCLA’s Centennial!
EYU & KGB Lab
The KGB Lab held the booth GEN31 Sweet and Cool Lab Blobs in Geology 3656, and here are some cool photos!
Image Credit: Xuesong Ding, Xiyuan Bao
In the afternoon, Matthew took the turn and introduced the shadowgraph and Hawaii:
Group photo of the lovely volunteers!
From Left to Right: Matthew Bogumil, Xiyuan Bao, Boontigan Kuhasubpasin, Arthur Lo, Xuesong Ding


When Mr. Bilbo Baggins of Bag End announced that he would shortly be celebrating his eleventy -first birthday with a party of special magnificence, there was much talk and excitement in Hobbiton.
Bilbo was very rich and very peculiar, and had been the wonder of the Shire for sixty years, ever since his remarkable disappearance and unexpected return. The riches he had brought back from his travels had now become a local legend, and it was popularly believed, whatever the old folk might say, that the Hill at Bag End was full of tunnels stuffed with treasure. And if that was not enough for fame, there was also his prolonged vigour to marvel at. Time wore on, but it seemed to have little effect on Mr. Baggins. At ninety he was much the same as at fifty. At ninety-nine they began to call him we//-preserved, but unchanged would have been nearer the mark. There were some that shook their heads and thought this was too much of a good thing; it seemed unfair that anyone should possess (apparently) perpetual youth as well as (reputedly) inexhaustible wealth.
…
The talk did not die down in nine or even ninety -nine days. The second disappearance of Mr. Bilbo Baggins was discussed in Hobbiton, and indeed all over the Shire, for a year and a day, and was remembered much longer than that. It became a fireside -story for young hobbits; and eventually Mad Baggins, who used to vanish with a bang and a flash and reappear with bags of jewels and gold, became a favourite character of legend and lived on long after all the true events were forgotten.
…
…


Jupyter + python + React using Comm¶
This is the most exciting step of our journey to master widget building process for Jupyter Notebook. In this cookbook you will find a way to open a communication between a python piece of code on your Notebook to a nbextension based on React. At the end, we will have a base project to create a widget on Jupyter using React, and Python. From that package, we should be able to create a first version of a boilerplate, easing the development of a new kind of ipywidget, based on React.
Set Up¶
first things first, what should we implement? Personnally, I would love to bring to Jupyter Environment the nice and good looking AppBar from Material UI. So, naturally, our project will be called Appbar.
mkdir appbar
cd appbar
Python Module part¶
This is probably the most simple part:
mkdir appbarpy
cd appbarpy
touch __init__.py main.py
mkdir static
JS part¶
As usual, lets create a basic setup for javascript:
cd ..
mkdir appbarjs
cd appbarjs
yarn init
touch index.js
From there, we should follow the instruction from react_nbextension_trial, and replace the names and paths accordingly to our configuration.
Note:Have in mind that the final goal is to put the webpack output files into the static folder of appbarpy, so consider dist folder is appbarpy/static.
at the end of this section, your project’s structure should look like the following:
tree -I node_modules appbar/
appbar/
├── appbarjs
│ ├── package.json
│ ├── src
│ │ ├── App.js
│ │ └── index.js
│ ├── webpack.config.js
│ └── yarn.lock
└── appbarpy
├── __init__.py
├── main.py
└── static
└── main.js
Nbextension install from Python¶
Hehe, so here begin our new journey to a React Comm implementation. If you already have used ipywidgets at least once, you might have noticed that to install a nbextension, you just have to run a setup.py file and enable it ! Whoaw mind blowing right?
Let’s try to do the same here, cause it’s quiet convenient. starting at the beginning, we should first read the documentation provided : jupyter notebook documenation
After reading it, you would have realize that what we want to accomplish here is described here.
More precisely, in our python package init.py file:
...
# Jupyter Extension points
def _jupyter_nbextension_paths():
return [dict(
section="notebook",
# the path is relative to the `my_fancy_module` directory
src="static",
# directory in the `nbextension/` namespace
dest="my_fancy_module",
# _also_ in the `nbextension/` namespace
require="my_fancy_module/index")]
...
So let’s transform that to our needs, and write in the appbarpy/__init__.py
:
def _jupyter_nbextension_paths():
return [
{
"section": "notebook",
"src": "static",
"dest": "appbar",
"require": "appbar/main"
}
]
According to documentation, we can now install this nbextension from the python module using:
jupyter nbextension install appbarpy --py --sys-prefix
jupyter nbextension enable appbarpy --py --sys-prefix
Let’s try it out right now, and see what happen:
jupyter nbextension install appbarpy --py --sys-prefix
...
ModuleNotFoundError: No module named 'appbarpy'
well that’s a simple one, we need python to be able to find our package. we have two options here:
option 1: quick and dirty we add path to appbarpy into PYTHONPATH, not very suistanable to on the long terme, but easy to do, quick to try out
option 2: the setup.py file, allowing us to use pip install -e nice one don’t you think?
Option 2 is the best long terme speaking, so long terme, we will go with this. But short terme we will setup the pythonpath and try it out directly to debug our current modification.
Option 1¶
echo $PWD
.../appbar
export PYTHONPATH=$PYTHONPATH:$PWD
jupyter nbextension install appbarpy --py --sys-prefix
...
jupyter nbextension enable appbarpy --py --sys-prefix
...
Enabling notebook extension appbar/main...
- Validating: OK
yay ! it worked, well at least it installed the nbextension.
let’s try it out into a notebook
jupyter notebook
and then you create a notebook from the manager.
Tadddaaaa it worked ! wouhou
Option 2¶
Option 1 was a handcraft, it’s was justified for quick testing, but you might find a bit tiring to set PYTHONPATH all the time. A solution would be to package it, using setuptool. It is obviously not an obligation to make it work, but it will come with some benefits which are: publishing it if you want, and ease its sharing with other people, include some script to ease install…
setup.py¶
if you haven’t package a python package python before, i recommend to read the official doc on that matter.
here below the content of my setup.py:
import setuptools
with open("README.md", 'r') as fh:
long_description = fh.read()
setuptools.setup(
name="appbar",
version="0.0.1",
author="Thomas Pouvreau",
<EMAIL_ADDRESS>description="a small example widget developped with React",
long_description=long_description,
long_description_content_type="text/markdown",
url="",
packages=setuptools.find_packages(),
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
python_requires='>=3.6',
)
In order for it work, I also added a small readme. right now there is pretty much nothing, but at somepoint it will be useful. Also, I added a MIT License as it is mentionned in doc.
what we want to do here is to leverage pip capabilities to make sure that when we install our package with pip install, it also install the nbextension so at the end, to install our project we just have to do:
pip install appbar
As we would with a custom widget from ipywidgets template.
On jupyter notebook documentation they are giving us an example on how you would do such a thing. According to this documentation, we need a appbar.json into appbar folder, containing this:
{
"load_extensions": {
"appbar/main": true
}
}
It is said to add to your setup few new arguments, which are include_package_data, data_files, zip_safe, here you will have our new setup.py:
import setuptools
with open("README.md", 'r') as fh:
long_description = fh.read()
setuptools.setup(
name="appbar",
version="0.0.1",
author="Thomas Pouvreau",
<EMAIL_ADDRESS>description="a small example widget developped with React",
long_description=long_description,
long_description_content_type="text/markdown",
url="",
include_package_data=True,
data_files=[
# like jupyter nbextension install --sys-prefix
("share/jupyter/nbextensions/appbar", ["appbarpy/static/main.js"]),
# like jupyter nbextension enable --sys-prefix
("etc/jupyter/nbconfig/notebook.d", ["appbar.json"])
],
packages=setuptools.find_packages(),
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
python_requires='>=3.6',
)
in addition, we need to create a MANIFEST.in file:
recursive-include appbar.json
recursive-include appbarpy/static *.js
for now we can test if it install normally with :
pip install .
jupyter nbextension list
first, make sure you have uninstall the nbextension and disable it: use jupyter nbextension disable then jupyter nbextension uninstall Normally here you will see that appbar/main is in the nbextension list, aaaand, if you try it in the notebook, your extension will still be there. Yay!
Entering the Fun part¶
Okay, so far we succeeded in creating a basic notebook extension, loading it from our python package and we also managed to automate the install process. What we need to do now is to initiate a communication with our Python package, receive it on the front end side and react accordingly.
Starting a communication from Kernel¶
Let’s do as we did before, which is create a communication channel from kernel.
for now, just add this in a your notebook. communication
will be the object
acting as a socket, which will allow you to communicate with the front end.
For now we will stick with it and later we will put it in a more sophisticated
object.
from ipykernel.comm import Comm
communication = Comm(target_name="appbar_comm",
data={"title": "this is the title"})
@communication.on_msg
def received(msg):
print(msg)
Receiving a communication within our front end objects¶
Okay so now is the tricky part: from jupyter notebook documentation on how to open a comm from the kernel, we can see that we have to register a target using Jupyter object imported dynamically. For our component to be able to work with it, we have several solutions:
one would be to put everything coming from the kernel into a Context, and then pass this context to the rest of the component subcomponent.
another one would be to use React composition pattern, and pass received data to children through props.
a third one would be to use a redux store, and it would be then very similar to how ipywidgets work. (store would took the model place)
This is a fundamental question on how we would like to build our future library: knowing that there are several ways to achieve the absolute same result, but with different levels of complexity, which one should we choose? Should we even choose one? Do we need to let developers access all these different ways of achieving it? If so why? And why not?
In this very example we will use the second option, for simplicity, but we keep in mind that there is at the very least, two other options to achieve it, and most likely several more.
So, for simplicity, we will create a comm and data object and pass it as props to App component.
In appbar/appbarjs/src/index.js
:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
let promise = import('base/js/namespace')
export const load_ipython_extension = () => {
promise.then( Jupyter => {
Jupyter.notebook.kernel.comm_manager.register_target('appbar_comm', function(comm, msg){
ReactDOM.render(<App comm={comm} data={msg.content.data}/>, document.getElementById('notebook-container'))
})
})
}
and then, in appbar/appbarjs/src/App.js
:
import React from 'react'
const App = (props) => {
return
 Hello, {props.data.title}!

}
export default App
we just need to rebuild in dev mode, and re install the nbextension.
cd appbar/appbarjs/
yarn dev
cd ..
pip uninstall appbar
pip install .
jupyter notebook test.ipynb
We see absolutly nothing… but, we need to instantiate from kernel remember? and, we are supposed to render once the connection is open, so let’s open a connection ! lets use the python snippet we defined earlier to create a comm from kernel, and put it in the first cell of test.ipynb. We launch it and bouyah! it’s working !!!
But… we just destroyed the notebook… maybe, it is time to think about how to target the cell output instead of destroying the whole notebook don’t you think?
Well I knew you would agree, moving on !
Cell output¶
Well well, in this wonderful project, we have a beginning of answer on how we could possibly do such a thing index.js, and it is referred right here:
...
const msg_id = msg.parent_header.msg_id;
const cell = Jupyter.notebook.get_msg_cell( msg_id );
...
then we have a bunch of functions to clear the cell output, to set it etc… on ipywidgets project, you will find something much more complex but very similar in the idea, so for now, we will stick to the most simple solution and see its limitation. but first, let’s print this cell, and see if we can render the react just after :)
So for it, I just printed the cell, and realized that there was an output_area inside. So I’ve sligthly changed index.js to that:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
let promise = import('base/js/namespace')
export const load_ipython_extension = () => {
promise.then( Jupyter => {
Jupyter.notebook.kernel.comm_manager.register_target('appbar_comm', function(comm, msg) {
const msg_id = msg.parent_header.msg_id
const cell = Jupyter.notebook.get_msg_cell(msg_id);
if(cell.output_area.selector[0]) {
const output = cell.output_area.selector[0].getElementsByClassName('output')[0]
ReactDOM.render(<App comm={comm} data={msg.content.data}/>, output)
}
})
})
}
If you recompile, build and run the notebook again, you will see text get inserted right under the cell.
Bi-directional communication¶
So far, we managed to :
create a nbextension using JSX and React
instantiate it from kernel leveraging Jupyter’s communication system
automate the install from python package using setup.py and some Jupyter’s config files
made sure that the widget print itself right under the notebook’s calling cell
Now, we want to :
make sure that we can communicate back to kernel from widget
update the widget from kernel
To make that happen, we will make a simple widget printing the number of click on a button.
Let’s change app.js to :
import React from 'react'
class App extends React.Component {
constructor(props) {
super(props)
this.state = {data: props.data}
this.handleMsg = this.handleMsg.bind(this)
this.handleClick = this.handleClick.bind(this)
props.comm.on_msg(this.handleMsg)
}
handleClick(e) {
this.props.comm.send("click")
}
handleMsg(msg) {
const data = msg.content.data
this.setState({data: data})
console.log("hey ! we received a msg")
}
render() {
return(

 Hello {this.state.data.title}!

<button onClick={ this.handleClick }> count +1 </button>

 count: {this.state.data.count}

)
}
}
export default App
What we are doing here is passing props.data to this.state at initialisation, then we handle the updates through this.handleMsg that we pass as callback to props.comm.on_msg method. So everytime we receive data, we update the state, and react take care of the rest !
Then we just have to update the python part:
Inside the test.ipynb:
from ipykernel.comm import Comm
data = {
"title": "this is the title",
"count": 0
}
communication = Comm(target_name="appbar_comm",
data=data)
@communication.on_msg
def received(msg):
data['count'] = data['count'] + 1
communication.send(data)
Click and the counter should get incremented. You may also evaluate data
in
a cell, click on the button and print again.
Creating a proper output area¶
Above we’ve explicitely set a margin with {{marginLeft: "150px"}}
in order to
fit the jupyter output area. Let’s now properly create all the elements that
make an output area:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
let promise = import('base/js/namespace')
const create_subarea = (output) =>{
const area = document.createElement('div')
area.classList.add('output_area')
output.appendChild(area)
const prompt = document.createElement('div')
prompt.classList.add('prompt')
prompt.classList.add('prompt_output')
area.appendChild(prompt)
const subarea = document.createElement('div')
subarea.classList.add('output_subarea')
area.appendChild(subarea)
return subarea
}
export const load_ipython_extension = () =>{
promise.then( Jupyter =>{
Jupyter.notebook.kernel.comm_manager.register_target('appbar_comm', function(comm, msg){
const msg_id = msg.parent_header.msg_id
const cell = Jupyter.notebook.get_msg_cell( msg_id );
if(cell.output_area.selector[0]){
const output = cell.output_area.selector[0].getElementsByClassName('output')[0]
const subarea = create_subarea(output)
ReactDOM.render(<App comm={comm} data={msg.content.data}/>, subarea)
}
})
})
}
Now the widget is displayed in a proper output area.
Appbar at last!¶
Now, let’s import Material-UI Appbar into our project.
Material-UI import:
cd appbar/appbarjs
yarn add @material-ui/core @material-ui/icons typeface-roboto
Insert import "typeface-roboto"
into index.js and modify App.js
like this:
import React from 'react'
import { makeStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
},
menuButton: {
marginRight: theme.spacing(2),
},
title: {
flexGrow: 1,
},
}));
function ButtonAppBar() {
const classes = useStyles();
return (

<AppBar position="static">
<Toolbar>
<IconButton edge="start" className={classes.menuButton} color="inherit" aria-label="menu">
<MenuIcon />
</IconButton>
<Typography variant="h6" className={classes.title}>
News
</Typography>
<Button color="inherit">Login</Button>
</Toolbar>
</AppBar>

);
}
class App extends React.Component{
constructor(props){
super(props)
this.state = {data: props.data}
this.handleMsg = this.handleMsg.bind(this)
this.handleClick = this.handleClick.bind(this)
props.comm.on_msg(this.handleMsg)
}
handleClick(e){
this.props.comm.send("click")
}
handleMsg( msg ){
const data = msg.content.data
this.setState({data: data})
console.log("hey ! we received a msg")
}
render(){
return(

<ButtonAppBar/>

 Hello {this.state.data.title}!

<button onClick={ this.handleClick }> count +1 </button>

 count: {this.state.data.count}

)
}
}
export default App
At this point it won’t compile since it needs a CSS loader:
yarn add style-loader css-loader file-loader --dev
Then in webpack.config.js add these rules:
// ...
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
'file-loader',
],
},
// ...
Then:
yarn build && cd .. && pip install . && jupyter notebook test.ipynb
You should now have a nice appbar printed on you notebook.
A further step would be to instantiate it and set events on it for nice rendering.


Annotation Processing with Kotlin
Annotation processors (see JSR 269) are supported in Kotlin with the kapt compiler plugin.
Being short, you can use libraries such as Dagger or Data Binding in your Kotlin projects.
Please read below about how to apply the kapt plugin to your Gradle/Maven build.
Using in Gradle
Apply the kotlin-kapt
Gradle plugin:
apply plugin: 'kotlin-kapt'
Or you can apply it using the plugins DSL:
plugins {
id "org.jetbrains.kotlin.kapt" version "1.2.60"
}
Then add the respective dependencies using the kapt
configuration in your dependencies
block:
dependencies {
kapt 'groupId:artifactId:version'
}
If you previously used the Android support for annotation processors, replace usages of the annotationProcessor
configuration with kapt
. If your project contains Java classes, kapt
will also take care of them.
If you use annotation processors for your androidTest
or test
sources, the respective kapt
configurations are named kaptAndroidTest
and kaptTest
. Note that kaptAndroidTest
and kaptTest
extends kapt
, so you can just provide the kapt
dependency and it will be available both for production sources and tests.
Annotation Processor Arguments
Use arguments {}
block to pass arguments to annotation processors:
kapt {
arguments {
arg("key", "value")
}
}
Java Compiler Options
Kapt uses Java compiler to run annotation processors.
Here is how you can pass arbitrary options to javac:
kapt {
javacOptions {
// Increase the max count of errors from annotation processors.
// Default is 100.
option("-Xmaxerrs", 500)
}
}
Non Existent Type Correction
Some annotation processors (such as AutoFactory
) rely on precise types in declaration signatures. By default, Kapt replaces every unknown type (including types for the generated classes) to NonExistentClass
, but you can change this behavior. Add the additional flag to the build.gradle
file to enable error type inferring in stubs:
kapt {
correctErrorTypes = true
}
Using in Maven
Add an execution of the kapt
goal from kotlin-maven-plugin before compile
:
<execution>
<id>kapt</id>
<goals>
<goal>kapt</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>src/main/kotlin</sourceDir>
<sourceDir>src/main/java</sourceDir>
</sourceDirs>
<annotationProcessorPaths>
<!-- Specify your annotation processors here. -->
<annotationProcessorPath>
<groupId>com.google.dagger</groupId>
<artifactId>dagger-compiler</artifactId>
<version>2.9</version>
</annotationProcessorPath>
</annotationProcessorPaths>
</configuration>
</execution>
You can find a complete sample project showing the use of Kotlin, Maven and Dagger in the Kotlin examples repository.
Please note that kapt is still not supported for IntelliJ IDEA’s own build system. Launch the build from the “Maven Projects” toolbar whenever you want to re-run the annotation processing.
Using in CLI
Kapt compiler plugin is available in the binary distribution of the Kotlin compiler.
You can attach the plugin by providing the path to its JAR file using the Xplugin
kotlinc option:
-Xplugin=$KOTLIN_HOME/lib/kotlin-annotation-processing.jar
Here is a list of the available options:
sources
(required): An output path for the generated files.classes
(required): An output path for the generated class files and resources.stubs
(required): An output path for the stub files. In other words, some temporary directory.incrementalData
: An output path for the binary stubs.apclasspath
(repeatable): A path to the annotation processor JAR. Pass as manyapclasspath
options as many JARs you have.apoptions
: A base64-encoded list of the annotation processor options. See AP/javac options encoding for more information.javacArguments
: A base64-encoded list of the options passed to javac. See AP/javac options encoding for more information.processors
: A comma-specified list of annotation processor qualified class names. If specified, kapt does not try to find annotation processors inapclasspath
.verbose
: Enable verbose output.aptMode
(required)stubs
– only generate stubs needed for annotation processing;apt
– only run annotation processing;stubsAndApt
– generate stubs and run annotation processing.
correctErrorTypes
: See below. Disabled by default.
The plugin option format is: -P plugin:<plugin id>:<key>=<value>
. Options can be repeated.
An example:
-P plugin:org.jetbrains.kotlin.kapt3:sources=build/kapt/sources
-P plugin:org.jetbrains.kotlin.kapt3:classes=build/kapt/classes
-P plugin:org.jetbrains.kotlin.kapt3:stubs=build/kapt/stubs
-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=lib/ap.jar
-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=lib/anotherAp.jar
-P plugin:org.jetbrains.kotlin.kapt3:correctErrorTypes=true
Generating Kotlin Sources
Kapt can generate Kotlin sources. Just write the generated Kotlin source files to the directory specified by processingEnv.options["kapt.kotlin.generated"]
, and these files will be compiled together with the main sources.
You can find the complete sample in the kotlin-examples Github repository.
Note that Kapt does not support multiple rounds for the generated Kotlin files.
AP/Javac Options Encoding
apoptions
and javacArguments
CLI options accept an encoded map of options.
Here is how you can encode options by yourself:
fun encodeList(options: Map<String, String>): String {
val os = ByteArrayOutputStream()
val oos = ObjectOutputStream(os)
oos.writeInt(options.size)
for ((key, value) in options.entries) {
oos.writeUTF(key)
oos.writeUTF(value)
}
oos.flush()
return Base64.getEncoder().encodeToString(os.toByteArray())
}


process module¶
-
class
pyrlang.process.
Process
(passive: bool = False)¶ Bases:
object
Implements Erlang process semantic and lifetime. Registers itself in the process registry, can receive and send messages. To optionally register self with a name, call
node.register_name(self, term.Atom('fgsfds'))
Subclass the Process to run your logic in its
_loop() -> bool
function or to handle incoming messages viahandle_one_inbox_message(self, msg)
.Note
Only a
Process
can serve as a target for sending messages, for linking and monitoring. You do not need to create a Process for simple one-way interactions with remote Erlang nodes.-
add_monitor
(pid: term.pid.Pid, ref: term.reference.Reference)¶ Helper function. To monitor a process please use Node's
monitor_process()
.
-
add_monitored_by
(pid: term.pid.Pid, ref: term.reference.Reference)¶ Helper function. To monitor a process please use Node's
monitor_process()
.
-
deliver_message
(msg)¶ Places message into the inbox, or delivers it immediately to a handler (if process is
passive
).
-
exit
(reason=None)¶ Marks the object as exiting with the reason, informs links and monitors and unregisters the object from the node process dictionary.
-
get_node
()¶ Finds current node from global nodes dict by
self.node_name_
. A convenient way to access the node which holds the current process. :rtype: pyrlang2.node.Node
-
handle_inbox
() → int¶ Do not override handle_inbox, instead go for handle_one_inbox_message :returns: How many messages have been handled
-
handle_one_inbox_message
(msg)¶ Override this method to handle new incoming messages.
-
async
handle_signals
()¶ Called from Node if the Node knows that there's a signal waiting to be handled.
-
inbox_
= None¶ Message queue. Messages are detected by the
_run
loop and handled one by one inhandle_one_inbox_message()
.
-
node_db
= <pyrlang.node_db.NodeDB object>¶
-
node_name_
= None¶ Convenience field to see the Node
-
passive_
= None¶ Having
passive=True
will only wake up thisProcess
when a message arrives, to handle it, otherwise it will not get any CPU time for any empty polling loops. Havingpassive=False
will runprocess_loop`()
polling inbox.
-
pid_
= None¶ Process identifier for this object. Remember that when creating a process, it registers itself in the node, and this creates a reference. References prevent an object from being garbage collected. To destroy a process, get rid of this extra reference by calling
exit()
and telling it the cause of its death.
-
async
process_loop
()¶ Polls inbox in an endless loop. .. note:
This will not be executed if the process was constructed with ``passive=True`` (the default). Passive processes should read their inbox directly from ``self.inbox_``.
-
async
receive
(match=None, timeout=None, timeout_callback=None)¶
-
remove_link
(pid)¶ Unlinks pid from this process. Please use Node method
unlink()
for proper unlinking.
-
remove_monitor
(pid: term.pid.Pid, ref: term.reference.Reference)¶ Helper function. To demonitor a process please use Node's
demonitor_process()
.
-
remove_monitored_by
(pid: term.pid.Pid, ref: term.reference.Reference)¶ Helper function. To demonitor a process please use Node's
demonitor_process()
.
-


US urges social media platforms to block Iran officials
by AFPWASHINGTON: The US State Department on Saturday called on Facebook, Instagram and Twitter to suspend the accounts of Iranian government leaders until Tehran re-establishes internet coverage throughout the riot-torn country.
The government imposed a near-total Internet blackout more than a week ago amid violent protests.
“It is a deeply hypocritical regime,” Brian Hook, special US representative for Iran, said in an interview with Bloomberg posted on the official State Department Twitter account.
“It shuts down the internet while its government continues to use all of these social media accounts.
“So one of the things that we are calling on are social media companies like Facebook and Instagram and Twitter to shut down the accounts of Supreme Leader Khamenei, the Foreign Minister Zarif and President Rouhani until they restore the internet to their own people.”
Demonstrations erupted in Iran on November 15, a few hours after the shock announcement of a decision to raise gasoline prices at the pump by up to 200 per cent in the sanctions-hit country.
The following day the government drastically restricted Iranians’ access to the internet in a step seen as aimed at curbing the spread of videos of the violent protests.
Five people have died in those protests by official government count, though Amnesty International has put the total at more than 100.
“The regime shut down the internet because they’re trying to hide all of the death and tragedy that the regime has been inflicting on thousands of protesters around the country,” Hook said.
Facebook and Instagram did not immediately respond to a request for comment from AFP, while Twitter said that it had no comment.
On Friday, the United States imposed sanctions on Iranian communications minister Mohammad Javad Azari Jahromi for what it said was his role in the “vast censorship” of the internet.
In a tweet Friday translated into Farsi, Secretary of State Mike Pompeo invited any Iranian who witnessed government “repression” to send documentation to the US, promising it would sanction any abuses.


public class SudokuSolver
extends java.lang.Object
The top level of the model, from where the Model is created and it's
attributes for the particular Sudoku puzzle loaded are applied, along with
any actions to take during solving.
This class holds the solving method that calls on each individual solving
algorithm as and when they are needed from the SudokuModel.
| Modifier and Type | Method and Description |
|---|---|
int[][] |
convertChar(char[][] lines)
After being passed a 2D array of Characters, the method creates a new 2D
array of Integers and begins converting the values.
|
Cell[][] |
getGrid()
A request to get the SudokuModel's grid, used by classes holding
reference to this class but not directly to the SudokuModel.
|
int |
getSteps() |
boolean |
isSolved()
Asks the SudokuModel if the puzzle is solved and returns a boolean answer
based on the response received.
|
Result |
returnResult() |
void |
setGrid(char[][] lines)
Sends a 2D Character array to a method to be converted into a 2D Integer
array and then sends this as an argument to the SudokuModel class to be
set as the current Cells to work with for solving a puzzle.
|
void |
setup()
Defines what a 'row', 'column' and 'block' is, adding each of them to a
single LinkedList holding all types.
|
void |
successfulMethod(java.lang.String msg)
Builds and returns the message based on the successful solving steps
taken.
|
java.lang.String |
takeStep()
When the request to 'take a step' in solving the Sudoku puzzle is called,
this method runs through the order of priority the solving algorithms
should be called in, and is written such that only one step can be taken
at a time, and only after those that have come before it have failed to
succeed.
|
public void setGrid(char[][] lines)
Sends a 2D Character array to a method to be converted into a 2D Integer
array and then sends this as an argument to the SudokuModel class to be
set as the current Cells to work with for solving a puzzle.
The char array comes from reading in a File where all text is stored as
char/Strings and needs converting in order to be used in the sudoku grid
as Integers with values.
lines
- - 2D Character array that will be converted into an array of
Integers in this class (see 'convertChar(char[][])') and sent
to the SudokuModel.public Cell[][] getGrid()
A request to get the SudokuModel's grid, used by classes holding reference to this class but not directly to the SudokuModel.
public java.lang.String takeStep()
When the request to 'take a step' in solving the Sudoku puzzle is called, this method runs through the order of priority the solving algorithms should be called in, and is written such that only one step can be taken at a time, and only after those that have come before it have failed to succeed.
In light of Complexity, I feel there is likely a much more efficient way of handling this request than 'if this, then do this', as if we wish to use the most advanced techniques, we must first attempt every other technique before it, adding complexity to each failed result. This would be addressed with more time on the project, however, my main goal was to address the data structures and individual solving algorithms on their own.
Each method creates it's own Result from running the method. More
information can be seen about this in the 'Result' class. However, these
contain information on whether the operation was a success, what message
to show the user and any Cells that were affected with updated
Values/solved.
With more time, I would expand into highlighting in text where the Cells
were updated, and also visually show which candidates would be removed.
public void setup()
Defines what a 'row', 'column' and 'block' is, adding each of them to a
single LinkedList holding all types.
Ordering: Row, Column, Row, Column, etc, ending with Column, Block,
Block.. Block.
public int[][] convertChar(char[][] lines)
After being passed a 2D array of Characters, the method creates a new 2D
array of Integers and begins converting the values.
The conversion is as simple as getting the numerical value of the
character, rather than it's Hex, Decimal or Octal value. The Numeric
value is quite literally 1 = 1, 2 = 2, 3 = 3, etc.
Any blank spaces are converted to -1, which are dealt with when passed to
the SolverModel.
The filled and resulting 2D array of Integers converted from the 2D Character array is returned to where it was called.
lines
- public boolean isSolved()
Asks the SudokuModel if the puzzle is solved and returns a boolean answer based on the response received.
public int getSteps()
public void successfulMethod(java.lang.String msg)
Builds and returns the message based on the successful solving steps taken.
msg
- public Result returnResult()


Sign in for the best experience
Create an account
Related to items you`ve viewed
Reebok shoe with hyper grip
₹ 1998.00 ₹ 1998.00
Reebok shoe with hyper grip
₹ 1998.00 ₹ 1998.00
Reebok shoe with hyper grip
₹ 1998.00 ₹ 1998.00
See More >>
Bestselling Mobile Phones
Reebok shoe with hyper grip
₹ 1998.00 ₹ 1998.00
Reebok shoe with hyper grip
₹ 1998.00 ₹ 1998.00
Reebok shoe with hyper grip
₹ 1998.00 ₹ 1998.00
See More >>
Shop Laptop By Brands
Explore all >>
Up to 40% off | Products from Small Businesses
Up to 60% off: Furniture
SOFAS
BEDS
DINNING SETS
FURNITURE
Explore all >>
Egate projectors : Up to 45% off + 1 year warranty
I9 LED HD PROJECTOR
ANDROID WIFI PROJECTOR
LED LCD PROJECTOR
LED 3D PROJECTOR
Explore all >>


Arch Linux for the Raspberry Pi A+
1 Creating the SD Card
1.1 A fork in the road
The instructions below are great if you've got a working Linux box and some
time to kill, but because that's not always the case. Someone somewhere on the
internet suggested grabbing the most recent Arch Linux ARM image (from
http://downloads.raspberrypi.org/arch/images/arch-2014-06-22/), write it do a
disk with dd
the old fashioned way, and run
$ sudo pacman -Syu
to bring it up to date. This sounds like a reasonable method to me.
1.1.1 The easy way1
- Download the
~/Downloads/ArchLinuxARM-2014.06-rpi.img.zip
.
Arch Linux ARM image linked above to somewhere
convenient like - Unzip the archive
$ unzip ~/Downloads/ArchLinuxARM-2014.06-rpi.img.zip -d ~/Downloads
(You can omit the
-d ~/Downloads
flag if you don't mind extracting to your current working directory, or you cancd ~/Downloads
before this step.) - Insert a micro SD card, and try to find its mount
point2:
$ diskutil list
and you'll see something like
/dev/disk0 #: TYPE NAME SIZE IDENTIFIER 0: GUID_partition_scheme *750.2 GB disk0 1: EFI EFI 209.7 MB disk0s1 2: Apple_HFS Foo 500.1 GB disk0s2 3: Apple_HFS Bar 249.6 GB disk0s3 /dev/disk1 #: TYPE NAME SIZE IDENTIFIER 0: GUID_partition_scheme *1.0 TB disk1 1: EFI EFI 209.7 MB disk1s1 2: Apple_HFS Baz 499.6 GB disk1s2 3: Apple_Boot Recovery HD 650.0 MB disk1s3 4: Microsoft Basic Data Qux 250.2 GB disk1s4 5: Microsoft Basic Data Blah 249.6 GB disk1s5 /dev/disk2 #: TYPE NAME SIZE IDENTIFIER 0: FDisk_partition_scheme *4.0 GB disk2 1: Windows_FAT_32 NO NAME 94.4 MB disk2s1 2: Linux 3.9 GB disk2s5
You want the root of the one that's clearly an SD card—in this case,
/dev/disk2
.3 - Unmount the micro SD card:
$ diskutil unmountDisk /dev/disk2
Note that in your case, the disk number maybe be different!
- Write the image to the file:
$ sudo dd bs=1m if=~/Downloads/ArchLinuxARM-2014.06-rpi.img of=/dev/rdisk2
(That
bs=1m
line is pretty important, and on OS X, them
is in fact lowercase.)This will take some time, but on OS X (and maybe Linux?), hitting CTRL-t will show you that something is happening, e.g.
load: 1.72 cmd: dd 28927 uninterruptible 0.00u 0.19s 210+0 records in 209+0 records out 219152384 bytes transferred in 45.639970 secs (4801764 bytes/sec)
In my case, the process took almost 7 minutes.
- Unmount the disk again:
$ diskutil unmountDisk /dev/disk2
- Put it in the A+, and you're (sort of) on your way!
1.2 The instructions per the Arch Linux ARM folks4
Replace <sdX>
in the following instructions with the device name for the SD card
as it appears on your computer.
- Start fdisk to partition the SD card:
$ fdisk /dev/<sdX>
- At the fdisk prompt, delete old partitions and create a new one:
- Type
o
. This will clear out any partitions on the drive. - Type
p
to list partitions. There should be no partitions left. - Type
n
, thenp
for primary,1
for the first partition on the drive, press ENTER to accept the default first sector, then type+100M
for the last sector. - Type
t
, thenc
to set the first partition to type W95 FAT32 (LBA). - Type
n
, thenp
for primary,2
for the second partition on the drive, and then press ENTER twice to accept the default first and last sector. - Write the partition table and exit by typing
w
.
- Type
- Create and mount the FAT filesystem:
$ mkfs.vfat /dev/<sdX>1 $ mkdir boot $ mount /dev/<sdX>1 boot
- Create and mount the ext4 filesystem:
$ mkfs.ext4 /dev/<sdX>2 $ mkdir root $ mount /dev/<sdX>2 root
- Download and extract the root filesystem (as root, not via sudo):
# wget http://archlinuxarm.org/os/ArchLinuxARM-rpi-latest.tar.gz # bsdtar -xpf ArchLinuxARM-rpi-latest.tar.gz -C root # sync
- Move boot files to the first partition:5
$ mv root/boot/* boot
- Unmount the two partitions:
$ umount boot root
- Insert the SD card into the Raspberry Pi, connect ethernet, and apply 5V power.
- Use the serial console or SSH to the IP address given to the board by your router. The default root password is 'root'.
2 Getting everything up and running
2.1 Turning it on
You'll want a powered USB hub, a wired USB keyboard (I had problems with my USB transceiver-based Microsoft Sculpt, but no problems with my old Apple wired keyboard), and a USB wifi dongle (I've always had good luck with the Edimax ones—they're ubiquitious and therefore well supported).
The login/password is root
.
2.2 Wireless networking
If you're using the Edimax wifi dongle, you shouldn't have any issues. Just check that it's connected with6
# dmesg | grep usbcore
or
# dmesg | grep rt18192cu
and hope you get results. If/when you do,
# cd /etc/netctl # cp examples/wireless-wpa <name>
Don't get too fancy with <name>
—I had trouble with matlock.home
, but not
with home
.
2.3 Add a user
Might as well make yourself a member of wheel
(this will come up later).
2.4 It's time to update Arch
# pacman -Syu
I couldn't even install sudo
without this, so it's pretty important. Anyway,
just say yes to everything (probably). It'll take awhile, but it'll also fix
tha nasty bash bug (shellshock?) among other things. In my case, there were 103
things that needed updating, which required downloading, unpacking, etc., so
yeah, it took quite awhile. (Don't be alarmed if the screen turns off—it's
just fallen asleep, so press a key to wake it up if you'd like.)
That whole process took somewhere between 30 minutes and an hours, I think.
2.5 Install sudo
# pacman -S sudo
2.6 Install emacs
Because trying to find stuff in nano
is terrible.
# pacman -S emacs
Ok, admittedly, 300+MB is a lot, especially when I haven't even expanded the
filesystem yet, but I just can't wrap my mind around vim
(nor do I especially
want to).
2.7 Configure sudo
You must use visudo
to edit the configuration file for sudo
, which lives
at /etc/sudoers
. Set emacs
as the visudo
editor:
# EDITOR=emacs visudo
To do this permanently, add these lines to the bottom of /etc/sudoers
:
# reset environment by default Defaults env_reset # set default EDITOR to emacs, and do not allow visudo to use EDITOR/VISUAL Defaults editor=/usr/bin/emacs, !env_editor
Despite what https://wiki.archlinux.org/index.php/sudo#Defaults_Skeleton says,
it looks like the !env_editor
, as well as a new line saying Defaults
!env_editor
causes visudo
to complain of a syntax error, so I guess you'll
just have to ignore that for now.
Now for the really important stuff: remember how you added yourself to the
group wheel
when you made your user account? wheel
is generally taken to be
the admin group. Find and uncomment the line
# %wheel ALL=(ALL) ALL
to give wheel
members sudo privileges.
Run
# sudo -ll
to verify that everything looks right.
At this point, you should log out of root
and log back in as <user>
. As a
result, the terminal prompt will be represented by $
instead of #
.
2.7.1 Disabling root
login
This is pretty important, but I think you'll do it in a bit over SSH. No,
just do this now. See
https://wiki.archlinux.org/index.php/sudo#Disable_root_login.
Since you're now logged in as a user, we'll have to use sudo
(and make sure
you do this as a user instead of root
to ensure you haven't messed anything
up!!).
$ sudo passwd -l root
2.8 Enable SSH access
Check systemctl
to see if an SSH daemon is running:
$ systemctl list-units | grep -i 'ssh'
sshd.service loaded active running OpenSSH Daemon
(That second line is the output I got, which shows that yes, an SSH daemon is running.)
Edit the SSH daemon config file with:
$ sudo emacs /etc/ssh/sshd_config
and add the lines
AllowGroups users wheel PermitRootLogin no # enable custom greeting Banner /etc/issue
and then edit /etc/issue
to your custom greeting:
$ sudo emacs /etc/issue
2.9 Change the hostname (optional, but recommended)
$ sudo hostnamectl set-hostname <new_hostname>
(I think you can also do this by editing /etc/hosts
and/etc/hostname
, but
using hostnamectl
seems like the right way to do it.)
2.10 SSH issues
At home, I had a problem with SSHing in like this:
$ ssh <me>@<hostname>
(we'll just say foo@bar
now), so I went over to the Pi and tried:
$ ip a
and saw a line that looked like
inet 10.0.1.<###>/<###> ...
and found that I could SSH in using
$ ssh<EMAIL_ADDRESS>At work this doesn't seem to be a problem, and it probably just means I need to configure my home network properly.
In any case, let's switch over to using the Pi through SSH.
3 Further necessary configuration
3.1 Install git
$ sudo pacman -S git
3.2 Install python
and useful related dependencies
$ sudo pacman -S python $ sudo pacman -S python-setuptools $ sudo pacman -S python-pip
3.3 A note
At this point I'm going to archive this image because I have not yet expanded
the drive to fill the partition. This could be handy later as there's less to
update, and I have important stuff like sudo
, emacs
, git
, and python
installed.
3.4 Add your GitHub SSH keys
3.5 Set up bash how you like it
3.6 Expand the root partition
Hopefully you've set things up so it's really obvious when you're root
now.
Quick note: I'm doing this with a 4GB drive, so your exact numbers will
probably vary slightly or even dramatically, depending on the vendor and size
of your drive. Note that a larger drive will make for longer dd
archive
times (I think—I'm at least 95% sure this is true).
- Log in as
root
:$ sudo su
- Run
fdisk
:# fdisk /dev/mmcblk0
- Print the partition table by entering command
p
:Welcome to fdisk (util-linux 2.25.2). Changes will remain in memory only, until you decide to write them. Be careful before using the write command. Command (m for help): p Disk /dev/mmcblk0: 3.7 GiB,<PHONE_NUMBER> bytes, 7744512 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x417ee54b Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 2048<PHONE_NUMBER>20 90M c W95 FAT32 (LBA) /dev/mmcblk0p2<PHONE_NUMBER>967 3481600 1.7G 5 Extended /dev/mmcblk0p5<PHONE_NUMBER>967 3479552 1.7G 83 Linux
- Delete partition 2 with command
d
, then selection2
:Command (m for help): d Partition number (1,2,5, default 5): 2 Partition 2 has been deleted.
- Recreate the extended partition. Add a new partition with command
n
, then selectione
, then number2
, then using the default selection at the next two prompts by pressing<ENTER>
for each:Command (m for help): n Partition type p primary (1 primary, 0 extended, 3 free) e extended (container for logical partitions) Select (default p): e Partition number (2-4, default 2): 2 First sector<PHONE_NUMBER>511, default 186368): Last sector, +sectors or +size{K,M,G,T,P}<PHONE_NUMBER>511, default 7744511): Created a new partition 2 of type 'Extended' and of size 3.6 GiB.
- Delete the root partition with command
d
, then selection5
.Command (m for help): d Partition number (1,2,5, default 5): 5 Partition 5 has been deleted.
- Recreate the root partition following a similar process to creating the
extended partition. Add a new partition with command
n
, then selectionl
, then<ENTER>
for the next two prompts:Command (m for help): n Partition type p primary (1 primary, 1 extended, 2 free) l logical (numbered from 5) Select (default p): l Adding logical partition 5 First sector<PHONE_NUMBER>511, default 188416): Last sector, +sectors or +size{K,M,G,T,P}<PHONE_NUMBER>511, default 7744511): Created a new partition 5 of type 'Linux' and of size 3.6 GiB.
- We haven't written our changes yet, so let's make sure everything looks
right by entering command
p
:Command (m for help): p Disk /dev/mmcblk0: 3.7 GiB,<PHONE_NUMBER> bytes, 7744512 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x417ee54b Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 2048<PHONE_NUMBER>20 90M c W95 FAT32 (LBA) /dev/mmcblk0p2<PHONE_NUMBER>511 7558144 3.6G 5 Extended /dev/mmcblk0p5<PHONE_NUMBER>511 7556096 3.6G 83 Linux
Looks good to me!
- Write our changes with command
w
:Command (m for help): w The partition table has been altered. Calling ioctl() to re-read partition table. Re-reading the partition table failed.: Device or resource busy The kernel still uses the old table. The new table will be used at the next reboot or after you run partprobe(8) or kpartx(8).
(I think this is actually ok.)
- Reboot the system:
# reboot
- Wait for the Pi to reboot, SSH back into it, and log back in as root:
$ sudo su
- Run
df
to see what the filesystem looks like now:# df Filesystem 1K-blocks Used Available Use% Mounted on /dev/root 1679632 1276676 299584 81% / devtmpfs 88424 0 88424 0% /dev tmpfs 92644 0 92644 0% /dev/shm tmpfs 92644 280 92364 1% /run tmpfs 92644 0 92644 0% /sys/fs/cgroup tmpfs 92644 0 92644 0% /tmp /dev/mmcblk0p1 91962 25948 66014 29% /boot tmpfs 18532 0 18532 0% /run/user/1000
81% used! That's a lot! (Thanks, Emacs.)
- Use
resize2fs
to finally apply our changes:# resize2fs /dev/mmcblk0p5 resize2fs 1.42.12 (29-Aug-2014) Filesystem at /dev/mmcblk0p5 is mounted on /; on-line resizing required old_desc_blocks = 1, new_desc_blocks = 1 The filesystem on /dev/mmcblk0p5 is now 944512 (4k) blocks long.
- Just out of curiosity, let's recheck the filesystem with
df
:# df Filesystem 1K-blocks Used Available Use% Mounted on /dev/root 3688608 1277524 2229996 37% / devtmpfs 88424 0 88424 0% /dev tmpfs 92644 0 92644 0% /dev/shm tmpfs 92644 280 92364 1% /run tmpfs 92644 0 92644 0% /sys/fs/cgroup tmpfs 92644 0 92644 0% /tmp /dev/mmcblk0p1 91962 25948 66014 29% /boot tmpfs 18532 0 18532 0% /run/user/1000
37% is somewhat more reasonable.
3.7 Make sure your important variables are set
E.g. PATH
, PYTHONPATH
, etc. My bash configuration takes care of this.
3.8 Install GNU Make
$ sudo pacman -S make
3.9 Install tree
(because trees are pretty) and Midnight Commander
$ sudo pacman -S tree $ sudo pacman -S mc
3.10 Install ack
because it's incredibly helpful
$ sudo pacman -S ack
3.11 Install gcc
$ sudo pacman -S gcc
3.12 Install wiringPi
$ git clone git://git.drogon.net/wiringPi $ cd wiringPi $ ./build
3.13 Install i2ctools
$ sudo pacman -S i2c-tools
and verify that it works with
$ sudo i2cdetect -y 1 Error: Could not open file `/dev/i2c-1' or `/dev/i2c/1': No such file or directory
That's not ideal.

Still, you want this to work on startup. Try:
$ systemctl list-units | grep ntp
And you'll probably see nothing. Do
$ sudo systemctl enable ntpd
and everything should work as expected.
To set up the timezone, first check where it's currently set with
$ timedatectl status
and we see that it's set for Denver. To fix that, do:
$ sudo timedatectl set-timezone $(timedatectl list-timezones | grep <your city>)
3.15 Install wiringpi2
$ cd ~ $ git clone git@github.com:Gadgetoid/WiringPi2-Python.git $ cd WiringPi2-Python $ sudo python setup.py install
(I originally tried to set this up using HTTPS instead of SSH, but because I haven't set up the clock yet, the device is still stuck in the late 60s/early 70s, so the SSL key was showing up as not yet valid.)
Actually, the whole thing didn't work because I didn't have the clock set up
yet. In fact, I had to rm -r
the whole thing and re-clone it because the
setup.py
script didn't like the pre-1980 timestamps.
When you see
Installed /usr/lib/python3.4/site-packages/wiringpi2-1.0.10-py3.4-linux-armv6l.egg Processing dependencies for wiringpi2==1.0.10 Finished processing dependencies for wiringpi2==1.0.10
you're probably fine, but let's test it out anyway:
$ python Python 3.4.2 (default, Oct 9 2014, 07:20:34) [GCC 4.8.2 20131219 (prerelease)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import wiringpi2 >>>
No ImportError
means we're good to go.
And I think that's all there is to it for now. Let's back it up again and get cracking.
Footnotes:
Done on a MacBook Pro running OS 10.9.5. There are probably a million ways to do this, but here's mine.
This is a little different on Linux. From
what I recall, on elementary OS (an Ubuntu derivative), it's probably going
to be somewhere like /media/<device_name>
, although I may be mistaken—I
mostly do this sort of thing in OS X.
In OS X, at least, what you really want is
/dev/rdisk2
when you're doing th writing. It's the raw disk, and it's
much faster
http://archlinuxarm.org/platforms/armv6/raspberry-pi on . These instructions seem to change often enough that it seems prudent to record them verbatim here.
I'm unclear whether or not this is as root or the user
#
means root
, $
means some
user
From http://raspberrypi.stackexchange.com/questions/266/how-can-i-keep-system-time and my earlier notes


Group makeup barely matters at low keystone levels. There is little reason to sweat your group composition on keys below 15. Bring the player, not the class.
That being said, your group composition will always be one tank, one healer, and three DPS. Multi-tank strategies are not viable, no matter how much you think they should be.
It's important to build a group that is well rounded in order increase your chances of completing a keystone within the timer. This means bringing consumables to make up for gaps in your group composition.
When considering your group composition, it is important to consider what each class can bring to the table. Does your group have:
Selecting your group carefully matters mostly for higher level keys where the difficulty of the run is often very high. For lower level keystone runs, group makeup is not as important. Just saying.
Most of the time when you apply to a key, 100 other people apply to the same key and your application gets buried.
Unfortunately, lots of people want to do keys and people running groups have the luxury of choosing people that may be better geared than you or have a higher Mythic+ rating than you.
There are a few ways to ensure you can get into keys:
Grinding out score can be frustrating when it takes 45 minutes to find a group, especially when it's a key you need and the group disbands after one mistake. All you can do is try your best. I got declined from over 600+ Mythic+ group applications throughout Shadowlands. I promise not everyone out there is an elitist that's out to get you.


This example contains the bare minimum includes and markup required to run a reveal.js presentation.
There's no theme included, so it will fall back on browser defaults.


Server Architecture¶
This chapter is a “deep dive” into Bokeh server’s internals... it assumes you’re already familiar with the information on Bokeh server in the User Guide.
You might want to read this if:
- you’re trying to work on the Bokeh codebase
- you’re trying to write your own custom server process to use rather than
bokeh serve
A custom server process can add additional routes (web pages or REST endpoints) using Tornado’s web framework.
The public API of Bokeh server is the Server
class (source). The
bokeh serve
command wraps Server
(source). Server
is intended to hide some of the Tornado implementation
details... most of the server implementation is in
BokehTornado
which subclasses Tornado’s TornadoApplication
type (source).
BokehTornado
isn’t meant to be a public API.
If an application developer uses bokeh serve
they shouldn’t
need to import the bokeh.server
package at all... they can
ignore it entirely. An application developer would only use the
Server
class if they are doing something custom, such as a
custom server process.
Applications, Sessions, and Connections¶
Each server contains one or more applications; you can think of an
application as a session template, or a factory for
sessions. Sessions have a 1-1 relationship with instances of
bokeh.document.Document
: each session has a document
instance. When a browser connects to the server, it gets a new
session; the application fills in the session’s document with
whatever plots, widgets, or other content it desires. The
application can also set up callbacks, to run periodically or to
run when the document changes.
Applications are represented by the Application
class (source). This
class is little more than a list of Handler
instances (source).
Handlers can be created in lots of ways; from JSON files, from
Python functions, from Python files, and perhaps many more ways in
the future.
Around each application, the server creates an
ApplicationContext
(source),
its primary role is to hold the set of sessions for the
application.
Sessions are represented by class ServerSession
(source).
Each application has a route (called an app_path
in the client
API), and each session has an ID. The combination of the two
specifies a Document
instance (the server looks up the
application by path, and then looks up the session by ID).
Each session has 0-N connections, represented by the
ServerConnection
class (source). Connections
are websocket connections. In general, sessions last as long as
they have connections, though they only expire after a timeout (to
allow for page reloads and the like).
Applications and application handlers cannot access the Server
ServerSession
, or ApplicationContext
directly; they have a
much more limited interface defined in two pieces,
ServerContext
(source)
and SessionContext
(source). ServerContext
presents a limited interface to some aspects of
ApplicationContext
and Server
, while SessionContext
presents a limited interface to some aspects of
ServerSession
. Concrete implementations of these interfaces
are BokehServerContext
(source)
and BokehSessionContext
(source).
Summarizing the object graph:
Server
implemented byBokehTornado
- has N
ApplicationContext
- has 1
Application
capable of creating new sessions- has 1 path used to identify it in URLs
- has 1
ServerContext
representing the aspects of the server visible to application code- has N
ServerSesssion
- has 1 session ID which is a string naming the session
- has 1
Document
representing the session state- has N
ServerConnection
representing websockets attached to the session- has 1
SessionContext
representing the aspects of the session visible to application code
Tornado IOLoop
and Async Code¶
To work on the server, you’ll need an understanding of Tornado’s
IOLoop
and the tornado.gen
module.
The Tornado documentation will be the best resource, but here are some quick things to know:
- the Bokeh server is single-threaded, so it’s important not to write “blocking” code, meaning code that uses up the single thread while it waits for IO or performs a long computation. If you do this, you’ll rapidly increase the latency seen by users of your application. For example, if you block for 100ms every time someone moves a slider, and ten users are doing this at once, users could easily see 10*100ms=1s of lag... with only ten users.
- in Tornado, nonblocking code is modeled with functions or
methods that return an instance of the
Future
class. You may have seen<EMAIL_ADDRESS>decorator, which transforms the decorated method into a method which returns aFuture
. - when no code is running, Tornado waits in its
IOLoop
(sometimes called a “main loop” or “event loop”), which means it’s waiting for something to happen. When something happens,IOLoop
executes any callbacks that were interested in that event.
Applications and the IOLoop
¶
We don’t want applications to touch the Tornado IOLoop
directly to add callbacks, because when a session expires or an
application is reloaded, we need the ability to remove all
callbacks belonging to a session or application.
To enable this, applications should only add callbacks using the
APIs on Document
and ServerContext
. Methods on those
classes allow applications to add_periodic_callback
,
add_timeout_callback
, and add_next_tick_callback
. We
intercept these callback additions and are able to remove them
when we unload an application or destroy a session.
Lifecycle¶
If you look at the Application
class (source),
there are two ways the server can call into it.
- the modify_document() method which does just what it says: it passes in the session’s Document and allows the application to modify it (perhaps adding some plots and widgets).
- a set of “hooks” on_server_loaded(), on_server_unloaded(), on_session_created(), on_session_destroyed().
The “hooks” are called “lifecycle hooks” since they happen at defined points in the lifetime of an application and a session.
Here are the steps in the lifecycle:
- When the server process starts up, it calls on_server_loaded() on each application.
- When a client connects with a previously-unused session ID, the
server creates a
ServerSession
and calls on_session_created() with an empty Document, then modify_document() to initialize the Document. The on_session_created() can also initialize part of the Document if it likes. on_session_created() happens before modify_document(). - When there are no connections to a session, it will eventually time out and on_session_destroyed() will be called.
- If the server process shuts down cleanly, it will call on_server_unloaded() on each application. This is probably rare in production: it’s typical for server processes to be killed by a signal. on_server_unloaded() may be more useful during development so that apps can be reloaded without leaking resources (in 0.11, dynamic reloading of applications hasn’t been implemented, but we’d like to add it).
These hooks can add periodic or one-shot callbacks to the
ServerContext
. These callbacks may be asynchronous (using
Tornado’s async IO facilities), and are able to update all live
session documents.
Critical consideration when using ``on_server_loaded()``: Process-global is NOT the same as cluster-global. If you scale a Bokeh application, you’ll want a separate process for each CPU core, roughly. Processes in a cluster may not even be on the same machine. A server process can never assume that it knows about “all sessions that exist,” only “all sessions hosted in this process.”
Details of ServerSession
¶
The session object handles most interaction between the client and the server.
Locking¶
The trickiest aspect of ServerSession
may be locking. In
general, we want one callback or one websocket request to be
processed at a time; we don’t want to interleave them, because it
would be difficult to implement callbacks and request handlers if
they had to worry about interleaving.
So ServerSession
does one thing at a time, controlled by
ServerSession._lock
, which is a Tornado lock.
If you’re familiar with locking and threads, the situation here is
conceptually identical; but race conditions can only happen at
“yield points” (when we return to the IOLoop
) rather than at
any point, and the lock is a Tornado lock rather than a thread
lock.
The rule is: to touch ServerSession.document code must hold ServerSession._lock.
For callbacks added through the Document
API, we automatically
acquire the lock on the callback’s behalf before we execute the
callback, and release it afterward.
For callbacks added through the ServerContext
API, they can
only obtain a reference to the session document using the
SessionContext.with_locked_document()
method (source). with_locked_document()
executes a function with the document lock held, passing the
document to that function. The lock is held while the function
runs (even if the function is asynchronous! if the function
returns a Future
, the lock is held until the Future
completes).
It is very easy to modify the server code in such a way that you’re touching the document without holding the lock. If you do this, things will break in subtle and painful-to-debug ways. When you touch the session document, triple-check that the lock is held.
Session Security¶
For background on session IDs, check out the bokeh serve
documentation on it.
We rely on session IDs being cryptographically random and difficult to guess; if an attacker knows someone’s session ID, they can eavesdrop on or modify the session. If you’re writing a larger web app with a Bokeh app embedded inside, this may affect how you design your larger app.
When hacking on the server, for the most part session IDs are opaque strings and after initially validating the ID, it doesn’t matter to the server code what the ID is.
Session Timeout¶
To avoid resource exhaustion, the server times out unused sessions. You can find the code for this in application_context.py.
Websocket Protocol¶
The server has a websocket connection open to each client (each
browser tab, in typical usage). The primary role of the websocket
is to keep the session’s Document
in sync between the client
and the server.
There are two client implementations in the Bokeh codebase; one is
a Python ClientSession
(source),
the other is a JavaScript (via CoffeeScript ClientSession
(source).
Client and server sessions are mostly symmetrical; on both sides,
we are receiving change notifications from the other side’s
Document
, and sending notification of changes made on our
side. In this way, the two Document
are kept in sync.
The Python implementation of the websocket protocol can be found
in bokeh.server.protocol
, though both the client side and the
server side use it (source).
Websockets already implement “frames” for us, and they guarantee frames will arrive in the same order they were sent. Frames are strings or byte arrays (or special internal frame types, such as pings). A websocket looks like a two sequences of frames, one sequence in each direction (“full duplex”).
On top of websocket frames, we implement our own Message
concept (source). A
Bokeh Message
spans multiple websocket frames. It always
contains a header frame, metadata frame, and content frame. These
three frames each contain a JSON string. The code permits these
three frames to be followed by binary data frames, but in Bokeh
0.11 binary data frames are not used.
The header frame indicates the message type and gives messages an ID. Message IDs are used to match replies with requests (the reply contains a field saying “I am the reply to the request with ID xyz”).
The metadata frame has nothing in it for now, but could be used for debugging data or another purpose in the future.
The content frame has the “body” of the message.
There aren’t many messages right now. You can find them all here but a quick overview:
ACK
is used for an initial handshake when setting up the connectionOK
is a generic reply when a request doesn’t require any more specific replyERROR
is a generic error reply when something goes wrongSERVER-INFO-REQ
andSERVER-INFO-REPLY
are a request-reply pair where the reply contains information about the server, such as its Bokeh versionPULL-DOC-REQ
asks to get the entire contents of the session’sDocument
as JSON, andPULL-DOC-REPLY
is the reply containing said JSON.PUSH-DOC
sends the entire contents of the session’sDocument
as JSON, and the other side should replace its document with these new contents.PATCH-DOC
sends changes to the session’s document to the other side
Typically, when opening a connection one side will pull or push
the entire document; after the initial pull or push, the two sides
stay in sync using PATCH-DOC
messages.
Some Current Protocol Caveats¶
- In the current protocol, conflicts where both sides change the
same thing at the same time are not handled (the two sides can
end up out-of-sync if this happens, because the two
PATCH-DOC
are in flight at the same time). It’s easy to devise a scheme to detect this situation, but it’s less clear what to do when it’s detected, so right now we don’t detect it and do nothing. In most cases, applications should avoid this situation because even if we could make sense of it and handle it somehow, it would probably be inefficient for the two sides of the app to “fight” over the same value. (If real-world applications trip on this issue, we will have to figure out what they’re trying to do and devise a solution.) - At the moment, we are not smart about patching collections; if
there’s a
Model
property that’s a giant dictionary, we’ll send the whole giant dictionary whenever any entry in it changes. - At the moment, we do not optimize binary data by sending it over binary websocket frames. If we did, we could copy it directly into typed arrays on the JavaScript side.
HTTP Endpoints¶
The server only supports a few HTTP routes; you can find them in
bokeh.server.urls
(source).
In brief:
/static/
serves Bokeh’s JS and CSS resources/app_path/
serves a page that displays a new session/app_path/ws
is the websocket connection URL/app_path/autoload.js
serves a chunk of JavaScript that backs thebokeh.embed.autoload_server()
functionality
Bokeh server isn’t intended to be a general-purpose web
framework. You can however pass new endpoints to Server
using
the extra_patterns
parameter and the Tornado APIs.
Testing¶
To test client-server functionality, use the utilities in
bokeh.server.tests.utils
(source).
Using ManagedServerLoop
, you can start up a server instance
in-process; share server.io_loop
with a client and you can
test any aspect of the server. Check out the existing tests for
lots of examples. Anytime you add a new websocket message or http
endpoint, be sure to add tests!


Home
Track
Resources
Rankings
Log out
Purple Cobras
Oakland Tech High
github.com/johnDoe
Track Design
TBA
Track Specs
Spotify Free
$0.00
/month
This is some text inside of a div block.
Shuffle play
Ad free
Unlimited skips
Listen offline
Play any track
High quality audio
GET FREE
Spotify Premium
$9.99
/month
Start your 30 day free trial*
Shuffle play
Ad free
Unlimited skips
Listen offline
Play any track
High quality audio
GET PREMIUM
Toad's Turnpike
25 January 2019
Specs subject to change before upcoming round.
Width: 1.8 meters
Border: 25 -35mm wide, white tape
Center Line: 35 - 55mm wide, yellow tape. Line is dashed with 20mm length tape. 20mm gaps between each.
1 left turn
1 right turn
1 hairpin turn (1.5m outside radius)
1 gradual turn (>3m outside radius)
Complete Registration
Total Points
25
Races Completed
1
Region Rank
12
Team Stats refresh after each round.
Dashboard
Rules
Resources
Race Upload
Rankings


Class: Log Abstract Deprecated
| Defined in: | source/javascripts/animal.coffee |
Overview
Deprecated.
This class is not used anymore
This
class
is abstract.
Each animal implementation must inherit from {Animal}
TODO:
Provide more examples
Note:
This is not used for codo, its purpose is to show all possible tags within a class.
Base class for all animals.
Examples:
How to subclass an animal
class Lion extends Animal
move: (direction, speed): ->
Instance Method Summary
- - (void) log() This will log something to the console
Instance Method Details
- (void) log()
This will log something to the console


--- sort_order: 4 tei_id: rdx_b5j2m.p.idm199454864 annotation_count: 0 images: small-thumbnail: http://readux.library.emory.edu/books/emory:b5j2m/pages/emory:p73d4/mini-thumbnail/ json: http://readux.library.emory.edu/books/emory:b5j2m/pages/emory:p73d4/info/ full: http://readux.library.emory.edu/books/emory:b5j2m/pages/emory:p73d4/fs/ page: http://readux.library.emory.edu/books/emory:b5j2m/pages/emory:p73d4/single-page/ thumbnail: http://readux.library.emory.edu/books/emory:b5j2m/pages/emory:p73d4/thumbnail/ title: Page 4 number: 4 ---


udev_selinux
Section: udev SELinux Policy documentation (8)Updated: udev
Index Return to Main Contents
NAME
udev_selinux - Security Enhanced Linux Policy for the udev processesDESCRIPTION
SELinux Linux secures udev (Policy for udev) processes via flexible mandatory access control.
FILE CONTEXTS
SELinux requires files to have an extended attribute to define the file type.You can see the context of a file using the -Z option to lsP Policy governs the access confined processes have to these files. SELinux udev policy is very flexible allowing users to setup their udev processes in as secure a method as possible.
The following file types are defined for udev:
udev_etc_t
- Set files with the udev_etc_t type, if you want to store udev files in the /etc directories.
udev_exec_t
- Set files with the udev_exec_t type, if you want to transition an executable to the udev_t domain.
- Paths:
-
/sbin/udevd, /sbin/start_udev, /sbin/udevsend, /usr/bin/udevinfo, /sbin/udev, /sbin/udevstart, /sbin/wait_for_sysfs, /lib/udev/udev-acl, /sbin/udevadm
udev_helper_exec_t
- Set files with the udev_helper_exec_t type, if you want to transition an executable to the udev_helper_t domain.
- Paths:
-
/etc/udev/scripts/.+, /etc/hotplug.d/default/udev.*, /etc/dev.d/.+
udev_tbl_t
- Set files with the udev_tbl_t type, if you want to treat the files as udev tbl data.
- Paths:
-
/dev/.udevdb, /dev/.udev(/.*)?, /dev/udev.tbl
udev_var_run_t
- Set files with the udev_var_run_t type, if you want to store the udev files under the /run directory.
- Paths:
-
/var/run/PackageKit/udev(/.*)?, /etc/udev/rules.d(/.*)?, /var/run/libgpod(/.*)?
Note: File context can be temporarily modified with the chcon command. If you want to permanently change the file context you need to use the semanage fcontext command. This will modify the SELinux labeling database. You will need to use restorecon to apply the labels.
PROCESS TYPES
SELinux defines process types (domains) for each process running on the systemYou can see the context of a process using the -Z option to psP Policy governs the access confined processes have to files. SELinux udev policy is very flexible allowing users to setup their udev processes in as secure a method as possible.
The following process types are defined for udev:
udev_t
Note: semanage permissive -a PROCESS_TYPE can be used to make a process type permissive. Permissive process types are not denied access by SELinux. AVC messages will still be generated.
COMMANDS
semanage fcontext can also be used to manipulate default file context mappings.semanage permissive can also be used to manipulate whether or not a process type is permissive.
semanage module can also be used to enable/disable/install/remove policy modules.
system-config-selinux is a GUI tool available to customize SELinux policy settings.
AUTHOR
This manual page was autogenerated by genman.py.SEE ALSO
selinux(8), udev(8), semanage(8), restorecon(8), chcon(1)
Index
This document was created by man2html, using the manual pages.
Time: 05:34:31 GMT, December 24, 2015


{% extends "base.html" %} {% block title %}Welcome{% end %} {% block content %}
Decss Sync integrates with the Decss Presentation Framework to allow you to remotely control your decks across multiple devices.
Log in with Twitter to get started.
{% end %}


{{greeting}}
People:
{{#people}} {{> _person}} {{/people}}
Add new person:
Save person
View source form handler:
add-person.js