Programming Skulpt
If you are reading this document, chances are you have used Skulpt in some form or another, maybe on skulpt.org or some other website. Or maybe you have embedded Skulpt on your own website. But, Skulpt is not complete. Bits and pieces of the Python language are missing, and now one of them is causing you enough pain that you have decided that you want to extend Skulpt with that missing bit. Or maybe you are just interested in learning a bit more about Skulpt and now you have found this document. Congratulations, thanks, and welcome.
What is Skulpt?
Skulpt is a system that compiles Python (of the 2.6-ish variety) into Javascript. But it's not Javascript that you can paste in to your browser and run. Python and Javascript are very different languanges, their types are different, their scoping rules are different. Python is designed to be run on Linux, or Windows, or Mac OS X, not in the browser! So, to provide a True Python experience Skulpt must provide a runtime environment in which the compiled code executes. This runtime environment is provided by the skulpt.min.js and skulpt-stdlib.js files that you must include in your web page in order to make Skulpt work.
To give you some idea of what is going on behind the scenes with skulpt lets look at what happens when our friend "hello world" is compiled from Python to Skulpt. We will revisit this program later and go into more detail, so for now, don't get bogged down in the detail, just have a look to see how much is really happening
Python Version
print "hello world"
Javascript Translation
/* 1 */ var $scope0 = (function($modname) {
/* 2 */ var $blk = 0,
/* 3 */ $exc = [],
/* 4 */ $gbl = {},
/* 5 */ $loc = $gbl,
/* 6 */ $err = undefined;
/* 7 */ $gbl.__name__ = $modname;
/* 8 */ Sk.globals = $gbl;
/* 9 */ try {
/* 10 */ while (true) {
/* 11 */ try {
/* 12 */ switch ($blk) {
/* 13 */ case 0:
/* 14 */ /* --- module entry --- */
/* 15 */ //
/* 16 */ // line 1:
/* 17 */ // print "hello world"
/* 18 */ // ^
/* 19 */ //
/* 20 */ Sk.currLineNo = 1;
/* 21 */ Sk.currColNo = 0
/* 22 */
/* 23 */
/* 24 */ Sk.currFilename = './simple.py';
/* 25 */
/* 26 */ var $str1 = new Sk.builtins['str']('hello world');
/* 27 */ Sk.misceval.print_(new Sk.builtins['str']($str1).v);
/* 28 */ Sk.misceval.print_("\n");
/* 29 */ return $loc;
/* 30 */ throw new Sk.builtin.SystemError('internal error: unterminated block');
/* 31 */ }
/* 32 */ } catch (err) {
/* 33 */ if ($exc.length > 0) {
/* 34 */ $err = err;
/* 35 */ $blk = $exc.pop();
/* 36 */ continue;
/* 37 */ } else {
/* 38 */ throw err;
/* 39 */ }
/* 40 */ }
/* 41 */ }
/* 42 */ } catch (err) {
/* 43 */ if (err instanceof Sk.builtin.SystemExit && !Sk.throwSystemExit) {
/* 44 */ Sk.misceval.print_(err.toString() + '\n');
/* 45 */ return $loc;
/* 46 */ } else {
/* 47 */ throw err;
/* 48 */ }
/* 49 */ }
/* 50 */ });
So, 50 lines of Javascript for hello world eh? That sounds kind of crazy, but you have to recognize that the environment with global variables, local variables, error handling, etc all has to happen even for the simplest program to run. The parts of the program above that really print "hello world" are lines 26-29. If you have a look at them you will see that we have to construct a string object from the string literal and then pass that off to some print function.
In the example above Sk.builtin.str
and Sk.misceval.print_
are part of the Skulpt runtime. It is usually the case that to extend Skulpt one of these runtime functions must be modified, or a new runtime function must be created and exposed so that it can be used in an ordinary Python program. The rest of this manual will take you through the essential parts of Skulpt so you can feel comfortable working on and extending the runtime environment.
An important thing to keep in mind as you are trying to understand Skulpt is that it is heavily influenced by the implementation of CPython. So although Python and Javascript are both object oriented languages many parts of the skulpt implementation are quite procedural. For example using functions that take an object as their first parameter may seem strange as we should have just created a method on that object. But in order to follow the CPython implementation this decision was made early on.
The Source
The src
directory contains the javascript that implements skulpt as well
as parts of the standard library. library modules are in src/lib. The
source files could roughly be divided into two pieces. The compiler and
the runtime. The compiler files are:
ast.js, parser.js, symtable.js, compile.js, and tokenize.js
The
compiler part of skulpt reads python code and generates a Javascript
program. If you want to change the syntax of Python these are the files
to look at. The syntax used in skulpt is taken right from the Python
2.6.5 distribution.
When you run the program in the browser the javascript part is 'evaled' by javascript. The runtime files roughly correspond to all of the major object types in Python plus builtins:
- abstract.js -- contains lots of abstract function defs
- biginteger.js -- implements Python's long integer type
- bool.js
- skulpt-stdlib.js -- builtin functions: range, min, max, etc. are defined here
- builtindict.js -- Provides a mapping from the standard Python name to the internal name in skulpt-stdlib.js
- dict.js
- enumerate.js
- env.js
- errors.js -- Exceptions are defined here
- file.js
- float.js
- function.js
- generator.js
- import.js
- int.js
- list.js
- long.js
- method.js
- module.js
- native.js
- number.js
- object.js -- most things "inherit" from object
- set.js
- slice.js
- str.js
- timsort.js
- tuple.js
- type.js
Types and Namespaces
The Sk
object contains all of the core Skulpt objects and
functions. It's pretty easy to get from Sk.blah to its source.
Usually you will see something like Sk.builtin.foo
which indicates
that you will likely find a corresponding file for foo in the src directory.
Similarly Sk.misceval.callsim
tells you that you should look
in misceval.js
for the callsim function.
Perhaps one of the most important concepts to learn when starting to program Skulpt is that you
are always moving back and forth between Python objects and Javascript objects. Much of your job
as a skulpt hacker is to either create Python objects as part of a builtin or module function,
or interact with objects that have been created by the users "regular" Python code. Knowing when
you are working with what is critical. For example a Javascript string is not the same thing as a
python string. A Python string is really an instance of Sk.builtin.str
and a Javscript string is
an instance of string
. You can't compare the two directly, and you definitely cannot use them
interchangeably.
| Python | Skulpt | Javascript |
|---|---|---|
| int | Sk.builtin.int | number |
| float | Sk.builtin.float | number |
| long | Sk.builtin.lng | NA |
| complex | Sk.builtin.complex | NA |
| list | Sk.builtin.list | Array |
| dict | Sk.builtin.dict | Object |
| set | Sk.builtin.set | NA |
| bool | Sk.builtin.bool | bool |
| tuple | Sk.builtin.tuple | NA |
So how do I get the equivalent value? How do I work with these Python objects from Javascript?
There are two key functions in Sk.ffi: Sk.ffi.remapToJs
and Sk.ffi.remapToPy
These utility functions are smart enough to remap most builtin data types back and forth. So if you have a Python string and want to compare it to a Javascript string literal you just need to do Sk.ffi.remapToJs(pystring)
to get a Javscript string you can compare.
If the Python object in question is a collection, remapToJs will work recursively and not only remap the top level object but also all of the contained objects.
When would you want to convert from Javascript to Python? Very often, in your implementation you will calculate a value that you want to return. The returned value needs to be a valid Python type. So lets say you calculate the factorial of a number in a new function you are adding to math. Then the resulting Javascript number must be turned into a Python object using Sk.ffi.remapToPy(myresult)
.
In many places in the current codebase you will see the use of somePythonObject.v
Where v
is the actual
javascript value hidden away inside the Python object. This is not the preferred way to obtain the mapping. Use
the Sk.ffi
API.
Skulpt is divided into several namespaces, you have already seen a couple of them, so here is the list
- Sk.abstr -- To extend skulpt you should know these functions
- Sk.builtin -- This is a big namespace that roughly corresponds to the Python
__builtin__
namespace - Sk.ffi -- This is the foreign function interface. Good for mapping back and forth from Python to Javascript
- Sk.misceval -- To extend skulpt you should know these functions
The Generated Code
Perhaps one of the most instructive things you can do to understand Skulpt and how the pieces begin to fit together is to look at a simple Python program, and its translation to Javscript. So lets begin with Hello World.
Python Version
print "hello world"
Javascript Translation
/* 1 */ var $scope0 = (function($modname) {
/* 2 */ var $blk = 0,
/* 3 */ $exc = [],
/* 4 */ $gbl = {},
/* 5 */ $loc = $gbl,
/* 6 */ $err = undefined;
/* 7 */ $gbl.__name__ = $modname;
/* 8 */ Sk.globals = $gbl;
/* 9 */ try {
/* 10 */ while (true) {
/* 11 */ try {
/* 12 */ switch ($blk) {
/* 13 */ case 0:
/* 14 */ /* --- module entry --- */
/* 15 */ //
/* 16 */ // line 1:
/* 17 */ // print "hello world"
/* 18 */ // ^
/* 19 */ //
/* 20 */ Sk.currLineNo = 1;
/* 21 */ Sk.currColNo = 0
/* 22 */
/* 23 */
/* 24 */ Sk.currFilename = './simple.py';
/* 25 */
/* 26 */ var $str1 = new Sk.builtins['str']('hello world');
/* 27 */ Sk.misceval.print_(new Sk.builtins['str']($str1).v);
/* 28 */ Sk.misceval.print_("\n");
/* 29 */ return $loc;
/* 30 */ throw new Sk.builtin.SystemError('internal error: unterminated block');
/* 31 */ }
/* 32 */ } catch (err) {
/* 33 */ if ($exc.length > 0) {
/* 34 */ $err = err;
/* 35 */ $blk = $exc.pop();
/* 36 */ continue;
/* 37 */ } else {
/* 38 */ throw err;
/* 39 */ }
/* 40 */ }
/* 41 */ }
/* 42 */ } catch (err) {
/* 43 */ if (err instanceof Sk.builtin.SystemExit && !Sk.throwSystemExit) {
/* 44 */ Sk.misceval.print_(err.toString() + '\n');
/* 45 */ return $loc;
/* 46 */ } else {
/* 47 */ throw err;
/* 48 */ }
/* 49 */ }
/* 50 */ });
So, one line of python becomes 50 lines of Javscript. Luckily lots of this is boiler plate that is the same for every program. One important convention is that variables that start with a $ are variables that are generated by the compiler. So, in the above example $scope0, $blk, $str1, etc are all generated by the compiler not by the Python program. Each line of the python program gets a corresponding entry in the Sk.currLineNo so that runtime error messages or exceptions can reference the line that caused them.
For now lets concentrate on the parts of the code that were generated specifically for our program. That would be lines 26-29 above.
- 26: The compiler creates a variable to hold the string literal
"hello world" A Python version of the string literal is created by
calling the constructor
Sk.builtins['str']
passing the javascript string literal. - 27: The
Sk.misceval.print_
function is called. Here is an interesting part of the runtime. The code for Sk.misceval.print_ is below. The key line isSk.output(s.v)
Sk.output
is configurable to be any function that the web developer might want to provide. For example you might write a function that takes a javascript string as a parameter and updates a pre element. Or you might simply write a function that calls alert. Notice thatprint_
simply expects to get an object. It converts this object into a Python string object by once again calling the string constructorSk.builtin.str
. If you've been keeping close watch, this is actually the third time our string liter has undergone this transformation. Luckily the string constructor is smart enough to simply return its parameter if the parameter is already a Python string. You might logically ask why does the compiler emit a call on line 27 when the runtime function takes care of the same issue. Not sure, maybe this is an optimization.
Sk.misceval.print_ = function(x) // this was function print(x) not sure why...
{
if (Sk.misceval.softspace_)
{
if (x !== "\n") Sk.output(' ');
Sk.misceval.softspace_ = false;
}
var s = new Sk.builtin.str(x);
Sk.output(s.v);
var isspace = function(c)
{
return c === '\n' || c === '\t' || c === '\r';
};
if (s.v.length === 0 || !isspace(s.v[s.v.length - 1]) || s.v[s.v.length - 1] === ' ')
Sk.misceval.softspace_ = true;
};
- 28: print always results in a newline. So do it.
- 29: done return. This gets us out of the while(true) loop.
Another Example Naming Conventions
Python
x = 1
y = 2
z = x + y
print z
Javascript
/* 1 */ var $scope0 = (function($modname) {
/* 2 */ var $blk = 0,
/* 3 */ $exc = [],
/* 4 */ $gbl = {},
/* 5 */ $loc = $gbl,
/* 6 */ $err = undefined;
/* 7 */ $gbl.__name__ = $modname;
/* 8 */ Sk.globals = $gbl;
/* 9 */ try {
/* 10 */ while (true) {
/* 11 */ try {
/* 12 */ switch ($blk) {
/* 13 */ case 0:
/* 14 */ /* --- module entry --- */
/* 15 */ //
/* 16 */ // line 1:
/* 17 */ // x = 1
/* 18 */ // ^
/* 19 */ //
/* 20 */ Sk.currLineNo = 1;
/* 21 */ Sk.currColNo = 0
/* 22 */
/* 23 */
/* 24 */ Sk.currFilename = './simple.py';
/* 25 */
/* 26 */ $loc.x = new Sk.builtin.nmber(1, 'int');
/* 27 */ //
/* 28 */ // line 2:
/* 29 */ // y = 2
/* 30 */ // ^
/* 31 */ //
/* 32 */ Sk.currLineNo = 2;
/* 33 */ Sk.currColNo = 0
/* 34 */
/* 35 */
/* 36 */ Sk.currFilename = './simple.py';
/* 37 */
/* 38 */ $loc.y = new Sk.builtin.nmber(2, 'int');
/* 39 */ //
/* 40 */ // line 3:
/* 41 */ // z = x + y
/* 42 */ // ^
/* 43 */ //
/* 44 */ Sk.currLineNo = 3;
/* 45 */ Sk.currColNo = 0
/* 46 */
/* 47 */
/* 48 */ Sk.currFilename = './simple.py';
/* 49 */
/* 50 */ var $loadname1 = $loc.x !== undefined ? $loc.x : Sk.misceval.loadname('x', $gbl);
/* 51 */ var $loadname2 = $loc.y !== undefined ? $loc.y : Sk.misceval.loadname('y', $gbl);
/* 52 */ var $binop3 = Sk.abstr.numberBinOp($loadname1, $loadname2, 'Add');
/* 53 */ $loc.z = $binop3;
/* 54 */ //
/* 55 */ // line 4:
/* 56 */ // print z
/* 57 */ // ^
/* 58 */ //
/* 59 */ Sk.currLineNo = 4;
/* 60 */ Sk.currColNo = 0
/* 61 */
/* 62 */
/* 63 */ Sk.currFilename = './simple.py';
/* 64 */
/* 65 */ var $loadname4 = $loc.z !== undefined ? $loc.z : Sk.misceval.loadname('z', $gbl);
/* 66 */ Sk.misceval.print_(new Sk.builtins['str']($loadname4).v);
/* 67 */ Sk.misceval.print_("\n");
/* 68 */ return $loc;
/* 69 */ throw new Sk.builtin.SystemError('internal error: unterminated block');
/* 70 */ }
/* 71 */ } catch (err) {
/* 72 */ if ($exc.length > 0) {
/* 73 */ $err = err;
/* 74 */ $blk = $exc.pop();
/* 75 */ continue;
/* 76 */ } else {
/* 77 */ throw err;
/* 78 */ }
/* 79 */ }
/* 80 */ }
/* 81 */ } catch (err) {
/* 82 */ if (err instanceof Sk.builtin.SystemExit && !Sk.throwSystemExit) {
/* 83 */ Sk.misceval.print_(err.toString() + '\n');
/* 84 */ return $loc;
/* 85 */ } else {
/* 86 */ throw err;
/* 87 */ }
/* 88 */ }
/* 89 */ });
So, here we create some local variables. x, y, do some math to create a
third local variable z, and then print it. Line 26 illustrates creating
a local variable x
(stored as an attribute of $loc)
new Sk.builtin.nmber(1, 'int');
By now you can probably guess that
Sk.builtin.nmber
is a constructor that creates a Python number object
that is of type int, and has the value of 1. The same thing happens for
y
.
Next, on lines 40 -- 53 we see what happens in an assignment statement.
first we load the values of x and y into temporary variables $loadname1
and $loadname2. Why not just use $loc.x ?? Well, we need to use
Python's scoping rules. If $loc.x is undefined then we should check the
outer scope to see if it exists there. Sk.misceval.loadname
If
loadname does not find a name x
or y
it throws a NameError, and
execution would abort. You can see where this works by changing the
assignment statement to z = x + t
to purposely cause the error. The
compiler blindly first tries $loc.t and then again calls loadname,
which in this case does abort with an error!
On lines 52 and 53 we perform the addition using
Sk.abstr.numberBinOp($loadname1, $loadname2, 'Add');
Note the abstract
(see abstract.js) nature of numberBinOp
-- two parameters for the
operands, and one parameter 'Add'
that indicates the operator. Finally
the temporary result returned by numberBinOp is stored in $loc.z. It's
important to note that $loc.z contains a Python number object. Down in
the bowels of numberBinOp, the javascript numeric values for x and y are
retrieved and result of adding two javascript numbers is converted to
the appropriate type of Python object.
Function Calls, Conditionals, and Loops
Oh my! so what is the deal with this while(true)/try/switch thing? To understand this we need a bit more complicated example, so lets look at a program that contains an if/else conditional. We'll see that we now have a much more interesting switch statement.
Without showing all of the generated code, lets consider a simple python
program like the one below. There will be two scope functions generated
by the compiler for this example. $scope0 is for the main program where
foo is defined and there is an if statement. The second $scope1 is for
when the foo function is actually called. The $scope1 while/switch
combo contains four cases: 0, 1, 2, and 3. You can imagine this python
code consisting of four blocks. The first block starts at the beginning
and goes through the evaluation of the if condition. The second block is
the if true block of the if. The third block is the else block of the if
statement, and the final block is the rest of the program after the
if/else is all done. You can verify this for yourself by putting this
program into a file simple.py
and running ./skulpt.py run simple.py
If you examine the output you will see that the $blk
variable is
manipulated to control which case
is executed the next time through
the while loop. Very clever! If Javascript had goto statements
this
would probably look a lot different.
# <--- $blk 0 starts
def foo(bar):
print bar
x = 2
if x % 2 == 0: # <---- end of $blk 0
foo("hello") # <---- $blk 3
else:
foo("goodbye") # <---- $blk 2
# <--- $blk 1 end of if
When foo is called, it has its own scope $scope1 created and called using Sk.misceval.callsim.
How do I add Feature X or Fix bug Y
Probably the biggest hurdle in working with skulpt is, "where do I start?" So, let me take you through a recent scenario, that is pretty illustrative of how I go about doing development on Skulpt.
The question was "how do I add keyword parameters (cmp, key, and reverse)" to the builtin sorted function. This is pretty tricky as Javascript does not support keyword parameters so there is no real straightforward path. So start as follows:
x = [1,2,3]
print(sorted(x,reverse=True))
Now run this using ./skulpt.py run test.py
and you will get a compiled
program. With a little bit of sleuthing you find:
/* 35 */ // line 2:
/* 36 */ // print(sorted(x,reverse=True))
/* 37 */ // ^
/* 38 */ //
/* 39 */ Sk.currLineNo = 2;
/* 40 */ Sk.currColNo = 0
/* 41 */
/* 42 */
/* 43 */ Sk.currFilename = './sd.py';
/* 44 */
/* 45 */ var $loadname8 = $loc.sorted !== undefined ? $loc.sorted : Sk.misceval.loadname('sorted', $gbl);
/* 46 */ var $loadname9 = $loc.x !== undefined ? $loc.x : Sk.misceval.loadname('x', $gbl);
/* 47 */ var $call10 = Sk.misceval.call($loadname8, undefined, undefined, ['reverse', Sk.builtin.bool.true$], $loadname9);
Where the important thing is to notice how the call is formatted after
it is compiled. The fourth parameter to Sk.misceval.call
is
['reverse', Sk.builtin.bool.true$]
Now if you check the source for
misceval, you will see that these parameters are passed on to the apply
function. In the apply function you will see that there is an assertion
that the fourth parameter should be empty. Ok, here's our starting point
to add in what's needed to actually process these key value parameters
successfully.
In the case of a bug fix, you would do a similar thing, except that the line where your get an exception is likely to be closer to helping you figure out your next steps.
HOW TO
This section is for providing specific examples, or documentation on how to do a specific task. Suggestions for additional tasks are welcome!
Default Parameters
How do I add a function with named parameters with default values?
The key to this is that as the author of either a builtin function, or a
method in a module, you need to add some meta data to the function
definition. Here's an example of how we added the named parameters to
the sorted
function.
Sk.builtin.sorted = function sorted(iterable, cmp, key, reverse) {
/* body of sorted here */
}
Sk.builtin.sorted.co_varnames = ['cmp', 'key', 'reverse'];
Sk.builtin.sorted.$defaults = [Sk.builtin.none, Sk.builtin.none, false];
Sk.builtin.sorted.co_numargs = 4;
kwargs
How do I add a function with **kwargs
?
Again the idea comes down to adding some meta-data after the function is
defined. Here is an example of adding **kwargs
to a method in a
module:
var plotk_f = function(kwa)
{
Sk.builtin.pyCheckArgsLen("plotk", arguments.length, 0, Infinity, true, false)
args = new Sk.builtins['tuple'](Array.prototype.slice.call(arguments, 1)); /*vararg*/
kwargs = new Sk.builtins['dict'](kwa);
return new Sk.builtins['tuple']([args, kwargs]);
};
plotk_f['co_kwargs'] = true;
mod.plotk = new Sk.builtin.func(plotk_f);
Adding a Module
This section is from a blog post I made in 2011, slightly updated.
So, here's the deal. skulpt relies on two javascript files the first is
skulpt.min.js and skulpt-stdlib.js A very minimal installation only uses
skulpt.min.js, whereas if you want to use any modules they are in
skulpt-stdlib.js. Looking around the distribution you will not
immediately find skulpt.min.js because you need to build it. You get a
sculpt.js file by using the skulpty.py script that comes with the distribution.
running ./skulpt.py --help
will give you the full list of commands, but the two
that you probably most care about are npm run build
and npm run docbi
The dist command builds both skulpt.min.js and skulpt-stdlib.js docbi builds
skulpt-stdlib.js and puts a new copy of it in the doc/static directory.
Lets begin with a quick tour of the source tree:
- src - contains the implementation of the Python interpreter
- src/lib - has the module implementations of webgl and goog. This is where turtle will live and any other modules I implement along the way.
- doc - This directory contains a google app engine application and is what you see on skulpt.org There are a couple of important files to check out in here. One of them is doc/static/env/editor.js This is the code that ties together the interactive editor on the home page with the skulpt interpreter and the codemirror editor. If you know how to build a google app engine app then this directory makes sense. One thing about the home page is that it is not set up to use any of the modules. The modules are used in the more advanced ide, which you can find in doc/ide/static. I'm going to tell you how to add modules to the simpler editor later in this article.
- test - this directory contains a bunch of files for testing the
implementation in a batch mode.  It contains the built and compressed versions of skulpt.min.js and skulpt-stdlib.js
To illustrate how to make use of modules, here's an extended version of my earlier hello world style example.
<html>
<head>
<script src="skulpt.min.js" type="text/javascript"></script>
<script src="skulpt-stdlib.js" type="text/javascript"></script>
</head>
<body>
<script type="text/javascript">
function outf(text) {
var mypre = document.getElementById("output");
mypre.innerHTML = mypre.innerHTML + text;
}
function builtinRead(x)
{
if (Sk.builtinFiles === undefined || Sk.builtinFiles["files"][x] === undefined)
throw "File not found: '" + x + "'";
return Sk.builtinFiles["files"][x];
}
function runit() {
var prog = document.getElementById("yourcode").value;
var mypre = document.getElementById("output");
mypre.innerHTML = '';
Sk.configure({output:outf,
read: builtinRead
});
try {
Sk.importMainWithBody("<stdin>",false,prog);
} catch (e) {
alert(e);
}
}
</script>
<h3>Try This</h3>
<form>
<textarea edit_id="eta_5" id="yourcode">
print "Hello World"
</textarea>
<button onclick="runit()" type="button">Run</button>
</form>
<pre id="output"></pre>
</body>
</html>
There are some important differences between this version and the non-module version. First off, the call to Sk.configure contains another key value pair which sets up a specialized read function. This is the function that is responsible for returning your module out of the large array of files that are contained in the skulpt-stdlib.js file. You will see that all of the modules are contained in this one file, stored in a big JSON structure. The extra key value pair is: read: builtinRead
The read function is just for loading modules and is called when you do an import statement of some kind. In this case the function accesses the variable builtinFiles which is created from the skulpt-stdlib.js file. The other difference, of course, is that you have to include skulpt-stdlib.js in your html file. Note that skulpt-stdlib.js must be included after skulpt.min.js
Now as far as the module itself goes, the easiest thing to do is to start your module in the src/lib directory. This way it will automatically get built and included in skulpt-stdlib.js. If you don't put it there then you are going to have to modify the skulpt.py script, specifically the docbi function in the skulpt.py script to include your module. Suppose that you want to have a module called bnm.test Here's what you have to do. First, you need to make a bnm directory under lib. In this directory you will need to have either __init__.py or __init__.js or bnm.js to stand in for the bnm module. There doesn't need to be anything in the file as long as it exists. This is just like CPython by the way. Then to make a test module you can either make a test directory and put all your javascript code in __init__.js or you can simply create a test.js file in the bnm directory. Let's look at the test module.
var $builtinmodule = function(name)
{
var mod = {};
var myfact = function(n) {
if(n < 1) {
return 1;
} else {
return n * myfact(n-1);
}
}
mod.fact = new Sk.builtin.func(function(a) {
return myfact(a.v); // extract the underlying JS value with .v
});
mod.Stack = Sk.misceval.buildClass(mod, function($gbl, $loc) {
$loc.__init__ = new Sk.builtin.func(function(self) {
self.stack = [];
});
$loc.push = new Sk.builtin.func(function(self,x) {
self.stack.push(x);
});
$loc.pop = new Sk.builtin.func(function(self) {
return self.stack.pop();
});
}, 'Stack', []);
return mod;
}
All modules start out with the $var builtinmodule = statement. This test module exposes a single method to the outside world, called fact, There are a couple of key functions for building up a module. The Sk.builtin.func call for adding functions to your module, and the Sk.misceval.buildClass method. This test module defines a simple factorial function called fact, and a class called stack. Here's a simple Python program that exercises the module:
import bnm.test
print 'starting'
print bnm.test.fact(10)
x = bnm.test.Stack()
x.push(1)
x.push(2)
print x.pop()
print 'done'
It's not obvious, but the buildClass method takes four parameters: globals, func, name, bases It seems that you always pass the mod object itself as the globals parameter, the func parameter is a function that represents the class object, the Name is the external name of the class, and bases presumably would be if the class is inheriting from another class.
The Sk.builtin.func method creates a function. For module creation we typically only have to worry about the one parameter, func, which is the javascript implementation of our Python function. The method can also take a globals object and two closure objects. Look at the comments in function.js if you want more explanation of how the builtin.func method works.
Well, I think this should be enough to get you going. It's worth
repeating, if you made it this far, don't forget to call npm run docbi
or
npm run build
after you make changes in your module, it's easy to get into the
mode of thinking that the new javascript is automatically loaded. But
skulpt-stdlib.js is not automatically rebuilt!
Importing/Using a module in another module
While working on the namedtuple factory in the collections module I needed to add code to make sure that the fields named in the named tuple did not duplicate python keywords. while I was looking around for a list of keywords I discovered that there already was a list of keywords in the keyword module. Why not use that? A couple of problems:
How do you import a module into another module? Especially under the condition where you are writing a module in javascript and the module you want to include is a python module?
How do you call a function that was imported from a python module? Here is the snippet that demonstrates
var keywds = Sk.importModule("keyword", false, false);
mod.namedtuple = function (name, fields) {
var nm = Sk.ffi.remapToJs(name);
// fields could be a string or a tuple or list of strings
var flds = Sk.ffi.remapToJs(fields);
if (typeof(flds) === 'string') {
flds = flds.split(/\s+/);
}
// use the keyword module function iskeyword
for (i = 0; i < flds.length; i++) {
if (Sk.ffi.remapToJs(Sk.misceval.callsim(keywds.$d['iskeyword'],Sk.ffi.remapToPy(flds[i])))) {
throw new Sk.builtin.ValueError("Type names and field names cannot be a keyword: " + flds[i]);
}
}
The importing part is easy: Sk.importModule(name, dumpJS, canSuspend)
The not-so-obvious part is the line:
Sk.ffi.remapToJs(Sk.misceval.callsim(keywds.$d['iskeyword'],Sk.ffi.remapToPy(flds[i])))
Working inside out: We use Sk.misceval.callsim
to call the python
function iskeyword
which we retrieve from the module's dictionary of
methods $d
Because we are calling a Python function we need to remap
the parameter from a javascript string to a Python string object. Hence
the remapToPy
call in the parameter. Since iskeyword
will return a
Python bool object we need to remap that back to javscript for our if
statement.
You can use a similar strategy for creating an instance of a class:
var io = Sk.importModule("io", false, false);
var stdin = Sk.misceval.callsim(io.$d["TextIOWrapper"]);
Seems like a lot of work to check for a keyword in an array. But knowing how to do this for much more complicated methods in other modules will pay off.
Debugging
How do I use the debugger in the browser to help me debug my code?
Easy, just add the statement: debugger;
to your code. Now if you have
the javscript deveoper tools open in the browser you will have it.
If you want to start the debugger from a python function that you have written you can also add a debugger statement
If you want to enable debugging generally for use with debugbrowser
follow these handy instructions:
- I make a new test using ./m nrt
- then add a debugger; to the start of the statement at
https://github.com/skulpt/skulpt/blob/master/src/import.js#L179
the line would like this:
finalcode += "\ndebugger;" + co.funcname + "(" + namestr + ");";
- run
npm run debugbrowser
wait until all tests have run - startup the developer tools cmd+alt+i on a mac or F12 on a PC in chrome that is
- run the test I added before and it stops right before you enter the compiled code!
Development Workflow
- Make a fork of the repository on github. DO NOT simply clone http://github.com/bnmnetp/runestone. Make a Fork. If you don't know how to make a fork consult the documentation here: https://help.github.com/articles/fork-a-repo
- Make a simple myabs.py file that contains a few lines of python that exercise the abs function. Say it looks like this:
print abs(-1.0)
print abs(24)
- Now go edit the source. To implement abs you would edit the builtin.js file. Now abs is pretty easy to add, because you can just have our skulpt version of abs call Math.abs So here it is
Sk.builtin.abs = function abs(x)
{
return Math.abs(x);
};
You are not done yet, because builtin functions also have to be declared in the builtindict.js object as follows:
Sk.builtins = {
'range': Sk.builtin.range,
'len': Sk.builtin.len,
'min': Sk.builtin.min,
'max': Sk.builtin.max,
'sum': Sk.builtin.sum,
'abs': Sk.builtin.abs,
...
}
Now you can test your modifications from the command line by running:
./skulpt.py run myabs.py
-----
print abs(-1.0)
print abs(24)
-----
/* 1 */ var $scope0 = (function($modname) {
/* 2 */ var $blk = 0,
/* 3 */ $exc = [],
/* 4 */ $gbl = {},
/* 5 */ $loc = $gbl;
/* 6 */ $gbl.__name__ = $modname;
/* 7 */ while (true) {
/* 8 */ try {
/* 9 */ switch ($blk) {
/* 10 */ case 0:
/* 11 */ /* --- module entry --- */
/* 12 */ //
/* 13 */ // line 1:
/* 14 */ // print abs(-1.0)
/* 15 */ // ^
/* 16 */ //
/* 17 */ Sk.currLineNo = 1;
/* 18 */ Sk.currColNo = 0
/* 19 */
/* 20 */
/* 21 */ Sk.currFilename = './myabs.py';
/* 22 */
/* 23 */ var $loadname1 = $loc.abs !== undefined ? $loc.abs : Sk.misceval.loadname('abs', $gbl);
/* 24 */ var $call2 = Sk.misceval.callsim($loadname1, Sk.numberFromStr('-1.0'));
/* 25 */ Sk.misceval.print_(new Sk.builtins['str']($call2).v);
/* 26 */ Sk.misceval.print_("\n");
/* 27 */ //
/* 28 */ // line 2:
/* 29 */ // print abs(24)
/* 30 */ // ^
/* 31 */ //
/* 32 */ Sk.currLineNo = 2;
/* 33 */ Sk.currColNo = 0
/* 34 */
/* 35 */
/* 36 */ Sk.currFilename = './myabs.py';
/* 37 */
/* 38 */ var $loadname3 = $loc.abs !== undefined ? $loc.abs : Sk.misceval.loadname('abs', $gbl);
/* 39 */ var $call4 = Sk.misceval.callsim($loadname3, Sk.numberFromStr('24'));
/* 40 */ Sk.misceval.print_(new Sk.builtins['str']($call4).v);
/* 41 */ Sk.misceval.print_("\n");
/* 42 */ return $loc;
/* 43 */ goog.asserts.fail('unterminated block');
/* 44 */ }
/* 45 */ } catch (err) {
/* 46 */ if ($exc.length > 0) {
/* 47 */ $blk = $exc.pop();
/* 48 */ continue;
/* 49 */ } else {
/* 50 */ throw err;
/* 51 */ }
/* 52 */ }
/* 53 */ }
/* 54 */ });
1
24
This is all incredibly useful information.
First it demonstrates that your addition actually worked. You can see the output at the bottom. Second, you can see how skulpt 'compiled' your python program into its intermediate Javascript form. While this may not be all that helpful in this particular case it can be very very helpful in figuring out what skulpt is actually doing. Now you should run all of the unit tests to make sure you have broken anything else accidentally. This is really easy:
npm test
If any tests fail it will be obvious that they did, and you'll have to do some investigation to figure out why. At the time of this writing you should see:
run: 343/343 (+1 disabled)
closure: skipped
Once you are satisfied that your extension is working fine. You should add a test case to test/run see: New Tests for instructions. This way we will have a permanent test in the bank of test cases in order to check for any future regressions.
Finally make a pull request on github to have your new feature integrated into the master copy. I probably will not accept your pull request if you haven't done step 4.
Outside of your editor, your browser, and your wits, the main development tool for skulpt is the skulpt.py command (also linked to m for historical compatibility).
./skulpt.py --help
Usage:
skulpt.py \<command> [\<options>] [script.py]
Commands:
run Run a Python file using Skulpt test Run all test cases dist Build core and library distribution files docbi Build library distribution file only and copy to doc/static
regenparser Regenerate parser tests regenasttests Regen abstract symbol table tests regenruntests Regenerate runtime unit tests regensymtabtests Regenerate symbol table tests regentests Regenerate all of the above
help Display help information about Skulpt host Start a simple HTTP server for testing upload Run appcfg.py to upload doc to live GAE site doctest Run the GAE development server for doc testing nrt Generate a file for a new test case runopt Run a Python file optimized browser Run all tests in the browser shell Run a Python program but keep a shell open (like python -i) vfs Build a virtual file system to support Skulpt read tests
debugbrowser Debug in the browser -- open your javascript console
Options:
-q, --quiet Only output important information -s, --silent Do not output anything, besides errors -u, --uncompressed Makes uncompressed core distribution file for debugging -v, --verbose Make output more verbose [default] --version Returns the version string in Bower configuration file.
Options: : --version show program's version number and exit -h, --help show this help message and exit -q, --quiet -s, --silent -u, --uncompressed -v, --verbose Make output more verbose [default]
run
The command ./skulpt.py run foo.py
compiles and runs a Python program
generating output similar to the examples shown in the previous section.
This is very common for development. For example if you find a bug, that
you can express in a small Python program you can start by running the
program from the command line and inspecting the generated code. Usually
this will give you a pretty good idea where the bug might be.
test
Run all the unit tests.
dist
Build the distribution files for skulpt:
- skulpt.min.js -- This is a minified version of the core interpreter files.
- skulpt-stdlib.js -- This is an unminified version of library functions. This file may contain javascript that implements a module, such as turtle or math, or it may contain pure python.
Building on windows
Running .\skulpt.cmd dist
on windows requires some extra work, because
the tests check against the text output, things with line-endings tend
to get icky.
We want to make use we checkout skulpt with LF
line endings, which is
not default on windows. You have to configure git and reset your working
directory. Like this:
> git config core.autocrlf input
> git update-index --refresh
> git rm --cached -r .
> git reset --hard
Getting stack traces from an exception
Sk.builtin.Exception objects have a property called 'traceback'. This property contains an Array of objects with 'filename', 'lineno' and (optionally) 'colno' properties, each representing a stack frame. The array is ordered from innermost to outermost frame.
If an object that is not an instance of Sk.builtin.Exception is thrown from within a Skulpt function (typically as part of an external piece of Javascript), it is wrapped in an Sk.builtin.ExternalError. The original object thrown is stringified (so the exception can be manipulated in Python), but a reference to the original is also saved in the ExternalError's 'nativeError' property so it can be inspected from Javascript.


A work-in-progress n64 emulator. Info
Many games run at full speed on a M2 Macbook Pro but there are lots of graphical issues. Here's a rough feature matirx showing what's been implemented:
| CPU | Implemented |
| TLB | Implemented |
| RSP | Implemented |
| Controller | Mostly implemented |
| Graphics - GBI0 | Mostly implemented |
| Graphics - GBI1 | Partially implemented |
| Graphics - GBI2 | Partially implemented |
| Audio | Not implemented |
| Save - Eeprom4k | Implemented |
| Save - Eeprom4k | Implemented |
| Save - SRAM | Implemented |
| Save - FlashRAM | Implemented |
| Save - Mempack | Implemented |
I did some quick testing on OSX 10.8:
| Chrome | 21.0.1180.79 or later should be ok - I've been doing most of my development in Chrome. |
| Firefox | 15.0.1 or later seems to work now, but is slower than Chrome. |
| Safari | 6.0 doesn't seem to work. I haven't tried with the latest nightlies. |
| Opera | Untested. |
WebGL is required, which places certain restrictions on which GPUs the emulator will work with.
Tweet me if you have any additional info.
There's lots of issues right now with slow performance, graphics glitches, unsupported opcodes, emulation bugs. It's probably easier just to list stuff that actually works right now :)
| N64 | Keyboard |
|---|---|
| Start | A |
| A | S |
| B | X |
| Z | Z |
| L | C |
| R | V |
| DPad Up | T |
| DPad Down | G |
| DPad Left | F |
| DPad Right | H |
| C Up | I |
| C Down | K |
| C Left | J |
| C Right | L |
n64js is based on Daedalus, an emulator I started writing while I was at university under a pseudonym of StrmnNrmn. I've worked on Daedalus intermittantly ever since, but life and work have limited the time I've been able to spend on the project in the past few years. The project lives on due to the excellent work of everyone at DaedalusX. In particular, Kreationz, Wally, Corn, Salvy all deserve great credit for keeping the project going. Also, hello to Schibo, who's been working on porting 1964 to JavaScript too: 1964js.
Jan-Christoph Borchardt - better keyboard mapping for QWERTZ keyboards.
By @HulkHolden. Blog. Code. Videos.


First Item
To add your first item:
- Select an item from the drop-down list.
- Enter an item quantity.
- Enter your contact information.
- Enter your credit card number.
- Click 'ADD TO ORDER' to add item(s) to your cart.
Additional Items
You can continue to add items to your cart until you checkout. There's no need to type in your customer information a second time. Simply add more items as follows:
- Select an item from the list.
- Choose the quantity.
- Click 'ADD TO ORDER' again to add the new items to your cart.
- When you are finished adding items, click 'PROCEED TO CHECKOUT'.


|
Subtracts the second operand (source operand) from the first operand (destination operand) and stores the result in the destination operand. The source operand can be a quadword integer stored in an MMX technology register or a 64-bit memory location, or it can be two packed quadword integers stored in an XMM register or an 128-bit memory location. The destination operand can be a quadword integer stored in an MMX technology register or two packed quadword integers stored in an XMM register. When packed quadword operands are used, an SIMD subtract is performed. When a quadword result is too large to be represented in 64 bits (overflow), the result is wrapped around and the low 64 bits are written to the destination element (that is, the carry is ignored).
Note that the PSUBQ instruction can operate on either unsigned or signed (two's complement notation) integers; however, it does not set bits in the EFLAGS register to indicate overflow and/or a carry. To prevent undetected overflow conditions, software must control the ranges of the values operated on.
|


Welcome!
About
Connect
Portfolio
Connect
About
Connect
Contact Me By:
Phone
(765) 242-7235
Email
<EMAIL_ADDRESS>Mail Address
2614 E 57th Street
Indianapolis, IN 46041
More About Me:
LinkedIn
See My Profile
GitHub
See My Work


Halloween : The Boogeyman don't scare me.
As reviewed by James Brundage
Someone once told me it was the most successful independent film of all time. Someone else told me that it revolutionized horror. Yet another told me it created horror (HELLO, Psycho?). Personally, I don't see what the big deal is all about. There are movies that I just can't stand. That their even being created mystifies me. Halloween was such a film.
Like all of the horror movies that you and I, the babies and the people who lived through the 80s dealt with, it has the same basic plot: Psycho escaped from institution has fun stabbing/gutting/strangling/decapitating (based upon film) the victims of his killing spree.
Like most horror movies, it could have been good for a laugh. But no. Trust John Carpenter (director) to give us a film that takes itself so seriously that you just can't laugh at it.
I am truly sorry it was made. If it wasn't, there would be no horror genre (for mass market), and we would be out some of the worst films of all time. Granted, the Scream franchise would be gone too, but I could live with that. I'm sorry if you already saw it. I'm sorry if you want to see it. Please, I implore you, don't waste your time.
http://fly.to/criticsheaven
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


Having fun traveling, while I code to help others.
Jack of all Trades, Master at None.
Join me at coderstravel where we love to travel while coding to help others.


This module provides a small collection of functions for diffing text.
The Diff library consists of a single file (diff.lua), plus a test script (tests/basic.lua). Just put the file somewhere in your Lua path. Here is a list of recent releases:
You can also install it using LuaRocks with
luarocks install diff
or:
luarocks --from=http://sputnik.freewisdom.org/rocks/earth install diff
diffProvides functions for diffing text. (c) 2007, 2008 Yuri Takhteyev<EMAIL_ADDRESS>(c) 2007 Hisham Muhammad License: MIT/X, see http://sputnik.freewisdom.org/en/License |
|
| diff() | Returns a diff of two strings as a list of pairs, where the first value represents a token and the second the token's status ("same", "in", "out").
|
| escape_html() | Escapes an HTML string.
|
| format_as_html() | Formats an inline diff as HTML, with and
|
| quick_LCS() | Derives the longest common subsequence of two strings.
|
| split() | Split a string into tokens.
|
Copyright (c) 2007, 2008 Yuri Takhteyev
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


The First Visualization Platform for Understanding Virus Spread
What Is Flowa?
Flowa is a platform where you can find places that can potentially facilitate virus transmission. With an easy-to-navigate interface, you can see areas of high risk and places with a high rate of virus infections.
Learn more
Do not miss the latest updates
Learn everything about the virus spread. Know every minute update about the rates in you district, city and country. Be aware of the places that can potentially facilitate virus transmission.
Subscribe
Last updates
This section is for demonstration purposes only and therefore is not functional
COVID-19 statistics
COVID-19 is the disease caused by the new coronavirus called SARS-CoV-2, that was first reported in Wuhan, China in December 2019. Since then, a pandemic has spread all around the world. Learn more
New Cases
5 mins ago
European Vaccine Plan
2 days ago
Map Update
1 week ago
Vaccinations
Districts in Your City


32-year-old man fatally shot, school bus hit by gunfire in Brooklyn
by WABCEAST NEW YORK, Brooklyn (WABC) -- A man was fatally shot and a school bus struck by the gunfire in Brooklyn Tuesday morning.
It happened around 8:45 a.m. at Pennsylvania and Dumont avenues in East New York.
Police say the 32-year-old man, identified by relatives as Francisco Bonilla, was shot in the intersection and pronounced dead at Brookdale University Hospital.
Bonilla was shot in front of the building where he lives with his mother, and he reportedly was involved in some sort of argument prior to the shooting.
His family says he has a young daughter.
A school bus with one child on board was also struck, as was an B20 MTA bus.
No other injuries were reported.
No arrests were immediately made, and the investigation is ongoing.
The Department of Education released a statement, saying, "NYPD and EMS immediately responded, and there were no injuries on the bus. We immediately notified the family and will provide any additional support needed."


South African Airways suspends flights to Hong Kong to curb losses
JOHANNESBURG: Strike-hit South African Airways (SAA) said on Thursday it would suspend all flights between Johannesburg and Hong Kong from Nov. 23 up to and including Dec. 14 to curb significant financial losses on the route.
SAA, which is running out of cash because of the week-long strike over wages and job cuts, said the losses had been exacerbated by political tensions in Hong Kong.


Downloading is as easy as taking out your Android smartphone and pressing the download link then following the on-screen instructions
Our web manager is available for users to see HERE , however giving access to the management hub would compromise security. If you would like to take it for a spin please contact us!


{% extends parent_template|default:"researcher/base.html" %} {% block title %} Delete Remote Project {% endblock %} {% block content %}
Are you sure you want to delete {{ project.name }} from {{ project.get_remote_URL }}?


$gatewayname Hotspot Gateway.
Welcome!
For access to the Internet, please tap or click Continue.
Copyright © The Nodogsplash Contributors 2004-2019.
This software is released under the GNU GPL license.


| Top |
Character Set ConversionCharacter Set Conversion — convert strings between different character sets |
| gchar * | g_convert () |
| gchar * | g_convert_with_fallback () |
| gchar * | g_convert_with_iconv () |
| GIConv | g_iconv_open () |
| gsize | g_iconv () |
| gint | g_iconv_close () |
| gchar * | g_locale_to_utf8 () |
| gchar * | g_filename_to_utf8 () |
| gchar * | g_filename_from_utf8 () |
| gboolean | g_get_filename_charsets () |
| gchar * | g_filename_display_name () |
| gchar * | g_filename_display_basename () |
| gchar * | g_locale_from_utf8 () |
| gboolean | g_get_charset () |
| gchar * | g_get_codeset () |
The g_convert()
family of function wraps the functionality of iconv()
.
In addition to pure character set conversions, GLib has functions to
deal with the extra complications of encodings for file names.
Historically, UNIX has not had a defined encoding for file names: a file name is valid as long as it does not have path separators in it ("/"). However, displaying file names may require conversion: from the character set in which they were created, to the character set in which the application operates. Consider the Spanish file name "Presentación.sxi". If the application which created it uses ISO-8859-1 for its encoding,
1 2 |
Character: P r e s e n t a c i ó n . s x i Hex code: 50 72 65 73 65 6e 74 61 63 69 f3 6e 2e 73 78 69 |
However, if the application use UTF-8, the actual file name on disk would look like this:
1 2 |
Character: P r e s e n t a c i ó n . s x i Hex code: 50 72 65 73 65 6e 74 61 63 69 c3 b3 6e 2e 73 78 69 |
Glib uses UTF-8 for its strings, and GUI toolkits like GTK+ that use
Glib do the same thing. If you get a file name from the file system,
for example, from readdir()
or from g_dir_read_name()
, and you wish
to display the file name to the user, you will need to convert it
into UTF-8. The opposite case is when the user types the name of a
file he wishes to save: the toolkit will give you that string in
UTF-8 encoding, and you will need to convert it to the character
set used for file names before you can create the file with open()
or fopen()
.
By default, Glib assumes that file names on disk are in UTF-8
encoding. This is a valid assumption for file systems which
were created relatively recently: most applications use UTF-8
encoding for their strings, and that is also what they use for
the file names they create. However, older file systems may
still contain file names created in "older" encodings, such as
ISO-8859-1. In this case, for compatibility reasons, you may want
to instruct Glib to use that particular encoding for file names
rather than UTF-8. You can do this by specifying the encoding for
file names in the G_FILENAME_ENCODING
environment variable. For example, if your installation uses
ISO-8859-1 for file names, you can put this in your ~/.profile
1 |
export G_FILENAME_ENCODING=ISO-8859-1 |
Glib provides the functions g_filename_to_utf8()
and
g_filename_from_utf8()
to perform the necessary conversions.
These functions convert file names from the encoding specified
in G_FILENAME_ENCODING
to UTF-8 and vice-versa. This
diagram illustrates how
these functions are used to convert between UTF-8 and the
encoding for file names in the file system.
This section is a practical summary of the detailed
things to do to make sure your applications process file name encodings correctly.
If you get a file name from the file system from a function
such as readdir()
or gtk_file_chooser_get_filename()
, you do
not need to do any conversion to pass that file name to
functions like open()
, rename()
, or fopen()
-- those are "raw"
file names which the file system understands.
If you need to display a file name, convert it to UTF-8 first
by using g_filename_to_utf8()
. If conversion fails, display a
string like "Unknown file name". Do not convert this string back
into the encoding used for file names if you wish to pass it to
the file system; use the original file name instead.
For example, the document window of a word processor could display
"Unknown file name" in its title bar but still let the user save
the file, as it would keep the raw file name internally. This
can happen if the user has not set the G_FILENAME_ENCODING
environment variable even though he has files whose names are
not encoded in UTF-8.
If your user interface lets the user type a file name for saving
or renaming, convert it to the encoding used for file names in
the file system by using g_filename_from_utf8()
. Pass the converted
file name to functions like fopen()
. If conversion fails, ask the
user to enter a different file name. This can happen if the user
types Japanese characters when G_FILENAME_ENCODING
is set to
ISO-8859-1
, for example.
gchar * g_convert (const gchar *str
,gssize len
,const gchar *to_codeset
,const gchar *from_codeset
,gsize *bytes_read
,gsize *bytes_written
,GError **error
);
Converts a string from one character set to another.
Note that you should use g_iconv()
for streaming conversions.
Despite the fact that byes_read
can return information about partial
characters, the g_convert_... functions are not generally suitable
for streaming. If the underlying converter maintains internal state,
then this won't be preserved across successive calls to g_convert()
,
g_convert_with_iconv()
or g_convert_with_fallback()
. (An example of
this is the GNU C converter for CP1255 which does not emit a base
character until it knows that the next character is not a mark that
could combine with the base character.)
Using extensions such as "//TRANSLIT" may not work (or may not work
well) on many platforms. Consider using g_str_to_ascii()
instead.
str |
the string to convert |
|
len |
the length of the string in bytes, or -1 if the string is
nul-terminated (Note that some encodings may allow nul
bytes to occur inside strings. In that case, using -1
for the |
|
to_codeset |
name of character set into which to convert |
|
from_codeset |
character set of |
|
bytes_read |
location to store the number of bytes in the
input string that were successfully converted, or |
[out] |
bytes_written |
the number of bytes stored in the output buffer (not including the terminating nul). |
[out] |
error |
location to store the error occurring, or |
gchar * g_convert_with_fallback (const gchar *str
,gssize len
,const gchar *to_codeset
,const gchar *from_codeset
,const gchar *fallback
,gsize *bytes_read
,gsize *bytes_written
,GError **error
);
Converts a string from one character set to another, possibly
including fallback sequences for characters not representable
in the output. Note that it is not guaranteed that the specification
for the fallback sequences in fallback
will be honored. Some
systems may do an approximate conversion from from_codeset
to to_codeset
in their iconv()
functions,
in which case GLib will simply return that approximate conversion.
Note that you should use g_iconv()
for streaming conversions.
Despite the fact that byes_read
can return information about partial
characters, the g_convert_... functions are not generally suitable
for streaming. If the underlying converter maintains internal state,
then this won't be preserved across successive calls to g_convert()
,
g_convert_with_iconv()
or g_convert_with_fallback()
. (An example of
this is the GNU C converter for CP1255 which does not emit a base
character until it knows that the next character is not a mark that
could combine with the base character.)
str |
the string to convert |
|
len |
the length of the string in bytes, or -1 if the string is
nul-terminated (Note that some encodings may allow nul
bytes to occur inside strings. In that case, using -1
for the |
|
to_codeset |
name of character set into which to convert |
|
from_codeset |
character set of |
|
fallback |
UTF-8 string to use in place of character not
present in the target encoding. (The string must be
representable in the target encoding).
If |
|
bytes_read |
location to store the number of bytes in the
input string that were successfully converted, or |
|
bytes_written |
the number of bytes stored in the output buffer (not including the terminating nul). |
|
error |
location to store the error occurring, or |
gchar * g_convert_with_iconv (const gchar *str
,gssize len
,GIConv converter
,gsize *bytes_read
,gsize *bytes_written
,GError **error
);
Converts a string from one character set to another.
Note that you should use g_iconv()
for streaming conversions.
Despite the fact that byes_read
can return information about partial
characters, the g_convert_... functions are not generally suitable
for streaming. If the underlying converter maintains internal state,
then this won't be preserved across successive calls to g_convert()
,
g_convert_with_iconv()
or g_convert_with_fallback()
. (An example of
this is the GNU C converter for CP1255 which does not emit a base
character until it knows that the next character is not a mark that
could combine with the base character.)
str |
the string to convert |
|
len |
the length of the string in bytes, or -1 if the string is
nul-terminated (Note that some encodings may allow nul
bytes to occur inside strings. In that case, using -1
for the |
|
converter |
conversion descriptor from |
|
bytes_read |
location to store the number of bytes in the
input string that were successfully converted, or |
|
bytes_written |
the number of bytes stored in the output buffer (not including the terminating nul). |
|
error |
location to store the error occurring, or |
GIConv g_iconv_open (const gchar *to_codeset
,const gchar *from_codeset
);
Same as the standard UNIX routine iconv_open()
, but
may be implemented via libiconv on UNIX flavors that lack
a native implementation.
GLib provides g_convert()
and g_locale_to_utf8()
which are likely
more convenient than the raw iconv wrappers.
gsize g_iconv (GIConv converter
,gchar **inbuf
,gsize *inbytes_left
,gchar **outbuf
,gsize *outbytes_left
);
Same as the standard UNIX routine iconv()
, but
may be implemented via libiconv on UNIX flavors that lack
a native implementation.
GLib provides g_convert()
and g_locale_to_utf8()
which are likely
more convenient than the raw iconv wrappers.
converter |
conversion descriptor from |
|
inbuf |
bytes to convert |
|
inbytes_left |
inout parameter, bytes remaining to convert in |
|
outbuf |
converted output bytes |
|
outbytes_left |
inout parameter, bytes available to fill in |
gint
g_iconv_close (GIConv converter
);
Same as the standard UNIX routine iconv_close()
, but
may be implemented via libiconv on UNIX flavors that lack
a native implementation. Should be called to clean up
the conversion descriptor from g_iconv_open()
when
you are done converting things.
GLib provides g_convert()
and g_locale_to_utf8()
which are likely
more convenient than the raw iconv wrappers.
gchar * g_locale_to_utf8 (const gchar *opsysstring
,gssize len
,gsize *bytes_read
,gsize *bytes_written
,GError **error
);
Converts a string which is in the encoding used for strings by the C runtime (usually the same as that used by the operating system) in the current locale into a UTF-8 string.
opsysstring |
a string in the encoding of the current locale. On Windows this means the system codepage. |
|
len |
the length of the string, or -1 if the string is
nul-terminated (Note that some encodings may allow nul
bytes to occur inside strings. In that case, using -1
for the |
|
bytes_read |
location to store the number of bytes in the
input string that were successfully converted, or |
|
bytes_written |
the number of bytes stored in the output buffer (not including the terminating nul). |
|
error |
location to store the error occurring, or |
A newly-allocated buffer containing the converted string,
or NULL
on an error, and error will be set.
gchar * g_filename_to_utf8 (const gchar *opsysstring
,gssize len
,gsize *bytes_read
,gsize *bytes_written
,GError **error
);
Converts a string which is in the encoding used by GLib for filenames into a UTF-8 string. Note that on Windows GLib uses UTF-8 for filenames; on other platforms, this function indirectly depends on the current locale.
opsysstring |
a string in the encoding for filenames |
|
len |
the length of the string, or -1 if the string is
nul-terminated (Note that some encodings may allow nul
bytes to occur inside strings. In that case, using -1
for the |
|
bytes_read |
location to store the number of bytes in the
input string that were successfully converted, or |
|
bytes_written |
the number of bytes stored in the output buffer (not including the terminating nul). |
|
error |
location to store the error occurring, or |
gchar * g_filename_from_utf8 (const gchar *utf8string
,gssize len
,gsize *bytes_read
,gsize *bytes_written
,GError **error
);
Converts a string from UTF-8 to the encoding GLib uses for filenames. Note that on Windows GLib uses UTF-8 for filenames; on other platforms, this function indirectly depends on the current locale.
utf8string |
a UTF-8 encoded string. |
|
len |
the length of the string, or -1 if the string is nul-terminated. |
|
bytes_read |
location to store the number of bytes in
the input string that were successfully converted, or |
[out][allow-none] |
bytes_written |
the number of bytes stored in the output buffer (not including the terminating nul). |
[out] |
error |
location to store the error occurring, or |
The converted string, or NULL
on an error.
[array length=bytes_written][element-type guint8][transfer full]
gboolean
g_get_filename_charsets (const gchar ***charsets
);
Determines the preferred character sets used for filenames.
The first character set from the charsets
is the filename encoding, the
subsequent character sets are used when trying to generate a displayable
representation of a filename, see g_filename_display_name()
.
On Unix, the character sets are determined by consulting the
environment variables G_FILENAME_ENCODING
and G_BROKEN_FILENAMES
.
On Windows, the character set used in the GLib API is always UTF-8
and said environment variables have no effect.
G_FILENAME_ENCODING
may be set to a comma-separated list of
character set names. The special token "@locale" is taken
to mean the character set for the current locale.
If G_FILENAME_ENCODING
is not set, but G_BROKEN_FILENAMES
is,
the character set of the current locale is taken as the filename
encoding. If neither environment variable is set, UTF-8 is taken
as the filename encoding, but the character set of the current locale
is also put in the list of encodings.
The returned charsets
belong to GLib and must not be freed.
Note that on Unix, regardless of the locale character set or
G_FILENAME_ENCODING
value, the actual file names present
on a system might be in any random encoding or just gibberish.
Since 2.6
gchar *
g_filename_display_name (const gchar *filename
);
Converts a filename into a valid UTF-8 string. The conversion is
not necessarily reversible, so you should keep the original around
and use the return value of this function only for display purposes.
Unlike g_filename_to_utf8()
, the result is guaranteed to be non-NULL
even if the filename actually isn't in the GLib file name encoding.
If GLib cannot make sense of the encoding of filename
, as a last resort it
replaces unknown characters with U+FFFD, the Unicode replacement character.
You can search the result for the UTF-8 encoding of this character (which is
"\357\277\275" in octal notation) to find out if filename
was in an invalid
encoding.
If you know the whole pathname of the file you should use
g_filename_display_basename()
, since that allows location-based
translation of filenames.
Since 2.6
gchar *
g_filename_display_basename (const gchar *filename
);
Returns the display basename for the particular filename, guaranteed to be valid UTF-8. The display name might not be identical to the filename, for instance there might be problems converting it to UTF-8, and some files can be translated in the display.
If GLib cannot make sense of the encoding of filename
, as a last resort it
replaces unknown characters with U+FFFD, the Unicode replacement character.
You can search the result for the UTF-8 encoding of this character (which is
"\357\277\275" in octal notation) to find out if filename
was in an invalid
encoding.
You must pass the whole absolute pathname to this functions so that translation of well known locations can be done.
This function is preferred over g_filename_display_name()
if you know the
whole path, as it allows translation.
a newly allocated string containing a rendition of the basename of the filename in valid UTF-8
Since 2.6
gchar * g_locale_from_utf8 (const gchar *utf8string
,gssize len
,gsize *bytes_read
,gsize *bytes_written
,GError **error
);
Converts a string from UTF-8 to the encoding used for strings by the C runtime (usually the same as that used by the operating system) in the current locale. On Windows this means the system codepage.
utf8string |
a UTF-8 encoded string |
|
len |
the length of the string, or -1 if the string is
nul-terminated (Note that some encodings may allow nul
bytes to occur inside strings. In that case, using -1
for the |
|
bytes_read |
location to store the number of bytes in the
input string that were successfully converted, or |
|
bytes_written |
the number of bytes stored in the output buffer (not including the terminating nul). |
|
error |
location to store the error occurring, or |
A newly-allocated buffer containing the converted string,
or NULL
on an error, and error will be set.
gboolean
g_get_charset (const char **charset
);
Obtains the character set for the current locale; you
might use this character set as an argument to g_convert()
, to convert
from the current locale's encoding to some other encoding. (Frequently
g_locale_to_utf8()
and g_locale_from_utf8()
are nice shortcuts, though.)
On Windows the character set returned by this function is the so-called system default ANSI code-page. That is the character set used by the "narrow" versions of C library and Win32 functions that handle file names. It might be different from the character set used by the C library's current locale.
The return value is TRUE
if the locale's encoding is UTF-8, in that
case you can perhaps avoid calling g_convert()
.
The string returned in charset
is not allocated, and should not be
freed.
typedef struct _GIConv GIConv;
The GIConv struct wraps an iconv()
conversion descriptor. It contains
private data and should only be accessed using the following functions.
#define G_CONVERT_ERROR g_convert_error_quark()
Error domain for character set conversions. Errors in this domain will be from the GConvertError enumeration. See GError for information on error domains.
Error codes returned by character set conversion routines.


Employment
- Accenture is a leading global technology services firm. The company clients include over 80% of the Global Fortune 500 companies. Headquartered in Dublin, Ireland with offices all over the globe.
- As Senior Full Stack, I headed our delivery pods for the North America innovation group collaborating with key clients, stakeholders, developers, and designers.
- Coordinating product delivery for Cloud Innovation practice leveraging AWS, Azure, and GCP for clients in a variety of industries including Consumer Goods & Services, Hospitality, Media, Telecommunications, Finance, Non-Profit, and Education.
- Leading efforts in hiring, onboarding and recruitment for the firm both remote and at college campuses
- Mentored and guided other developers on best development practice and in daily code reviews.
Technologies used: AWS Cloud, Azure Cloud, Google Cloud, React, Angular, Spring Boot, Java, PHP, NodeJS, Ruby on Rails, Javascript, HTML, CSS, XML, JSON, LDAP, JWT
- Robert Half International is an IT Staffing Firm working nationally with many medium to large enterprises.
- As a technology consultant I would work with clients both onsite and remote to execute delivery of software development services across media agencies in the Atlanta area.
Technologies used: PHP, Wordpress, Ruby on Rails, React, HTML, JS, CSS, Java, SAP, Bootstrap, Handlebars, NodeJS
- Codecademy is an online interactive platform that offers free coding classes in more than 12 different programming languages.
- As a lead advisor, I was responsible for staying up to date with all content releases and content development. In addition to supporting over 10,000 learners in one to one mentoring sessions, code review, and debugging.
Technologies used: Javascript, React, Angular, AngularJS, Ruby, Ruby on Rails, SQL, PHP, noSQL, NodeJS, Python, Numpy, pandas, d3, data viz, data science
- Undaground was media company that provides an app as a platform for local communities to broadcast their content through a live and on-demand local podcast directory.
- As the founding engineer I acted as the lead, CTO, developer, and business driver.
- I helped the organization keep momentum through local business accelerators.
Technologies used: Javascript, Ionic, Java, iOS, Swift, NodeJS, Rails, GoLang, AWS, Server Administration, Android Studio, Xcode, RTMP, Streaming, Ethereum, Blockchain
Accolades:
Best Overall Business Idea & People's Choice - Will This Float? Music Edition - Dec '15
Co.Lab Accelerator Spring '15 Alumni
- Apple, Inc is a technology company that specializes in consumer electronics, software, and online services
- As a lead supervisor for AppleCare support I reported remote to AppleCare engineering and I was responsible for diagnosis, reporting, and documentation of software bugs and defects, safety issues, and Accessibility support for iPhone, iPad, Mac, OS X and iOS users which involved using bash and command shell tools.
Technologies used: OSX, Windows, Powershell, Terminal, Shell Scripting, iOS, xCode, iOS Developer Program, VNC
- As a Technology Consultant, I helped design websites, digital ad campaigns, and content for different companies and groups around the country from small to medium sized businesses.
Technologies used: PHP, Wordpress, Builder.io, Svelte, React, NodeJS, Rust, Python, Flask, Swift, React Native, Ionic, iOS, Android


The additional features include the Phobos Menu (with 5 new features) and the Auto Layout feature which is accessible directly from an icon on the main GUI or from the Edit menu.
The Phobos menu in MARS is accessible on the top menu bar to the right of Help. From the dropdown menu, you will find the following features.
Tick the checkbox Comma Constraint to enable this feature. When enabled, this feature strictly requires commas to be used in instructions and arrays for the program to assemble.
Example usage:
addi $t1 $t0 1 # This line will NOT assemble because of the lack of commas addi $t1, $t0, 1 # This line WILL assemble because it has the correct number of commas
Note that if the Comma Constraint feature were to be disabled, the above two lines would both assemble.
Tick the checkbox Register Name Constraint to enable this feature. When enabled, this feature strictly requires register names to be used, rather than register numbers, for the program to assemble.
Example usage:
addi $1, $0, 1 # This line will NOT assemble because register numbers are being used addi $t1, $t0, 1 # This line WILL assemble because register names are being used
Note that if the Register Name Constraint feature were to be disabled, the above two lines would both assemble (albeit, the first line would then be using possibly different registers than intended).
Tick the checkbox Offset Constraint to enable this feature. When enabled, this feature strictly requires an offset to be used when using the lw or sw instructions.
Example usage:
lw $t0, ($t1) # This line will NOT assemble because there is not an offset lw $t0, 0($t1) # This line WILL assemble because an offset is supplied
Tick the checkbox Show Register Usage on Assemble to enable this feature. When enabled, this feature will show a popup window when a program is successfully assembled. The popup window will have multiple tabs that one can select (or move between using the arrow keys) to see bar charts on the amount of registers that the assembled program contains.
Example usage:
The above image shows the usage of temporary registers. Using this image alone, one can see how many of each temporary registers are used within the program. According to the image, the program contains six $t3 registers, one $t2 register, and zero $t8 registers.
Select the option Instruction Subset ... to bring up the following dialog window:
This feature can be enabled by ticking the Enable Instruction Subset checkbox. When enabled, this feature allows one to use a whitelist or blacklist to determine what subset of instructions can or can not be used, respectively. Any instructions that are currently in the subset are displayed in the list on the left.
To add an instruction, simply type in any valid instruction into the text box at the top right and then press the + button. If the instruction is invalid, a warning will pop up and the instruction will not be added to the subset.
To remove a selected instruction first select any amount of instructions. Specific instructions can be selected by clicking on them in the subset. To select more than one contiguous instruction hold Shift and click down to the last instruction to be selected. To deselect a specific instruction that you have selected, hold Ctrl and click the instruction. One can also hold Ctrl to pick more than one instruction that is not contiguous.
Once the instruction(s) in the subset to be removed have been selected, press the Remove Selected button to remove them.
To clear all instructions from the subset, press the Clear button.
If Blacklist is selected, then all instructions in the subset are effectively "banned" from being used within the program. If any instructions that are in the subset are used, then the program will not assemble.
If Whitelist is selected, then all instructions in the subset are the only ones allowed to be used within the program. If any instructions that are NOT in the subset are used, then the program will not assemble.
To import specific instructions from a text file, press the Import Subset button. One must have a text file (*.txt extension only) prepared beforehand. Within this text file, any instructions one would like to add to the subset must be entered each on their own line. Any invalid instructions entered will be ignored and not added to the subset.
Example text file:
add addi lw jal
When importing a text file, a prompt will appear asking whether to Overwrite or Add. To overwrite the current instruction subset with the instructions being imported, select the Overwrite button. To add the instructions from the text file to the existing instruction subset, select the Add button. Duplicate instructions do not have to be worried about as duplicates are filtered out.
There are three ways one can use the Auto Layout feature in MARS while editing a file:
Auto Layout can be used at any time to automatically reformat a document to the specified guidelines:
Example usage:
This is the program before Auto Layout is used.
################### # Block of comments ################### .data a: .word 128 # This is a word .text lw $t0, a LABEL: # Label to jump back to addi $t0, $t0, -1 # Subtract one bgt $t0, 0, LABEL
This is the program after Auto Layout is used.
################### # Block of comments ################### .data a: .word 128 # This is a word .text lw $t0, a LABEL: # Label to jump back to addi $t0, $t0, -1 # Subtract one bgt $t0, 0, LABEL


| MATLAB 文件帮助: cv.Utils | 查看 cv.Utils 的代码 | Index |
Utils Utility and system information functions.
| Sealed | false |
| Construct on load | false |
| Utils | Utility and system information functions. |
| Static | checkHardwareSupport | Returns hardware CPU features |
| Static | getBuildInformation | Returns full configuration time CMake output |
| Static | getNumThreads | Returns number of threads used by OpenCV for parallel regions |
| Static | getNumberOfCPUs | Return number of logical CPUs |
| Static | setNumThreads | Sets number of threads used by OpenCV for parallel regions |
| Static | setUseOptimized | Enables or disables the optimized code |
| Static | useOptimized | Returns the status of optimized code usage |


Code Kata - Atari
This Code Kata was set by Keith Braithwaite, at his session TDD As If You Meant It, during Software Craftsmanship 2009.
The challenge is taken from the game of Go.  A stone is atari if a stone or chain of stones has only one liberty. The liberty is the number of vacant points that are adjacent to a stone or connected group of same coloured stones (diagonals do not count). Some example configurations, with their liberty, are shown in the following pictures:
The Kata is to calculate whether a stone is atari, for an arbitrary collection of stones.
Keith had some rules about how you should proceed with coding, which define an extreme limit of TDD:
- Write exactly ONE failing test.
- Make the test from (1) pass by first writing implementation code IN THE TEST.
- Create a new implementation method by:
- doing extract method on implementation code created as per (2), or
- moving implementation code as per (2) into an existing implementation method.
- Only ever create new methods IN THE TEST CLASS.
- Only ever create implementation classes to provide a destination for extracting a method created as per (4).
- Populate implementation classes by doing move method from a test class into them.
- Refactor as required.
- Go to (1).
Some reactions from other attendees of the session are here and here.


三世书首页
Logout and Login Again
{% block mainbody %}
Master Page
{% endblock %}
Done!
Balabalabal.
Continue
Please Hold On!
Please Hold On!!!!!!!!!
And Don't Click Any Where!!!!
Oh snap!
Balabalabal.
Continue


Scientific Fortran Tools (SciFT)
1.2
Main Page
Related Pages
Data Types List
Files
Data Types List
Data Types
Class Hierarchy
Data Fields
All
Classes
Files
Functions
Variables
Pages
Class Hierarchy
Go to the textual class hierarchy
Generated on Fri Mar 13 2015 12:19:34 for Scientific Fortran Tools (SciFT) by
1.8.6


HTML is Really Fun , If you Learn From us
| Introduction To HTML | Brief History of HTML |
| HTML Versions | Features of HTML |
Tim Berners-Lee is known as the father of HTML. The first available description of HTML was a document called "HTML Tags" proposed by Tim in late 1991. The latest version of HTML is HTML5
HTML 1.0: The first version of HTML was 1.0, which was the barebones version of HTML language, and it was released in1991.
HTML 2.0: This was the next version which was released in 1995, and it was standard language version for website design. HTML 2.0 was able to support extra features such as form-based file upload, form elements such as text box, option button, etc.
HTML 3.2: HTML 3.2 version was published by W3C in early 1997. This version was capable of creating tables and providing support for extra options for form elements. It can also support a web page with complex mathematical equations. It became an official standard for any browser till January 1997. Today it is practically supported by most of the browsers.
HTML 4.01: HTML 4.01 version was released on December 1999, and it is a very stable version of HTML language. This version is the current official standard, and it provides added support for stylesheets (CSS) and scripting ability for various multimedia elements.
HTML5 : HTML5 is the newest version of HyperText Markup language. The first draft of this version was announced in January 2008. There are two major organizations one is W3C (World Wide Web Consortium), and another one is WHATWG( Web Hypertext Application Technology Working Group) which are involved in the development of HTML 5 version, and still, it is under development.
2) It is very easy to make an effective presentation with HTML because it has a lot of formatting tags.
3) It is a markup language, so it provides a flexible way to design web pages along with the text.
4) It facilitates programmers to add a link on the web pages (by html anchor tag), so it enhances the interest of browsing of the user.
5) It is platform-independent because it can be displayed on any platform like Windows, Linux, and Macintosh, etc.
6) It facilitates the programmer to add Graphics, Videos, and Sound to the web pages which makes it more attractive and interactive.
7) HTML is a case-insensitive language, which means we can use tags either in lower-case or upper-case.


available:
staked:
Network: Please connect your wallet
Selected Account: 0x...
BNB Balance: 00.0000
Contract:
BSCScan:


| Date | Description | Ref Number | Resolution Method | SLA | In SLA/ Out SLA | Priority | Duration |
|---|---|---|---|---|---|---|---|
| {{issue.added | date:'medium'}} | {{issue.issueDescription}} | {{issue.issueRefNumber}} | {{issue.comments}} | {{issue.issuePriority.prioritySLA}} | {{issue.issueChannel.channelName}} | {{issue.issuePriority.priorityName}} | {{issue.duration}} |


In A Nutshell
Test driven development - or TDD - proposes to start the development process with tests that defines an improvement or new function to a program. While there are different flavors of TDD, most styles seek ask that the developer write the least amount of code to make the test pass first. Refactoring for readability and scalability is a later (but important) consideration.
What About BDD?
Many developers will tell you that BDD is TDD but done right. What they mean is that BDD is TDD but with particular focus on what a user wants and expects out of a system rather than simply testing system outputs. This is very nuanced. You can tell BDD is being used if the tests are phrased more semantically and if you see more integration tests, tests written to test a few functions/features together, being used.
As a product manager (PM), I cared more about what a user saw and expected from a system so I favored BDD in my work. In fact, if you have technical PM, having the PM write BDD can save you time and miscommunications that result from improperly translated user stories.
So remember, there is no distinction between BDD or TDD, it's just a matter of keeping best practices in mind while doing test driven development.


Welcome to Matchmaker 2.0 for Jaylen. In this program we will test to see what our compatibility is. To do so please respond to each question using the drop drop down options provided. At the end, a compatibility score will be calculated. Good luck!


HANNIBAL (2001) Reviewed by Jerry Saravia October 10th, 2001
Ridley Scott's "Hannibal" has been criticized for its over-the-top gross out scenes and little else. There is a reason for this - there is little else to discuss and that is unfortunate. For all the character development that "The Silence of the Lambs" provided for Hannibal Lecter and Clarice Starling, "Hannibal" focuses on cartoonish types in a freak show designed to titillate, a far cry from what "Silence" accomplished.
"Hannibal" begins effectively as we observe Clarice (Julianne Moore, replacing Jodie Foster) on a drug raid with the help of several FBI agents. She kills a drug czar (Hazelle Goodman) by firing a bullet at her chest as she clutches her baby. The incident puts Clarice in a difficult position with the FBI as she has to turn over her gun and badge. She is on the Guiness Book of World Records for being the only FBI female agent to have the most kills. This Clarice, ten years after dealing with Hannibal Lecter face-to-face, is a changed woman, colder and less emotional. Probably a dose of good old Hannibal is just what she needs to get out of her slump. Still, another agent named Krendler (Ray Liotta) has it in for Clarice, and desires her sexually. As always, Clarice's interests in life exclude anything sexual. One funny scene shows Krendler looking at photos of Lecter unaware Clarice is watching him. She alerts him and he asks, "What are you doing in the dark?" Her response: "Thinking of cannibalism."
So far, so good. "Hannibal" then switches to Florence, Italy where the good doctor Lecter resides and is trying to find a job as a museum curator! A detective named Pazzi (Giancarlo Giannini) is investigating the disappearance of the former curator and discovers that the doctor is Hannibal and is on the FBI ten most wanted list (which also includes the terrorist Bin Laden)!
The film's pacing slackens, spending far too much time on the Italian detective and so little on Clarice who is still looking for Hannibal. Keeping the two most memorable characters in the history of movies apart amounts to awkwardly patched-together situations that have little to do with anything. In fact, as written by David Mamet and Steven Zaillian, the story is almost nonexistent. There is no tension, no surprise and a general lack of credibility. How can someone like Hannibal, who never wears a disguise, be able to move about Italy in a flowing cape and a hat and not be noticed? How can you not notice someone wiping the glasses of wine they drink from at a restaurant? Well, the detective notices but surely there must have some way of him communicating this information to the FBI if he wanted to.
Of course, Pazzi chooses not to as his primary motive is financial. You see a certain billionaire by the name of Mason Verger (Gary Oldman) wants Hannibal fed to his killer boars.  Now he is a faceless cipher with no eyelids and a horrifying expression that is sure to creep out the most jaded viewer. He is about as loony as Hannibal himself and provides a handsome reward to anyone who knows of Hannibal's whereabouts. Enter the desperate Pazzi, yet he doesn't realize he is being hounded by Hannibal.
But none of this matters in the least. There is no sense of urgency since Hannibal can escape and elude authorities so easily. The crux of the film is the Florence investigation but I missed the central relationship between Hannibal and Clarice - they so embodied "Silence of the Lambs" that here, they are mostly left on the sidelines. No character shadings or depth to either one of them leaves us out in the cold. A real shame since Julianne Moore is an excellent replacement for Jodie Foster, and a brief meeting between her and Hannibal sheds little light on either one of them.
Another factor is that Hannibal was imprisoned in "Silence" thus leaving plenty of time to understand his motives and desires, and his developing interest in Clarice. Letting him loose like a wild animal does little to raise our expectations - he is simply a madman with an insatiable appetite for flesh who has a host of sardonic comments to make about cannibalism. Where is the charm and elegance Hopkins brought to the original?
Moore is well-cast and strong and empathetic but she still remains as one-note as Hopkins does. It is not her fault, the script needed plenty of fine-tuning but what can you say about two top-of-the-class screenwriters hired to provide such a mediocre, rambling screenplay?
"Hannibal" looks and sounds terrific thanks to director Ridley Scott. It is glossy filmmaking but with no soul or human interest. A climactic dinner sequence remains as loathsome and gory a sequence as anything Hollywood has ever produced before (though Scott has directed it tastefully). But mean-spiritedness and gore are central to "Hannibal" - it is a bloodless freak show where the characters are all cartoons. "Silence of the Lambs" defied genre expectations by never quite fitting into a thriller mode or a horror movie scenario - it was, at its best, a psychological character study with a gripping hold on the audience through its sheer intensity and surefire direction by Jonathan Demme. This film is a pure slasher flick, unengaging and uneven. And all poor old Hannibal has left to say are such flat one-liners like "Goody-goody" and "Ta-da." How rude!
For more reviews, check out JERRY AT THE MOVIES at http://moviething.com/members/movies/faust/JATMindex.shtml
E-mail me with any questions, comments or general complaints at<EMAIL_ADDRESS>or at<EMAIL_ADDRESS>========== X-RAMR-ID: 29793 X-Language: en X-RT-ReviewID: 254293 X-RT-TitleID: 1104385 X-RT-SourceID: 875 X-RT-AuthorID: 1314
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


This page is not yet done. Please see the todo list for information on how you can help finish this manual.


{% extends "djtracker/base.html" %} {% block content %}
You may now browse the site. You may need to ask your administrator to assign you to necessary groups to browse certain projects however.


Account
Checkout
Cart
Login
Toggle navigation
Home
Shop
Contact
Features Items
$100
White Skunk
5 seeds per bag
Add to cart


{%extends "base.html" %} {%if not icon%}{%macro icon(what)%}{%endmacro%}{%endif%} {%block title%}Conference Sessions - {{conference}}{%endblock%} {%block content%}
The following list contains all the talks that have been approved so far for {{conference}}. Note that they may not yet have been scheduled! You can find the full conference information at the conference website.
{%for track,sessionlist in sessions|groupby_sort('track', 'sortkey')%}


Financial Protection Advisor (Web App)Full Stack (RoR, SQL, Oracle DB)
OWStats Bot for RedditPython, BeautifulSoup, and Selenium
Wikipedia Search EngineHTML/CSS, JavaSript, and API
Future Project Placeholder


Skip to navigation
Skip to content
Skip to footer
Homepage - a11ycast example
Article Title
Another Article Title
Open dialog
Dialog Example
But awesome stuff. It's really aweomse.
Close
Ok


SORRY!
YOU'RE NOT ELIGIBLE
Our marketing code states that you are not eligible to view the content that you have requested. Unfortunately, this is as far as you can go on our website.
For more information about how we only promote our products responsibly, please follow the link to the Mars Marketing Code. For more information about our Marketing Code, please click here.


Police: Drone 'instrumental' in overnight search for missing man found incoherent in culvert
by Tabatha WethalSUN PRAIRIE, Wis. - Authorities were able to find a missing man using a drone early Thursday, according to police.
The Sun Prairie Police Department said that at about 2:40 a.m. Thursday, an officer from the Sun Prairie Police Department observed a vehicle in a near a new housing development off O'Keeffe Avenue.
The officer investigated the potentially suspicious vehicle, which was unoccupied with the engine running and a door open.
Additional officers began searching the area for a 57-year-old man, according to the report. Contact was made with the man's family, who determined no one had heard from him since 2:30 p.m. Wednesday.
The Dane County Sheriff's Office was brought in to provide a K-9 to assist with a track, police said.
A ping of the man's phone was plotting near the area, officials said. A request was made for a drone with thermal imaging to assist in the search, which Madison police officers were able to provide.
Police said the drone search began at approximately 3:25 a.m. The drone was able to pick up a thermal signature within 2 to 4 minutes, and officers found the man lying in a culvert at approximately 3:48 a.m.
The man was found alive but incoherent, police said. He was taken to a hospital and was in critical condition.
Authorities said it was determined that the man suffered a medically significant event and likely drove off the road, into the field, then wandered from his vehicle.
Police said that as of Friday afternoon, there have been no indications of foul play.
Sun Prairie police thanked the Dane County Sheriff's Office and Madison Police Department for their help in the case.
"The thermal imaging drone was instrumental in finding this person alive," Sun Prairie police said in a statement.


The last week has been a lot of fun travels, great meetups, and solid meetings. All focused around several key topics;
- traveling to nearby cities to speak & present on immutable infrastructure with Terraform and Kubernetes and…
- meetings to help build next generation applications for medical, personal, and privacy tracking information.
Before rolling into this week I wanted to put together a quick recap of events and meetings.
The travel consisted of an easy trip to Olympia. I always love traveling to Olympia, and in normal Adron fashion I do it my way, which consists of no cars but a lot of other fun stuff.  But I’m sure that this is part of the beauty of this small city. It helps keep it free of arbitrary “pass through” traffic of people who’d not care or just toss their trash randomly about the city.
One can study this phenom with cities in the US which have an Interstate cut through them, with exits, and an Interstate that goes around the city. Massively different results, the later letting a city retain cleanliness and it’s own much better then the aforementioned technique.
Olympia, I might add is one of the few small cities that really retains a lot of the zeal and attractiveness of the gritty northwest vibe of yesteryear. Oly, as it’s oft referred has tons of unique, local, individualistic shops and street culture. One might be amazed to see such a thing in such a small city, but Oly is one of those few places that bats above its weight. It’s definitely worth visiting.
Each visit to Olympia that I’ve taken I stay at a few different places.
- Sometimes at my buddy Bobby’s house.
- Sometimes at an airbnb.
- Regularly at the Governor in downtown.
The Governor in downtown is this classic 50’s era hotel. It faces the old Capital across the park, just near where the new capital is, but the benefit is its even closer to downtown Olympia. Here I’ve scratched a circle around it, where I go to speak just north of the hotel at the South Sound Developers User Group, and then we always retire to the east at Fish Tale Brewing.
The trip to Olympia I enjoy immensely. It all starts with the standard Amtrak Cascades departure from Seattle at King Street Station. The departure was on time, as was the arrival, which is something that is pretty standard on our northwestern Cascades train routes. I don’t always expect them to be, being US trains, but these are pretty reliable here.
After the scenic and relaxing coding session on the train, I arrive at the station in Olympia. This station is a cute little deal, located in the suburbs on the freight line about ~8 miles or so east of downtown Oly. You see, in typical American fashion the state, federal regs, and railroad(s), along with a failure of foresight by previous generations decided they’d tear up the track connection to the station that did exist in Olympia. This station, of course, was built around people traveling from Oly to other places, and was built intelligently, as we tended to do in long lost past decades. But hey, I arrived at the new station and as I generally do, I had a plan already sorted.
I’ve put together a few photos and a video short for the trip too, enjoy.
My path along the Chehalis Trail into Olympia
Looking at the Old Tracks in Olympia along Colorful Leaves
There’s a spectacular trail that is very close to the station that I take built upon an old rail line that was abandoned. Here’s a map with the trail highlighted along with the northern and southern connecting routes. At the southern end I’ve circled the Amtrak Lacey Station (Lacey, being where it is actually located, I always call it Olympia though because that’s the distinctively larger city!)
I might muster some time to post the other images and video from the trip later. But for now, this is it. In other news, I’ve got my “Secret Business Brunch n’ Bike” brunch lunch scheduled tomorrow at Hi-Life @ 11, and also Beers on Wednesday. Feel free to join me, always hacking, biking, and eating something. Cheers!


Content-type: text/html;charset=UTF-8 Set-cookie: session=7777
Person is a grammatical category that distinguishes between different discourse participants. Natural languages generally distinguish up to three discourse participants: the speaker (the first person), the person spoken to (the second person), and anyone else (the third person). Some languages are analyzed as having an additional fourth person category, whose meaning varies from language to language. The answers you provide on this page will determine what values are available later in the questionnaire for the person feature (or the pernum feature; see below).
Which values of person are distinguished in your language? none First, second, and third First, second, third, and fourth First and non-first Second and non-second Third and non-third
Some languages are best analyzed as having subtypes of the first person for some values of the number feature. For example, inclusive/exclusive languages make a distinction in the non-singular between the first person exclusive, which does not include the person spoken to, and the first person inclusive, which does. In minimal/augmented languages, three distinctions are made: speaker and one person spoken to, speaker and one other (third) person, and speaker and more than one other person.
What subtypes does your language distinguish in the first person? none inclusive and exclusive in the: other: