{% extends "tutorial.html" %}
{% block headauthor %}Paul Lewis I have used Three.js for some of my experiments, and it does a really great job of
abstracting away the headaches of getting going with 3D in the browser.
 And since it's
open source you could even get involved with the project. But right now
I'll focus on what I've learned by playing with it as an engine, and talk
you through some of the basics. For all the awesomeness of Three.js, there can be times where you
might struggle. Typically you will need to spend quite a large amount of time with
the examples, reverse engineering and (in my case certainly) hunting down
specific functionality and occasionally asking questions via GitHub. If you
have to as questions, by the way, I've found Mr. doob and AlteredQualia are
extremely helpful! I will assume that you have at
least a passing knowledge of 3D, and reasonable proficiency with
JavaScript. If you don't it may be worth learning a bit before you try
and play with this stuff, as it can get a little confusing. In our 3D world we will have some of the following, which I will
guide you through the process of creating: You can, of course, do some crazy things, and my hope is that you will
go on to do that and start to experiment with 3D in your browser. Just a quick note on support in the browsers. Google's Chrome browser is, in my experience,
the best browser to work with in terms of which renderers are supported, and
the speed of the underlying JavaScript engine. Chrome supports
Canvas, WebGL and SVG and it's blazingly fast. Firefox is a close second, with the
advent of version 4. Its JavaScript engine does seem to be a touch slower than
Chrome's, but again its support for the render technologies is great. Opera and Safari
are in the process of adding WebGL support, but their current versions only support canvas.
Internet Explorer (version 9+) support canvas rendering only, and I've not heard
anything of Microsoft planning to add WebGL capabilities. I'll assume you've chosen a browser that supports all the rendering technologies,
and that you want to render with canvas or WebGL, since they're the more standard
choices. Canvas is more widely supported than WebGL, but it's worth noting that
WebGL runs on your graphics card's GPU, which means that your CPU can concentrate
on other non-rendering tasks like any physics or user interaction you're trying to
do. Irrespective of your chosen renderer you should bear in mind that the JavaScript
will need to optimised for performance. 3D isn't a lightweight task for a browser
(and it's awesome that it's even possible), so be careful to understand where any
bottlenecks are in your code, and remove them if you can! So with that said, and on the assumption you have downloaded and included three.js
in your HTML file, how do you go about setting up a scene? Like this:
Introduction
1. The basics
2. Support
3. Set the Scene
// set the scene size
var WIDTH = 400,
HEIGHT = 300;
// set some camera attributes
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1,
FAR = 10000;
// get the DOM element to attach to
// - assume we've got jQuery to hand
var $container = $('#container');
// create a WebGL renderer, camera
// and a scene
var renderer = new THREE.WebGLRenderer();
var camera = new THREE.PerspectiveCamera(
VIEW_ANGLE,
ASPECT,
NEAR,
FAR );
var scene = new THREE.Scene();
// the camera starts at 0,0,0 so pull it back
camera.position.z = 300;
// start the renderer
renderer.setSize(WIDTH, HEIGHT);
// attach the render-supplied DOM element
$container.append(renderer.domElement);
Not too tricky, really!
So we have a scene, a camera and a renderer (I opted for a WebGL one in my sample code) but we have nothing to actually draw. Three.js actually comes with support for loading a few different standard file types, which is great if you are outputting models from Blender, Maya, Cinema4D or anything else. To keep things simple (this is about getting started after all!) I'll talk about primitives. Primitives are geometric meshes, relatively basic ones like Spheres, Planes, Cubes and Cylinders. Three.js lets you create these types of primitives easily:
// set up the sphere vars var radius = 50, segments = 16, rings = 16; // create a new mesh with sphere geometry - // we will cover the sphereMaterial next! var sphere = new THREE.Mesh( new THREE.SphereGeometry(radius, segments, rings), sphereMaterial); // add the sphere to the scene scene.add(sphere);All good, but what about the material for the sphere? In the code we've used a variable sphereMaterial but we've not defined it yet. First we need to talk about materials in a bit more detail.
Without doubt this is one of the most useful parts of Three.js. It provides for you a number of common (and very handy) materials to apply to your meshes:
There are more, but again in the interests of simplicity I'll let you discover those for yourself. In the case of WebGL particularly these materials can be a life-saver. Why? Well because in WebGL you have to write shaders for everything being rendered. Shaders are a huge topic in themselves, but in short they are written in GLSL (OpenGL Shader Language), which tells the GPU how something should look. This means you need to mimic the maths of lighting, reflection and so on. It can get very complicated very quickly. Thanks to Three.js you don't have to do this if you don't want to because it abstracts that away for you. If you want to write shaders, however, you can do that too with a MeshShaderMaterial, so it's a flexible setup.
For now, however, let's apply a lambert material to the sphere:
// create the sphere's material var sphereMaterial = new THREE.MeshLambertMaterial( { // a gorgeous red. color: 0xCC0000 });It's worth pointing out as well that there are other properties you can specify when you create a material besides the colour, such as smoothing or environment maps. You should check out the Wiki page for the various properties you can set on the materials and, in fact, any object that the engine provides for you. Also threejs.org recently sprung up, which offers a more attractive view of the API.
If you were to render the scene right now you'd see a red circle. Even though we have a Lambert material applied there's no light in the scene so by default Three.js will revert to a full ambient light, which is the same as flat colouring. Let's fix that with a simple point of light:
// create a point light var pointLight = new THREE.PointLight( 0xFFFFFF ); // set its position pointLight.position.x = 10; pointLight.position.y = 50; pointLight.position.z = 130; // add to the scene scene.add(pointLight);
We now actually have everything set up to render, remarkably. But we actually need to go ahead and do just that:
// draw! renderer.render(scene, camera);And this is how it looks:
You're probably going to want to render more than once, though, so if you're going to do a loop you should really use requestAnimationFrame; it's by far the smartest way of handling animation in the browser. It's not fully supported as yet, so I'd totally recommend that you take a look at Paul Irish's shim.
If you take time to look through the code for Three.js you'll see a lot of objects "inherit" from Object3D. This is a base object which contains some very useful properties, such as the position, rotation and scale information. In particular our Sphere is a Mesh which inherits from Object3D, to which it adds its own properties: geometry and materials. Why do I mention these? Well it's unlikely you're going to want to just have a sphere on your screen that does nothing, and these properties are worth investigating as they allow you to manipulate the underlying details of the meshes and materials on the fly.
// sphere geometry sphere.geometry // which contains the vertices and faces sphere.geometry.vertices // an array sphere.geometry.faces // also an array // its position sphere.position // has x, y and z properties sphere.rotation // same sphere.scale // ... same
I just wanted to quickly point out a quick gotcha for Three.js, which is that if you modify, for example, the vertices of a mesh, you will notice in your render loop that nothing changes. Why? Well because Three.js (as far as I can tell) caches the data for a mesh as something of an optimisation. What you actually need to do is to flag to Three.js that something has changed so it can recalculate whatever it needs to. You do this with the following:
// changes to the vertices sphere.geometry.__dirtyVertices = true; // changes to the normals sphere.geometry.__dirtyNormals = true;Again there are more, but those two I've found are the most useful. You should obviously only flag the things that have changed to avoid unnecessary calculations.
Well I hope you've found this brief introduction to Three.js helpful. There's nothing quite like actually getting your hands dirty and trying something, and I can't recommend it highly enough. 3D running natively in the browser is a lot of fun, and using an engine like Three.js takes away a lot of the headaches for you and lets you get to making some seriously cool stuff.
To help you out a bit I've wrapped up the source code in this lab article, so you can use that as a reference.
If you've enjoyed this let me know via Twitter, it's always good to say hello!
{% endblock %}


Testing on Multiple Platforms#
Sage is intended to build and run on a variety of platforms, including all major Linux distributions, as well as MacOS, and Windows (with Cygwin and WSL).
There is considerable variation among these platforms. To ensure that Sage continues to build correctly on users’ machines, it is crucial to test changes to Sage, in particular when external packages are added or upgraded, on a wide spectrum of platforms.
GitHub actions#
The GitHub Actions will automatically test your GitHub PR by attempting an incremental build of Sage and running doctests.
Sage buildbots#
The Sage Release buildbot builds entire tarballs (e.g., all the development releases) on a variety of machines.
Developers’ and users’ tests on sage-release#
Sage developers and users are encouraged to contribute to testing releases that are announced on Sage Release on their machines and to report test results (success and failures) by responding to the announcements.
Testing Sage on a different platform using Docker#
Docker is a popular virtualization software, running Linux operating system images (“Docker images”) in containers on a shared Linux kernel. These containers can be run using a Docker client on your Linux, Mac, or Windows box, as well as on various cloud services.
To get started, you need to install a Docker client. The clients are available for Linux, Mac, and Windows. The clients for the latter are known as “Docker Desktop”.
Make sure that your Docker client is configured to provide enough RAM to the containers (8 GB are a good choice). In Docker Desktop this setting is in Preferences -> Resources -> Advanced.
All examples in this section were obtained using Docker Desktop for Mac; but the command-line user interface for the other platforms is identical.
All major Linux distributions provide ready-to-use Docker images, which are published via Docker Hub. For example, to run the current stable (LTS) version of Ubuntu interactively, you can use the shell command:
[mkoeppe@sage sage]$ docker run -it ubuntu:latest
root@9f3398da43c2:/#
Here ubuntu
is referred to as the “image (name)” and latest
as
the “tag”. Other releases of Ubuntu are available under different
tags, such as xenial
or devel
.
The above command drops you in a root shell on the container:
root@9f3398da43c2:/# uname -a
Linux 9f3398da43c2 4.19.76-linuxkit #1 SMP Thu Oct 17 19:31:58 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
root@9f3398da43c2:/# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 181G 116G 56G 68% /
tmpfs 64M 0 64M 0% /dev
tmpfs 2.7G 0 2.7G 0% /sys/fs/cgroup
shm 64M 0 64M 0% /dev/shm
/dev/sda1 181G 116G 56G 68% /etc/hosts
tmpfs 2.7G 0 2.7G 0% /proc/acpi
tmpfs 2.7G 0 2.7G 0% /sys/firmware
Exiting the shell terminates the container:
root@9f3398da43c2:/# ^D
[mkoeppe@sage sage]$
Let us work with a distclean Sage source tree. If you are using git,
a good way to get one (without losing a precious installation in
SAGE_LOCAL
) is by creating a new worktree:
[mkoeppe@sage sage] git worktree add worktree-ubuntu-latest
[mkoeppe@sage sage] cd worktree-ubuntu-latest
[mkoeppe@sage worktree-ubuntu-latest] ls
COPYING.txt ... Makefile ... configure.ac ... src tox.ini
This is not bootstrapped (configure
is missing), so let’s bootstrap it:
[mkoeppe@sage worktree-ubuntu-latest] make configure
...
We can start a container again with same image, ubuntu:latest
, but
this time let’s mount the current directory into it:
[mkoeppe@sage worktree-ubuntu-latest]$ docker run -it --mount type=bind,source=$(pwd),target=/sage ubuntu:latest
root@39d693b2a75d:/# mount | grep sage
osxfs on /sage type fuse.osxfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other,max_read=1048576)
root@39d693b2a75d:/# cd sage
root@39d693b2a75d:/sage# ls
COPYING.txt ... Makefile ... config configure configure.ac ... src tox.ini
Typical Docker images provide minimal installations of packages only:
root@39d693b2a75d:/sage# command -v python
root@39d693b2a75d:/sage# command -v gcc
root@39d693b2a75d:/sage#
As you can see above, the image ubuntu:latest
has neither a Python nor
a GCC installed, which are among the build prerequisites of Sage. We
need to install them using the distribution’s package manager first.
Sage facilitates testing various distributions on Docker as follows.
Discovering the system’s package system#
root@39d693b2a75d:/sage# build/bin/sage-guess-package-system
debian
Let’s install gcc, hoping that the Ubuntu package providing it is
simply named gcc
. If we forgot what the package manager on
Debian-derived distributions is called, we can ask Sage for a
reminder:
root@39d693b2a75d:/sage# build/bin/sage-print-system-package-command debian install gcc
apt-get install gcc
We remember that we need to fetch the current package lists from the server first:
root@39d693b2a75d:/sage# apt-get update
root@39d693b2a75d:/sage# apt-get install gcc
Using Sage’s database of distribution prerequisites#
The source code of the Sage distribution contains a database of
package names in various distributions’ package managers. For
example, the file build/pkgs/_prereq/distros/debian.txt
contains the following
# This file, build/pkgs/_prereq/distros/debian.txt, contains names
# of Debian/Ubuntu packages needed for installation of Sage from source.
#
# In addition, the files build/pkgs/SPKG/distros/debian.txt contain the names
# of packages that provide the equivalent of SPKG.
#
# Everything on a line after a # character is ignored.
binutils
make
m4
perl
# python3-minimal is not enough on debian buster, ubuntu bionic - it does not have urllib
python3 # system python for bootstrapping the build
tar
bc
gcc
# On debian buster, need C++ even to survive 'configure'. Otherwise:
# checking how to run the C++ preprocessor... /lib/cpp
# configure: error: in `/sage':
# configure: error: C++ preprocessor "/lib/cpp" fails sanity check
g++
# Needed if we download some packages from a https upstream URL
ca-certificates
From this information, we know that we can use the following command on our container to install the necessary build prerequisites:
root@39d693b2a75d:/sage# apt-get install binutils make m4 perl python3 tar bc gcc g++ ca-certificates
Reading package lists... Done
Building dependency tree
Reading state information... Done
tar is already the newest version (1.29b-2ubuntu0.1).
The following additional packages will be installed:
...
Done.
(The Sage Installation Guide also provides such command lines for some distributions; these are automatically generated from the database of package names.)
Now we can start the build:
root@39d693b2a75d:/sage# ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking for root user... yes
configure: error: You cannot build Sage as root, switch to an unprivileged user. (If building in a container, use --enable-build-as-root.)
Let’s just follow this helpful hint:
root@39d693b2a75d:/sage# ./configure --enable-build-as-root
checking for a BSD-compatible install... /usr/bin/install -c
...
Using Sage’s database of equivalent distribution packages#
At the end of the ./configure
run, Sage issued a message like the
following:
configure: notice: the following SPKGs did not find equivalent system packages: arb boost_cropped bzip2 ... zeromq zlib
checking for the package system in use... debian
configure: hint: installing the following system packages is recommended and may avoid building some of the above SPKGs from source:
configure: $ sudo apt-get install libflint-arb-dev ... libzmq3-dev libz-dev
configure: After installation, re-run configure using:
configure: $ ./config.status --recheck && ./config.status
This information comes from Sage’s database of equivalent distribution packages. For example:
root@39d693b2a75d:/sage# ls build/pkgs/arb/distros/
arch.txt conda.txt debian.txt gentoo.txt
root@39d693b2a75d:/sage# cat build/pkgs/arb/distros/debian.txt
libflint-arb-dev
Note that these package equivalencies are based on a current stable or testing version of the distribution; the packages are not guaranteed to exist in every release or derivative distribution.
The Sage distribution is intended to build correctly no matter what superset of the set of packages forming the minimal build prerequisites is installed on the system. If it does not, this is a bug of the Sage distribution and should be reported and fixed on a ticket. Crucial part of a bug report is the configuration of the system, in particular a list of installed packages and their versions.
Let us install a subset of these packages:
root@39d693b2a75d:/sage# apt-get install libbz2-dev bzip2 libz-dev
Reading package lists... Done
...
Setting up zlib1g-dev:amd64 (1:1.2.11.dfsg-0ubuntu2) ...
root@39d693b2a75d:/sage#
Committing a container to disk#
After terminating the container, we can create a new image corresponding to its current state:
root@39d693b2a75d:/sage# ^D
[mkoeppe@sage worktree-ubuntu-latest]$ docker ps -a | head -n3
CONTAINER ID IMAGE COMMAND CREATED STATUS
39d693b2a75d ubuntu:latest "/bin/bash" 8 minutes ago Exited (0) 6 seconds ago
9f3398da43c2 ubuntu:latest "/bin/bash" 8 minutes ago Exited (0) 8 minutes ago
[mkoeppe@sage worktree-ubuntu-latest]$ docker commit 39d693b2a75d ubuntu-latest-minimal-17
sha256:4151c5ca4476660f6181cdb13923da8fe44082222b984c377fb4fd6cc05415c1
Here, 39d693b2a75d
was the container id (which appeared in the
shell prompts and in the output of docker ps
), and
ubuntu-latest-minimal-17
is an arbitrary symbolic name for the new
image. The output of the command is the id of the new image. We can
use either the symbolic name or the id to refer to the new image.
We can run the image and get a new container with the same state as the one that we terminated. Again we want to mount our worktree into it; otherwise, because we did not make a copy, the new container will have no access to the worktree:
[mkoeppe@sage worktree-ubuntu-latest]$ docker run -it \
--mount type=bind,source=$(pwd),target=/sage ubuntu-latest-minimal-17
root@73987568712c:/# cd sage
root@73987568712c:/sage# command -v gcc
/usr/bin/gcc
root@73987568712c:/sage# command -v bunzip2
/usr/bin/bunzip2
root@73987568712c:/sage# ^D
[mkoeppe@sage worktree-ubuntu-latest]$
The image ubuntu-latest-minimal-17
can be run in as many
containers as we want and can also be shared with other users or
developers so that they can run it in a container on their machine.
(See the Docker documentation on how to share images on Docker Hub or to save images to a
tar archive.)
This facilitates collaboration on fixing portability bugs of the Sage distribution. After reproducing a portability bug on a container, several developers can work on fixing the bug using containers running on their respective machines.
Generating dockerfiles#
Sage also provides a script for generating a Dockerfile
, which is
a recipe for automatically building a new image:
[mkoeppe@sage sage]$ build/bin/write-dockerfile.sh debian ":standard: :optional:" > Dockerfile
(The second argument is passed to sage -package list
to find packages for the listed package types.)
The Dockerfile
instructs the command docker build
to build a
new Docker image. Let us take a quick look at the generated file;
this is slightly simplified:
[mkoeppe@sage sage]$ cat Dockerfile
# Automatically generated by SAGE_ROOT/build/bin/write-dockerfile.sh
# the :comments: separate the generated file into sections
# to simplify writing scripts that customize this file
...
First, it instructs docker build
to start from an existing base
image…:
...
ARG BASE_IMAGE=ubuntu:latest
FROM ${BASE_IMAGE}
...
Then, to install system packages…:
...
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -qqq --no-install-recommends --yes binutils make m4 perl python3 ... libzmq3-dev libz-dev && apt-get clean
Then, to bootstrap and configure…:
RUN mkdir -p /sage
WORKDIR /sage
ADD Makefile VERSION.txt README.md bootstrap configure.ac sage ./
ADD src/doc/bootstrap src/doc/bootstrap
ADD m4 ./m4
ADD build ./build
RUN ./bootstrap
ADD src/bin src/bin
ARG EXTRA_CONFIGURE_ARGS=""
RUN ./configure --enable-build-as-root ${EXTRA_CONFIGURE_ARGS} || (cat config.log; exit 1)
Finally, to build and test…:
ARG NUMPROC=8
ENV MAKE="make -j${NUMPROC}"
ARG USE_MAKEFLAGS="-k"
RUN make ${USE_MAKEFLAGS} base-toolchain
ARG TARGETS_PRE="all-sage-local"
RUN make ${USE_MAKEFLAGS} ${TARGETS_PRE}
ADD src src
ARG TARGETS="build ptest"
RUN make ${USE_MAKEFLAGS} ${TARGETS}
You can customize the image build process by passing build arguments to the
command docker build
. For example:
[mkoeppe@sage sage]$ docker build . -f Dockerfile \
--build-arg BASE_IMAGE=ubuntu:latest \
--build-arg NUMPROC=4 \
--build-arg EXTRA_CONFIGURE_ARGS="--with-python=/usr/bin/python3.42"
These arguments (and their default values) are defined using ARG
commands in the Dockerfile
.
The above command will build Sage from scratch and will therefore take
quite long. Let us instead just do a partial build, consisting of one
small package, by setting the arguments TARGETS_PRE
and
TARGETS
. We use a silent build (make V=0
):
[mkoeppe@sage sage]$ docker build . -f Dockerfile \
--build-arg TARGETS_PRE=ratpoints \
--build-arg TARGETS=ratpoints \
--build-arg USE_MAKEFLAGS="V=0"
Sending build context to Docker daemon 285MB
Step 1/28 : ARG BASE_IMAGE=ubuntu:latest
...
Step 2/28 : FROM ${BASE_IMAGE}
---> 549b9b86cb8d
...
Step 25/28 : RUN make SAGE_SPKG="sage-spkg -y -o" ${USE_MAKEFLAGS} ${TARGETS_PRE}
...
make[1]: Entering directory '/sage/build/make'
sage-logger -p 'sage-spkg -y -o ratpoints-2.1.3.p5' '/sage/logs/pkgs/ratpoints-2.1.3.p5.log'
[ratpoints-2.1.3.p5] installing. Log file: /sage/logs/pkgs/ratpoints-2.1.3.p5.log
[ratpoints-2.1.3.p5] successfully installed.
make[1]: Leaving directory '/sage/build/make'
real 0m18.886s
user 0m1.779s
sys 0m0.314s
Sage build/upgrade complete!
...
---> 2d06689d39fa
Successfully built 2d06689d39fa
We can now start a container using the image id shown in the last step:
[mkoeppe@sage sage]$ docker run -it 2d06689d39fa bash
root@fab59e09a641:/sage# ls -l logs/pkgs/
total 236
-rw-r--r-- 1 root root 231169 Mar 26 22:07 config.log
-rw-r--r-- 1 root root 6025 Mar 26 22:27 ratpoints-2.1.3.p5.log
root@fab59e09a641:/sage# ls -l local/lib/*rat*
-rw-r--r-- 1 root root 177256 Mar 26 22:27 local/lib/libratpoints.a
You can customize the image build process further by editing the
Dockerfile
. For example, by default, the generated Dockerfile
configures, builds, and tests Sage. By deleting or commenting out the
commands for the latter, you can adjust the Dockerfile to stop after
the configure
phase, for example.
Dockerfile
is the default filename for Dockerfiles. You can
change it to any other name, but it is recommended to use
Dockerfile
as a prefix, such as Dockerfile-debian-standard
.
It should be placed within the tree rooted at the current directory
(.
); if you want to put it elsewhere, you need to learn about
details of “Docker build contexts”.
Note that in contrast to the workflow described in the above sections,
the Dockerfile
copies a snapshot of your Sage worktree into
the build container, using ADD
commands, instead of mounting the
directory into it. This copying is subject to the exclusions in the
.gitignore
file (via a symbolic link from .dockerignore
).
Therefore, only the sources are copied, but not your configuration
(such as the file config.status
), nor the $SAGE_LOCAL
tree,
nor any other build artefacts.
Because of this, you can build a Docker image using the generated
Dockerfile
from your main Sage development tree. It does not have
to be distclean to start, and the build will not write into it at all.
Hence, you can continue editing and compiling your Sage development
tree even while Docker builds are running.
Debugging a portability bug using Docker#
Let us do another partial build. We choose a package that we suspect
might not work on all platforms, surf
, which was marked as
“experimental” in 2017:
[mkoeppe@sage sage]$ docker build . -f Dockerfile \
--build-arg BASE_IMAGE=ubuntu:latest \
--build-arg NUMPROC=4 \
--build-arg TARGETS_PRE=surf \
--build-arg TARGETS=surf
Sending build context to Docker daemon 285MB
Step 1/28 : ARG BASE_IMAGE=ubuntu:latest
Step 2/28 : FROM ${BASE_IMAGE}
---> 549b9b86cb8d
...
Step 24/28 : ARG TARGETS_PRE="all-sage-local"
---> Running in 17d0ddb5ad7b
Removing intermediate container 17d0ddb5ad7b
---> 7b51411520c3
Step 25/28 : RUN make SAGE_SPKG="sage-spkg -y -o" ${USE_MAKEFLAGS} ${TARGETS_PRE}
---> Running in 61833bea6a6d
make -j4 build/make/Makefile --stop
...
[surf-1.0.6-gcc6] Attempting to download package surf-1.0.6-gcc6.tar.gz from mirrors
...
[surf-1.0.6-gcc6] http://mirrors.mit.edu/sage/spkg/upstream/surf/surf-1.0.6-gcc6.tar.gz
...
[surf-1.0.6-gcc6] Setting up build directory for surf-1.0.6-gcc6
...
[surf-1.0.6-gcc6] /usr/bin/ld: cannot find -lfl
[surf-1.0.6-gcc6] collect2: error: ld returned 1 exit status
[surf-1.0.6-gcc6] Makefile:504: recipe for target 'surf' failed
[surf-1.0.6-gcc6] make[3]: *** [surf] Error 1
...
[surf-1.0.6-gcc6] Error installing package surf-1.0.6-gcc6
...
Makefile:2088: recipe for target '/sage/local/var/lib/sage/installed/surf-1.0.6-gcc6' failed
make[1]: *** [/sage/local/var/lib/sage/installed/surf-1.0.6-gcc6] Error 1
make[1]: Target 'surf' not remade because of errors.
make[1]: Leaving directory '/sage/build/make'
...
Error building Sage.
The following package(s) may have failed to build (not necessarily
during this run of 'make surf'):
* package: surf-1.0.6-gcc6
last build time: Mar 26 22:07
log file: /sage/logs/pkgs/surf-1.0.6-gcc6.log
build directory: /sage/local/var/tmp/sage/build/surf-1.0.6-gcc6
...
Makefile:31: recipe for target 'surf' failed
make: *** [surf] Error 1
The command '/bin/sh -c make SAGE_SPKG="sage-spkg -y -o" ${USE_MAKEFLAGS} ${TARGETS_PRE}' returned a non-zero code: 2
Note that no image id is shown at the end; the build failed, and no image is created. However, the container in which the last step of the build was attempted exists:
[mkoeppe@sage sage]$ docker ps -a |head -n3
CONTAINER ID IMAGE COMMAND CREATED STATUS
61833bea6a6d 7b51411520c3 "/bin/sh -c 'make SA…" 9 minutes ago Exited (2) 1 minute ago
73987568712c ubuntu-latest-minimal-17 "/bin/bash" 24 hours ago Exited (0) 23 hours ago
We can copy the build directory from the container for inspection:
[mkoeppe@sage sage]$ docker cp 61833bea6a6d:/sage/local/var/tmp/sage/build ubuntu-build
[mkoeppe@sage sage]$ ls ubuntu-build/surf*/src
AUTHORS TODO curve misc
COPYING acinclude.m4 debug missing
ChangeLog aclocal.m4 dither mkinstalldirs
INSTALL background.pic docs mt
Makefile config.guess draw src
Makefile.am config.log drawfunc surf.1
Makefile.global config.status examples surf.xpm
Makefile.in config.sub gtkgui yaccsrc
NEWS configure image-formats
README configure.in install-sh
Alternatively, we can use docker commit
as explained earlier to
create an image from the container:
[mkoeppe@sage sage]$ docker commit 61833bea6a6d
sha256:003fbd511016fe305bd8494bb1747f0fbf4cb2c788b4e755e9099d9f2014a60d
[mkoeppe@sage sage]$ docker run -it 003fbd511 bash
root@2d9ac65f4572:/sage# (cd /sage/local/var/tmp/sage/build/surf* && /sage/sage --buildsh)
Starting subshell with Sage environment variables set. Don't forget
to exit when you are done.
...
Note: SAGE_ROOT=/sage
(sage-buildsh) root@2d9ac65f4572:surf-1.0.6-gcc6$ ls /usr/lib/libfl*
/usr/lib/libflint-2.5.2.so /usr/lib/libflint-2.5.2.so.13.5.2 /usr/lib/libflint.a /usr/lib/libflint.so
(sage-buildsh) root@2d9ac65f4572:surf-1.0.6-gcc6$ apt-get update && apt-get install apt-file
(sage-buildsh) root@2d9ac65f4572:surf-1.0.6-gcc6$ apt-file update
(sage-buildsh) root@2d9ac65f4572:surf-1.0.6-gcc6$ apt-file search "/usr/lib/libfl.a"
flex-old: /usr/lib/libfl.a
freebsd-buildutils: /usr/lib/libfl.a
(sage-buildsh) root@2d9ac65f4572:surf-1.0.6-gcc6$ apt-get install flex-old
(sage-buildsh) root@2d9ac65f4572:surf-1.0.6-gcc6$ ./spkg-install
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
...
/usr/bin/install -c surf /sage/local/bin/surf
/usr/bin/install -c -m 644 ./surf.1 /sage/local/share/man/man1/surf.1
...
make[1]: Leaving directory '/sage/local/var/tmp/sage/build/surf-1.0.6-gcc6/src'
(sage-buildsh) root@2d9ac65f4572:surf-1.0.6-gcc6$ exit
root@2d9ac65f4572:/sage# exit
[mkoeppe@sage sage]$
A standard case of bitrot.
Automatic Docker-based build testing using tox#
tox is a Python package that is widely used for automating tests of Python projects.
Install tox
for use with your system Python, for example using:
[mkoeppe@sage sage]$ pip install --user tox
A tox “environment” is identified by a symbolic name composed of
several Tox “factors”,
which are defined in the file $SAGE_ROOT/tox.ini
.
The technology factor describes how the environment is run:
docker
builds a Docker image as described above.local
runs testing on the host OS instead. We explain this technology in a later section.
The next two factors determine the host system configuration: The system factor describes a base operating system image.

The packages factor describes a list of system packages to be installed on the system before building Sage:
minimal
installs the system packages known to Sage to provide minimal prerequisites for bootstrapping and building the Sage distribution. This corresponds to the packages_bootstrap
and_prereq
.standard
additionally installs all known system packages that are equivalent to standard packages of the Sage distribution, for which the mechanismspkg-configure.m4
is implemented. This corresponds to the packages listed by:[mkoeppe@sage sage]$ sage --package list --has-file=spkg-configure.m4 :standard:
maximal
does the same for all standard and optional packages. This corresponds to the packages listed by:[mkoeppe@sage sage]$ sage --package list :standard: :optional:
The factors are connected by a hyphen to name a system configuration,
such as debian-buster-standard
and centos-7-i386-minimal
.
Finally, the configuration factor (which is allowed to be empty)
controls how the configure
script is run.
The factors are connected by a hyphen to name a tox environment. (The order of the factors does not matter; however, for consistency and because the ordered name is used for caching purposes, we recommend to use the factors in the listed order.)
To run an environment:
[mkoeppe@sage sage]$ tox -e docker-slackware-14.2-minimal
[mkoeppe@sage sage]$ tox -e docker-ubuntu-bionic-standard
Arbitrary extra arguments to docker build
can be supplied through
the environment variable EXTRA_DOCKER_BUILD_ARGS
. For example,
for a non-silent build (make V=1
), use:
[mkoeppe@sage sage]$ EXTRA_DOCKER_BUILD_ARGS="--build-arg USE_MAKEFLAGS=\"V=1\"" \
tox -e docker-ubuntu-bionic-standard
By default, tox uses TARGETS_PRE=all-sage-local
and
TARGETS=build
, leading to a complete build of Sage without the
documentation. If you pass positional arguments to tox (separated
from tox options by --
), then both TARGETS_PRE
and TARGETS
are set to these arguments. In this way, you can build some specific
packages instead of all of Sage, for example:
[mkoeppe@sage sage]$ tox -e docker-centos-8-standard -- ratpoints
If the build succeeds, this will create a new image named
sage-centos-8-standard-with-targets:9.1.beta9-431-gca4b5b2f33-dirty
,
where
the image name is derived from the tox environment name and the suffix
with-targets
expresses that themake
targets given inTARGETS
have been built;the tag name describes the git revision of the source tree as per
git describe --dirty
.
You can ask for tox to create named intermediate images as well. For
example, to create the images corresponding to the state of the OS
after installing all system packages (with-system-packages
) and
the one just after running the configure
script (configured
):
[mkoeppe@sage sage]$ DOCKER_TARGETS="with-system-packages configured with-targets" \
tox -e docker-centos-8-standard -- ratpoints
...
Sending build context to Docker daemon ...
Step 1/109 : ARG BASE_IMAGE=fedora:latest
Step 2/109 : FROM ${BASE_IMAGE} as with-system-packages
...
Step 109/109 : RUN yum install -y zlib-devel || echo "(ignoring error)"
...
Successfully built 4bb14c3d5646
Successfully tagged sage-centos-8-standard-with-system-packages:9.1.beta9-435-g861ba33bbc-dirty
Sending build context to Docker daemon ...
...
Successfully tagged sage-centos-8-standard-configured:9.1.beta9-435-g861ba33bbc-dirty
...
Sending build context to Docker daemon ...
...
Successfully tagged sage-centos-8-standard-with-targets:9.1.beta9-435-g861ba33bbc-dirty
Let’s verify that the images are available:
(base) egret:~/s/sage/sage-rebasing/worktree-algebraic-2018-spring (mkoeppe *$%>)$ docker images | head
REPOSITORY TAG IMAGE ID
sage-centos-8-standard-with-targets 9.1.beta9-435-g861ba33bbc-dirty 7ecfa86fceab
sage-centos-8-standard-configured 9.1.beta9-435-g861ba33bbc-dirty 4314929e2b4c
sage-centos-8-standard-with-system-packages 9.1.beta9-435-g861ba33bbc-dirty 4bb14c3d5646
...
Automatic build testing on the host OS using tox -e local-direct#
The local
technology runs testing on the host OS instead.
In contrast to the docker
technology, it does not make a copy of
the source tree. It is most straightforward to run it from a
separate, distclean git worktree.
Let us try a first variant of the local
technology, the tox
environment called local-direct
. Because all builds with tox
begin by bootstrapping the source tree, you will need autotools and
other prerequisites installed in your system. See
build/pkgs/_bootstrap/distros/*.txt
for a list of system packages that
provide these prerequisites.
We start by creating a fresh (distclean) git worktree:
[mkoeppe@sage sage] git worktree add worktree-local
[mkoeppe@sage sage] cd worktree-local
[mkoeppe@sage worktree-local] ls
COPYING.txt ... Makefile ... configure.ac ... src tox.ini
Again we build only a small package. Build targets can be passed as
positional arguments (separated from tox options by --
):
[mkoeppe@sage worktree-local] tox -e local-direct -- ratpoints
local-direct create: /Users/mkoeppe/.../worktree-local/.tox/local-direct
local-direct run-test-pre: PYTHONHASHSEED='2211987514'
...
src/doc/bootstrap:48: installing src/doc/en/installation/debian.txt...
bootstrap:69: installing 'config/config.rpath'
configure.ac:328: installing 'config/compile'
configure.ac:113: installing 'config/config.guess'
...
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
...
sage-logger -p 'sage-spkg -y -o ratpoints-2.1.3.p5' '.../worktree-local/logs/pkgs/ratpoints-2.1.3.p5.log'
[ratpoints-2.1.3.p5] installing. Log file: .../worktree-local/logs/pkgs/ratpoints-2.1.3.p5.log
[ratpoints-2.1.3.p5] successfully installed.
...
local-direct: commands succeeded
congratulations :)
Let’s investigate what happened here:
[mkoeppe@sage worktree-local]$ ls -la
total 2576
drwxr-xr-x 35 mkoeppe staff 1120 Mar 26 22:20 .
drwxr-xr-x 63 mkoeppe staff 2016 Mar 27 09:35 ..
...
lrwxr-xr-x 1 mkoeppe staff 10 Mar 26 20:34 .dockerignore -> .gitignore
-rw-r--r-- 1 mkoeppe staff 74 Mar 26 20:34 .git
...
-rw-r--r-- 1 mkoeppe staff 1212 Mar 26 20:41 .gitignore
...
drwxr-xr-x 7 mkoeppe staff 224 Mar 26 22:11 .tox
...
-rw-r--r-- 1 mkoeppe staff 7542 Mar 26 20:41 Makefile
...
lrwxr-xr-x 1 mkoeppe staff 114 Mar 26 20:45 config.log -> .tox/local-direct/log/config.log
-rwxr-xr-x 1 mkoeppe staff 90411 Mar 26 20:46 config.status
-rwxr-xr-x 1 mkoeppe staff 887180 Mar 26 20:45 configure
-rw-r--r-- 1 mkoeppe staff 17070 Mar 26 20:41 configure.ac
...
lrwxr-xr-x 1 mkoeppe staff 103 Mar 26 20:45 logs -> .tox/local-direct/log
drwxr-xr-x 24 mkoeppe staff 768 Mar 26 20:45 m4
lrwxr-xr-x 1 mkoeppe staff 105 Mar 26 20:45 prefix -> .tox/local-direct/local
-rwxr-xr-x 1 mkoeppe staff 4868 Mar 26 20:34 sage
drwxr-xr-x 16 mkoeppe staff 512 Mar 26 20:46 src
-rw-r--r-- 1 mkoeppe staff 13478 Mar 26 20:41 tox.ini
drwxr-xr-x 4 mkoeppe staff 128 Mar 26 20:46 upstream
There is no local
subdirectory. This is part of a strategy to
keep the source tree clean to the extent possible. In particular:
tox
configured the build to use a separate$SAGE_LOCAL
hierarchy in a directory under the tox environment directory.tox/local-direct
. It created a symbolic linkprefix
that points there, for convenience:[mkoeppe@sage worktree-local]$ ls -l prefix/lib/*rat* -rw-r--r-- 1 mkoeppe staff 165968 Mar 26 20:46 prefix/lib/libratpoints.a
Likewise, it created a separate
logs
directory, again under the tox environment directory, and a symbolic link.
This makes it possible for advanced users to test several local
tox environments (such as local-direct
) out of one worktree. However, because a
build still writes configuration scripts and build artefacts (such as
config.status
) into the worktree, only one local
build can run
at a time in a given worktree.
The tox environment directory will be reused for the next tox
run,
which will therefore do an incremental build. To start a fresh build,
you can use the -r
option.
Automatic build testing on the host OS with best-effort isolation using tox -e local#
tox -e local
(without -direct
) attempts a best-effort
isolation from the user’s environment as follows:
All environment variables are set to standard values; with the exception of
MAKE
andEXTRA_CONFIGURE_ARGS
. In particular,PATH
is set to just/usr/bin:/bin:/usr/sbin:/sbin
; it does not include/usr/local/bin
.
Note, however, that various packages have build scripts that use
/usr/local
or other popular file system locations such as
/opt/sfw/
. Therefore, the isolation is not complete. Using
/usr/local
is considered standard behavior. On the other hand, we
consider a package build script that inspects other file system
locations to be a bug of the Sage distribution, which should be
reported and fixed on a ticket.
Automatic build testing on macOS with a best-effort isolated installation of Homebrew#
XCode on macOS does not provide the prerequisites for bootstrapping the Sage distribution. A good way to install them is using the Homebrew package manager.
In fact, Sage provides a tox environment that automatically installs an isolated copy of Homebrew with all prerequisites for bootstrapping:
[mkoeppe@sage worktree-local]$ tox -e local-homebrew-macos-minimal -- lrslib
local-homebrew-macos-minimal create: .../worktree-local/.tox/local-homebrew-macos-minimal
local-homebrew-macos-minimal run-test-pre: PYTHONHASHSEED='4246149402'
...
Initialized empty Git repository in .../worktree-local/.tox/local-homebrew-macos-minimal/homebrew/.git/
...
Tapped 2 commands and 4942 formulae (5,205 files, 310.7MB).
==> Downloading https://ftp.gnu.org/gnu/gettext/gettext-0.20.1.tar.xz
...
==> Pouring autoconf-2.69.catalina.bottle.4.tar.gz
...
==> Pouring pkg-config-0.29.2.catalina.bottle.1.tar.gz
.../worktree-local/.tox/local-homebrew-macos-minimal/homebrew/Cellar/pkg-config/0.29.2: 11 files, 623.4KB
==> Caveats
==> gettext
gettext is keg-only, which means it was not symlinked into .../worktree-local/.tox/local-homebrew-macos-minimal/homebrew,
because macOS provides the BSD gettext library & some software gets confused if both are in the library path.
If you need to have gettext first in your PATH run:
echo 'export PATH=".../worktree-local/.tox/local-homebrew-macos-minimal/homebrew/opt/gettext/bin:$PATH"' >> ~/.bash_profile
For compilers to find gettext you may need to set:
export LDFLAGS="-L.../worktree-local/.tox/local-homebrew-macos-minimal/homebrew/opt/gettext/lib"
export CPPFLAGS="-I.../worktree-local/.tox/local-homebrew-macos-minimal/homebrew/opt/gettext/include"
...
local-homebrew-macos-minimal run-test: commands[0] | bash -c 'export PATH=.../worktree-local/.tox/local-homebrew-macos-minimal/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin && . .homebrew-build-env && ./bootstrap && ./configure --prefix=.../worktree-local/.tox/local-homebrew-macos-minimal/local && make -k V=0 ... lrslib'
...
bootstrap:69: installing 'config/config.rpath'
...
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
...
configure: notice: the following SPKGs did not find equivalent system packages: arb cbc cliquer ... tachyon xz zeromq
checking for the package system in use... homebrew
configure: hint: installing the following system packages is recommended and may avoid building some of the above SPKGs from source:
configure: $ brew install cmake gcc gsl mpfi ninja openblas gpatch r readline xz zeromq
...
sage-logger -p 'sage-spkg -y -o lrslib-062+autotools-2017-03-03.p1' '.../worktree-local/logs/pkgs/lrslib-062+autotools-2017-03-03.p1.log'
[lrslib-062+autotools-2017-03-03.p1] installing. Log file: .../worktree-local/logs/pkgs/lrslib-062+autotools-2017-03-03.p1.log
[lrslib-062+autotools-2017-03-03.p1] successfully installed.
...
local-homebrew-macos-minimal: commands succeeded
congratulations :)
The tox environment uses the subdirectory homebrew
of the
environment directory .tox/local-homebrew-macos-minimal
as the
Homebrew prefix. This installation does not interact in any way with
a Homebrew installation in /usr/local
that you may have.
The test script sets the PATH
to the bin
directory of the
Homebrew prefix, followed by /usr/bin:/bin:/usr/sbin:/sbin
. It
then uses the script $SAGE_ROOT/.homebrew-build-env
to set
environment variables so that Sage’s build scripts will find
“keg-only” packages such as gettext
.
The local-homebrew-macos-minimal
environment does not install
Homebrew’s python3
package. It uses XCode’s /usr/bin/python3
as system python. However, because various packages are missing
that Sage considers as dependencies, Sage builds its own copy of
these packages and of python3
.
The local-homebrew-macos-standard
environment additionally
installs (in its separate isolated copy of Homebrew) all Homebrew
packages known to Sage for which the spkg-configure.m4
mechanism
is implemented; this is similar to the docker-standard
tox
environments described earlier. In particular it installs and uses
Homebrew’s python3
package.
By using configuration factors, more variants can be tested.
The local-homebrew-macos-standard-python3_xcode
environment
installs the same packages, but uses XCode’s /usr/bin/python3
.
The local-homebrew-macos-standard-python3_pythonorg
expects an
installation of Python 3.10 in
/Library/Frameworks/Python.framework
; this is where the binary
packages provided by python.org install themselves.
Automatic build testing with a best-effort isolated installation of Conda#
Sage provides environments local-conda-forge-standard
and
local-conda-forge-minimal
that create isolated installations of
Miniconda in the subdirectory conda
of the environment directory.
They do not interact in any way with other installations of Anaconda
or Miniconda that you may have on your system.
The environments use the conda-forge channel and use the python
package and the compilers from this channel.
Options for build testing with the local technology#
The environments using the local
technology can be customized
by setting environment variables.
If
SKIP_SYSTEM_PKG_INSTALL
is set to1
(oryes
), then all steps of installing system packages are skipped in this run. When reusing a previously created tox environment, this option can save time and also give developers more control for experiments with system packages.If
SKIP_BOOTSTRAP
is set to1
(oryes
), then the bootstrapping phase is skipped. When reusing a previously created tox environment, this option can save time.If
SKIP_CONFIGURE
is set to1
(oryes
), then theconfigure
script is not run explicitly. When reusing a previously created tox environment, this option can save time. (TheMakefile
may still rerun configuration usingconfig.status --recheck
.)
The local
technology also defines a special target bash
:
Instead of building anything with make
, it just starts an
interactive shell. For example, in combination with the above
options:
[mkoeppe@sage worktree-local]$ SKIP_SYSTEM_PKG_INSTALL=yes SKIP_BOOTSTRAP=1 SKIP_CONFIGURE=1 tox -e local-homebrew-macos-minimal -- bash
Automatic testing on multiple platforms on GitHub Actions#
The Sage source tree includes a default configuration for GitHub Actions that runs our portability tests on a multitude of platforms on every push of a tag (but not of a branch) to a repository for which GitHub Actions are enabled.
In particular, it automatically runs on our main repository sagemath/sage on every release tag.
This is defined in the files
$SAGE_ROOT/.github/workflows/ci-linux.yml (which calls $SAGE_ROOT/.github/workflows/docker.yml),
$SAGE_ROOT/.github/workflows/ci-cygwin-standard.yml (which calls $SAGE_ROOT/.github/workflows/cygwin.yml).
GitHub Actions runs these build jobs on 2-core machines with 7 GB of
RAM memory and 14 GB of SSD disk space, cf.
here,
and has a time limit of 6h per job. This could be just barely enough for a
typical minimal
build followed by make ptest
to succeed; for
added robustness, we split it into two jobs. Our workflow stores
Docker images corresponding to various build phases within these two
jobs on GitHub Packages (ghcr.io).
Build logs can be inspected during the run and become available as “artifacts” when all jobs of the workflow have finished. Each job generates one tarball. “Annotations” highlight certain top-level errors or warnings issued during the build.
In addition to these automatic runs in our main repository, all Sage developers can run the same tests on GitHub Actions in their personal forks of the Sage repository. To prepare this, enable GitHub Actions in your fork of the Sage repository.
As usual we assume that origin
is the name of the remote
corresponding to your GitHub fork of the Sage repository:
$ git remote -v | grep origin
origin https://github.com/mkoeppe/sage.git (fetch)
origin https://github.com/mkoeppe/sage.git (push)
Then the following procedure triggers a run of tests with the default set of system configurations.
Push your branch to
origin
(your fork).Go to the Actions tab of your fork and select the workflow you would like to run, for example “CI Linux”.
Click on “Run workflow” above the list of workflow runs and select your branch as the branch on which the workflow will run.
For more information, see the GitHub documentation.
Alternatively, you can trigger a run of tests by creating and pushing a custom tag as follows.
Create a (“lightweight”, not “annotated”) tag with an arbitrary name, say
ci
(for “Continuous Integration”):git tag -f ci
Then push the tag to your GitHub repository:
git push -f origin ci
(In both commands, the “force” option (-f
) allows overwriting a
previous tag of that name.)
Either way, when the workflow has been triggered, you can inspect it by using the workflow status page in the “Actions” tab of your repository.
Here is how to read it. Each of the items in the left pane represents
a full build of Sage on a particular system configuration. A test
item in the left pane is marked with a green checkmark in the left
pane if make build doc-html
finished without error. (It also runs
package testsuites and the Sage doctests but failures in these are not
reflected in the left pane; see below.)
The right pane (“Artifacts”) offers archives of the logs for download.
Scrolling down in the right pane shows “Annotations”:
Red “check failure” annotations appear for each log file that contains a build error. For example, you might see:
docker (fedora-28, standard) artifacts/logs-commit-8ca1c2df8f1fb4c6d54b44b34b4d8320ebecb164-tox-docker-fedora-28-standard/logs/pkgs/sagetex-3.4.log#L1 ==== ERROR IN LOG FILE artifacts/logs-commit-8ca1c2df8f1fb4c6d54b44b34b4d8320ebecb164-tox-docker-fedora-28-standard/logs/pkgs/sagetex-3.4.log ====
Yellow “check warning” annotations. There are 2 types of these:
Package testsuite or Sage doctest failures, like the following:
docker (fedora-30, standard) artifacts/logs-commit-8ca1c2df8f1fb4c6d54b44b34b4d8320ebecb164-tox-docker-fedora-30-standard/logs/ptest.log#L1 ==== TESTSUITE FAILURE IN LOG FILE artifacts/logs-commit-8ca1c2df8f1fb4c6d54b44b34b4d8320ebecb164-tox-docker-fedora-30-standard/logs/ptest.log ====
Notices from ./configure about not finding equivalent system packages, like the following:
docker (fedora-31, standard) artifacts/logs-commit-8ca1c2df8f1fb4c6d54b44b34b4d8320ebecb164-tox-docker-fedora-31-standard/config.log#L1 configure: notice: the following SPKGs did not find equivalent system packages: arb cbc cddlib cmake eclib ecm fflas_ffpack flint fplll givaro gp
Clicking on the annotations does not take you to a very useful place. To view details, click on one of the items in the pane. This changes the right pane to a log viewer.
The docker
workflows automatically push images to
ghcr.io
. You find them in the Packages tab of your
GitHub repository.
In order to pull them for use on your computer, you need to first
generate a Personal Access Token providing the read:packages
scope
as follows. Visit https://github.com/settings/tokens/new (this may
prompt you for your GitHub password). As “Note”, type “Access
ghcr.io”; then in “Select scopes”, select the checkbox
for read:packages
. Finally, push the “Generate token” button at
the bottom. This will lead to a page showing your token, such as
de1ec7ab1ec0ffee5ca1dedbaff1ed0ddba11
. Copy this token and paste
it to the command line:
$ echo de1ec7ab1ec0ffee5ca1dedbaff1ed0ddba11 | docker login ghcr.io --username YOUR-GITHUB-USERNAME
where you replace the token by your token, of course, and
YOUR-GITHUB-USERNAME
by your GitHub username.
Now you can pull the image and run it:
$ docker pull ghcr.io/YOUR-GITHUB-USERNAME/sage/sage-fedora-31-standard-configured:f4bd671
$ docker run -it ghcr.io/YOUR-GITHUB-USERNAME/sage/sage-fedora-31-standard-configured:f4bd671 bash
Using our pre-built Docker images published on ghcr.io#
Our portability CI on GitHub Actions builds Docker images for all tested Linux platforms (and system package configurations) and makes them available on GitHub Packages (ghcr.io).
This makes it easy for developers to debug problems that showed up in the build logs for a given platform.
The image version corresponding to the latest development release
receives the additional Docker tag dev
, see for example the Docker
image for the platform ubuntu-focal-standard. Thus,
for example, the following command will work:
$ docker run -it ghcr.io/sagemath/sage/sage-ubuntu-focal-standard-with-targets-optional:dev bash
Unable to find image 'ghcr.io/sagemath/sage/sage-ubuntu-focal-standard-with-targets-optional:dev' locally
dev: Pulling from sagemath/sage/sage-ubuntu-focal-standard-with-targets-optional
d5fd17ec1767: Already exists
67586203f0c7: Pull complete
b63c529f4777: Pull complete
...
159775d1a3d2: Pull complete
Digest: sha256:e6ba5e12f59c6c4668692ef4cfe4ae5f242556482664fb347bf260f32bf8e698
Status: Downloaded newer image for ghcr.io/sagemath/sage/sage-ubuntu-focal-standard-with-targets-optional:dev
root@8055a7ba0607:/sage# ./sage
┌────────────────────────────────────────────────────────────────────┐
│ SageMath version 9.6, Release Date: 2022-05-15 │
│ Using Python 3.8.10. Type "help()" for help. │
└────────────────────────────────────────────────────────────────────┘
sage:
Images whose names end with the suffix -with-targets-optional
are
the results of full builds and a run of make ptest
. They also
contain a copy of the source tree and the full logs of the build and
test.
Also smaller images corresponding to earlier build stages are available:
-with-system-packages
provides a system installation with system packages installed, no source tree,
-configured
contains a partial source tree (SAGE_ROOT
) and has completed the bootstrapping phase and the run of theconfigure
script,
-with-targets-pre
contains the full source tree and a full installation of all non-Python packages (SAGE_LOCAL
),
-with-targets
contains the full source tree and a full installation of Sage, including the HTML documentation, butmake ptest
has not been run yet.
Using our pre-built Docker images for development in VS Code#
VS Code is very convenient for developing with Docker containers thanks to the Visual Studio Code Remote - Containers extension.
If the extension is not already installed, then in VS Code, click the “Extension” icon on the left (or press Ctrl + Shift + X; on macOS, Command + Shift + X) to open a list of extensions. Search for “Remote - Containers” and install it.
The extension needs a devcontainer.json
configuration file to work. Sage
provides sample devcontainer.json
configuration files
$SAGE_ROOT/.devcontainer/*/devcontainer.json for this
purpose.
If you open the sage folder in VS Code, it may prompt you whether you would like to open the current directory in the dev container (yes). If it does not, use the command palette (Ctrl + Shift + P), enter the command “Remote-Containers: Reopen Folder in Container” , and hit Enter.
If the above code .
command does not work, start VS Code as a regular
application, then in the command palette of VS Code, enter “Remote-Containers:
Open Folder in Container”, and hit Enter, and choose the directory
$SAGE_ROOT
of your local Sage repository.
VS Code then prompts you to choose a dev container configuration.
For example, choose “Ubuntu jammy” .devcontainer/portability-ubuntu-jammy-standard/devcontainer.json,
which uses the Docker image based on ubuntu-jammy-standard
, the most recent
development version of Sage (dev
tag), and a full installation of
the Sage distribution (with-targets
). Other dev container configurations
are described below.
Once VS Code starts configuring the dev container, by clicking on “show log”, you can see what it does:
It pulls the prebuilt image from ghcr.io (via $SAGE_ROOT/.devcontainer/portability-Dockerfile); note that these are multi-gigabyte images, so it may take a while.
As part of the “onCreateCommand”, it installs additional system packages to support VS Code and for development.
Then, as part of the “updateContentCommand”, it bootstraps and configures the source tree and starts to build Sage from source, reusing the installation (
SAGE_LOCAL
,SAGE_VENV
) from the prebuilt image.
After VS Code finished configuring the dev container (when the message “Done.
Press any key to close the terminal.” appears in the terminal named
“Configuring”), your local Sage repository at $SAGE_ROOT
is available in
the container at the directory /workspaces/<repository name>
. To use Sage
in a terminal, open a new terminal in VS Code, type ./sage
and hit
Enter.
Note
Your Sage at $SAGE_ROOT
was configured and rebuilt inside the dev
container. In particular, $SAGE_ROOT/venv
, $SAGE_ROOT/prefix
, and
(possibly) $SAGE_ROOT/logs
will be symbolic links that work inside the dev
container, but not in your local file system; and also the script
$SAGE_ROOT/sage
will not work. Hence after working with the dev container,
you will want to remove logs
if it is a symbolic link, and rerun the
configure
script.
You can edit a copy of the configuration file to change to a different platform, another version, or build stage. After editing the configuration file, run “Remote-Containers: Rebuild Container” from the command palette. See the VS Code devcontainer.json reference and the GitHub introduction to dev containers for more information.
In addition to the
$SAGE_ROOT/.devcontainer/portability-.../devcontainer.json
files, Sage also
provides several other sample devcontainer.json
configuration files in the
directory $SAGE_ROOT/.devcontainer
.
Files named $SAGE_ROOT/.devcontainer/develop-.../devcontainer.json
configure
containers from a public Docker image that provides SageMath and then updates the
installation of SageMath in this container by building from the current source tree.
develop-docker-computop/devcontainer.json configures a container with the Docker image from the 3-manifolds project, providing SnapPy, Regina, PHCPack, etc.
After VS Code finished configuring the
dev container, to use Sage in a terminal, open a new terminal in VS Code, type ./sage
and hit
Enter.
Files named $SAGE_ROOT/.devcontainer/downstream-.../devcontainer.json
configure
containers with an installation of downstream packages providing SageMath from a
package manager (downstream-archlinux-...
, downstream-conda-forge
;
see also the _sagemath dummy package),
or from a public Docker image that provides SageMath (docker-cocalc
, docker-computop
).
These devcontainer.json
configuration files are useful for testing
user scripts on these deployments of SageMath. You may also find it
useful to copy these configurations into your own projects (they should
work without change) or to adapt them to your needs.
downstream-archlinux-latest/devcontainer.json configures a container with an installation of Arch Linux and its SageMath package. (The suffix
latest
indicates the most recent version of Arch Linux as available on Docker Hub.)downstream-conda-forge-latest/devcontainer.json configures a container with an installation of conda-forge and its SageMath package.
downstream-docker-cocalc/devcontainer.json configures a container with the CoCalc Docker image.
downstream-docker-computop/devcontainer.json configures a container with the Docker image from the 3-manifolds project, providing SnapPy, Regina, PHCPack, etc.
After VS Code finished configuring the
dev container, to use Sage in a terminal, open a new terminal in VS Code, type sage
and hit
Enter. (Do not use ./sage
; this will not work because the source
tree is not configured.)


{{ item.date }}
{{ content }}
This email was sent to you because you selected to receive emails from us. If you wish to unsubscribe, please click
here


Highly motivated and passionate Agile developer with rich experience in a wide range of web technologies and languages.
I have a passion for web development, using the following technologies
Get in touch with me via: Github or LinkedIn


Welcome to a world of dogs.
Learn from examples.
Read about cars.
Welcome to a world of dogs.
Learn from examples.
Read about cars.
The ng-app directive defines the AngularJS application. The ng-controller directive defines the application controller. The ng-model directive binds two input elements to the user object in the model. The formCtrl controller sets initial values to the master object, and defines the reset() method. The reset() method sets the user object equal to the master object. The ng-click directive invokes the reset() method, only if the button is clicked.


Service Testing Interface
Mesos Playground
Use this page to make calls back into the cluster to test different parts of the system.
UUID->GENERATE
Generate
Result:
0
MATH->SUM
Left Addend:
Right Addend:
SUM
Result:
0
MATH->PRODUCT
Left Factor:
Right Factor:
PRODUCT
Result:
0


Quest for Camelot (G) **
With the visually spectacular and entertaining Anastasia, Fox declared itself a worthy contender to Disney's feature animation throne. Now comes the Warner Bros. stab at animation riches, Quest for Camelot, and if this shoddy enterprise is what it considers topline animated entertainment, the studio is a mere pretender to the Mouse's throne.
As is the case with most underwhelming live action films, one of the roots of Quest's mediocrity is the script, written by Kirk DeMicco, William Schifrin, Jacqueline Feather, and David Seidler from Vera Chapman's novel The King's Damosel. The story is just about nonexistent, boiling down to an extended, uninteresting search for a sword. Dastardly former knight Ruber (voice of Gary Oldman) steals King Arthur's (Pierce Brosnan) magic sword Excalibur, only to lose it in the forest. Ruber and his crew of baddies search for it, as does the courageous daughter of deceased knight Lionel (Gabriel Byrne), Kayley (Jessalyn Gilsig), who is joined in her quest by the blind loner Garrett (Cary Elwes) and the two-headed (conjoined?) dragon(s) Devon (Eric Idle) and Cornwall (Don Rickles).
Anastasia set the bar for non-Disney animation high with its opening glimpse of a stunningly realistic, computer-animated music box. Quest counters with a shot has become cliche in live action features: the trusty camera-travelling-over-water shot. But this is a minor quibble in a film teeming with visual problems. The art is strictly Saturday morning-level, a point which is underscored further a scene where Kayley and Garrett face a computer-generated giant ogre; unlike in Anastasia or any given Disney effort, the CGI and the traditional cel animation do not mesh convincingly at all. The ogre, as impressive as it looks, looks completely out of place, appearing to have wandered in from a better, bigger-budgeted film. The worst visual sin committed by director Frederik DuChau and the animation crew is the sloppy lipsynching, especially during the musical numbers, where the voices often do not match the characters' mouth movements.
Even more distracting is the noticeable difference between the characters' singing and speaking voices. In Disney features (or, for that matter, Anastasia), the singing and speaking voices can plausibly originate from the same set of vocal cords. Although there are a couple of exceptions--Gilsig and Andrea Corr sound remarkably similar as Kayley; and the Jane Seymour/Celine Dion teamup for Kayley's mother, Lady Juliana, works surprisingly well--too often the voices are wildly dissimilar. When Garrett breaks into song, Elwes's soft, Brit-accented tones suddenly change into those of raspy Yank country-western singer Bryan White. The biggest stretch of all is the tandem for King Arthur: current 007 Brosnan and... former Journey frontman Steve Perry?! The stretch casting would be forgivable if David Foster and Carole Bayer Sager's songs were the least bit memorable. Suffice it to say, they aren't.
Quest for Camelot follows the tried-and-true Disney formula fairly closely--"I Want" song, villainous scheme number, love duet, final confrontation--but DuChau fails to realize that the key to Disney's success in animation is not necessarily the formula but a generous helping of imagination and magic to go with it. While their Anastasia was not a complete triumph, directors Don Bluth and Gary Goldman were able to create some superb, haunting moments that rank with, if not surpass, some of Disney's. If Quest is any indication, Warner Bros. Feature Animation, which enjoyed a successful launch with 1996's Space Jam, is severely out of its depth.
Michael Dequina Chat Forum Host, The Official Michael Jordan Web Site http://jordan.sportsline.com
<EMAIL_ADDRESS><EMAIL_ADDRESS>|<EMAIL_ADDRESS>>My personal WWW sites< Mr. Brown's Movie Site: http://welcome.to/mrbrown Michael Jordan Beyond the Court: http://fly.to/michaeljordan A Michael Jordan Fan's Heartbreak: http://fly.to/mj23 Personal Page: http://welcome.to/w3md >Other WWW sites I work on< CompuServe Hollywood Hotline: http://www.HollywoodHotline.com Albany Online: http://www.AlbanyOnline.com Eyepiece Network: http://www.eyepiece.com
"I didn't know what to expect. It's like something you chase for so long, but then you don't know how to react when you get it. I still don't know how to react." --Michael Jordan, on winning his first NBA championship in 1991 ...or, my thoughts after meeting him on November 21, 1997
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


The founding belief of the MIT Vaccine for All initiative (as part of the MIT Program for Trusted Pandemic Technologies Program) is that when it comes to engaging citizens in a quest for the common good, especially public health, trust at all levels and among all participants is mandatory for success. The program builds on privacy preserving systems for smartphone data, analytics and machine learning.
We help communities overcome challenges and risks during vaccine distribution through digital solutions. It can be achieved through participatory real time epidemiology and believe that user-centric crowdsourced solutions can address the main 3 unsolved problems:
- User challenges: faith/trust in vaccine, equitable/fair/who gets first, second booster and reminder
- Unknown efficacy: unknown duration of immunity, glitches in cold-storage supply chain
- Unknown safety: side-effects/adverse reactions
This participatory crowdsourced data may allow intelligent solutions for public health (dashboards for vaccine deployment progress by geography and population groups, adaptive planning) and businesses (pharma: vaccine development, employers: back to work solutions, service industry: customer health verification).


Snookes1516.github.io
73 4th Grade Writing Prompts ⋆ Journal Buddies. A word cloud created from all the questions compiled below. Updated, June 20, 2017 Looking for more lists of student questions? Try these: 650 Prompts. MLA Formatting and Style Guide // Purdue Writing.
Play as development: Vygotsky and teaching English. Create Your Own Anti-Anxiety Kit for Children. An interesting area. I’ve seen quite a few ‘adult play’ centres open in France which are often part of creches. They offer ‘evenings for adults to play games.
Creative Writing Prompt: Spiced Architecture Writer's Digest. The Purdue University Online Writing Lab serves writers from around the world and the Purdue University Writing Lab helps writers on Purdue's campus. Daily creative writing prompts for adults. The Cultivate Team Just Wants to Dance from Lara Casey on Vimeo. Here we come 2018! You are doing the hard work, making a mess, and making meaningful progress. WritingFix: Quality Teaching Resources for K-12 strategically de signed lessons to help "fix" teachers who don't enjoy teaching writing. How this website Easy Doodle Art Prompts for Kids: 21 Printable Daily.
Writing Prompt: For World Storytelling Day, share the best story you've ever heard or told by word of mouth, or have a fictional character recount their.
Create a Calm Down Kit for Your Child to help combat anxiety - includes free printable relaxation prompt cards. 1, 000 Awesome Writing Prompts Ryan Andrew Kinder on Amazon.com. FREE shipping on qualifying offers. Have you ever wanted to write a story, but you didn't This week's writing prompt concerns a mysterious misadventure that begins on a familiar path and ends at the door of a structure made of gingerbread.
163 Questions to Write or Talk About - The New York Times.
1, 000 Awesome Writing Prompts - Kindle edition
2018 GOAL SETTING, Part 5: Make it Happen - Lara Casey. The Muse Writers Center offers a variety of creative and creative writing classes in Poetry, Fiction, Science Fiction, Fantasy, and Horror, Children's Literature. 1, 000 Awesome Writing Prompts: Ryan Andrew Kinder. Creative Writing Classes and Seminars at The Muse Writers. Benefits of Writing and Journaling— Journaling has many benefits for both children and adults, and the simple act of writing is a powerful way to express feelings. Of all the resources we publish on The Learning Network, perhaps it’s our vast collection of writing prompts that is our most widely used resource.
Spoken Stories Weekly Writing Prompt – Writer's Digest. Creative Writing Prompts for Kids Super Easy Storytelling. WritingFix: prompts, lessons, and resources for writing. Use doodles and drawings to inspire reflection and writing as an introduction to journal writing and sketchbooking 1, 000 Awesome Writing Prompts - Kindle edition by Ryan Andrew Kinder. Download it once and read it on your Kindle device, PC, phones or tablets. Use features. Original WritingFix Prompt Generator - Corbett Harrison. Creative writing prompts for kids in 3rd, 4th, 5th, 6th grades. Mix and Match funny creative writing prompts for kids to create countless story ideas. Printable. 401 Prompts for Argumentative Writing - The New York Times. For my Amazing Middle School Students: Handouts and resources ; Lessons/Resources for Visiting Teachers Sacred Writing Time-- our daily routine.


Add here all the API hostnames used by KrakenD to retrieve the data. If you don't use service discovery to resolve hostnames choose None from the following discovery providers list:


No Errors
Server:
Port:
Log In (Single Sign On)
Username:
Password:
Save Password?
Station:
Log In
Dial
Conference Checked Interactions
Interaction ID
Remote Name
Remote Number
State
Conference ID
Show messages in page


We are a boutique web service firm focused on user experience, design, development, inbound marketing, measurement, and maintenance.
Monkee-Boy is one of Austin’s leading digital agencies and has been helping organizations of all shapes and sizes, around the world, do one thing for almost 18 years. That one thing is simple...solve the web. We focus on digital strategy, user experience, design, development, inbound marketing, measurement, and ongoing maintenance. Don't forget to checkout our site at monkee-boy.com for more about us and our work.
We’re looking for a UX/UI Designer with a sharp design eye and a passion for learning new things to join the Monkee-Boy team.
A UX/UI designer is responsible for initial concepting and brainstorming, working closely with content strategy to determine features and functionality, wireframing both web and mobile projects, UI design, animation and interaction direction, and handling client maintenance requests. This is a full time position and will be required to work from the Monkee-Boy World Headquarters in beautiful Austin, Texas.
The candidate will be compensated based on work experience, demonstration of success, and other intangibles they bring to the table. They will also be able to participate in all employee incentive programs.
We need a designer who loves the web.
Each of the below will get you a +1 with us.
This application process is not a one way street. It’s important not only for you to be a good fit for us but that we are a good fit for you. We won’t take it personally if you pass on us.
With a name like Monkee-Boy, what else would you expect?


LIFE IS A STORY.
So, enjoy life!
Whatever you do, you hold on to that foolishly hopeful smile.
You can catch me on my blog or read my wiki.


{% extends "base.html" %} {% block title %} Forgotten Password {% endblock %} {% block postContainer %}
If you don't remember your password, enter your mail address below. We will send a link to your e-mail address. You should click it to reset your password.
Don't have an account? Sign up now!


Easy and frictionless
It should be easy for anyone to run a full stack Dart application. So
your goal is to give easy choices that matters first. Still give you
the power and control you need when you application grows. In a
perfect world you should be able just give us code and a budget and
we handle the rest.
Open Source Startup
I have done the secret build up a big project stealth mode startup
and it was a pain. This time I want swing the pendulum the other way
and be as open and transparent as possible. The rule of thumb should
be, the only thing secret are the keys and customer data.
For the community
In the end its all about you guys and girls in the Dart community.
The goal of this enterprise is to help the Dart community not to make
a few of us rich. So we will seek input on almost everything. But we
will not necessarily blindly follow the majority. And if the
community allows it we would like to give hosting to even the ones
with a zero budget to help Dart grow.
Accelerated on Amazon Web Services
Why build everything from scratch when you stand on shoulders of
giants and in host/cloud business there is none bigger. With AWS as
the base we can get to the market quicker and better than doing all
inhouse. It also has the positive effect for you to have access to
the extensive ecosystem that has buildup around AWS. This is where we
will start but where we go be will mostly up to you the community.


‘Beautiful’ mum found dead 17 days after escaping mental health unit
The daughter of a woman who died after escaping from a mental health unit said her family are at ‘rock bottom’ following their loss.
Leah Fletcher, 24, fears her mum Georgina committed suicide after going missing from Lakeside Mental Health centre in Houndslow on October 31st.
She claims her mum, known as Gina to her friends, had gone missing 15-20 times and expressed suicidal thoughts in the run up to being sectioned at the West London practice.
She and her siblings desperately clung on to the hope their mum, 50, would be found alive and spent over two weeks frantically searching for her with the help of the public.
But on Sunday November 17, they received the devastating news that a body had been found in Hounslow Heath.
Leah, who has a five-year-old son, told metro.co.uk: ‘It’s absolutely devastating. How do you tell your kids that nanny has gone to sleep, or that nanny is in heaven?
Advertisement Advertisement
‘She loved her grandkids more than anything. It’s absolutely heart breaking.
‘My mum had an awful upbringing, but she still made sure that her kids had everything we needed. She was such a lovely person. She was beautiful inside and out’.
Adding to the family’s grief, Gina’s death is close to the anniversary of her sister, Leah’s aunty, who died by suicide five years ago.
Leah said a history of mental health runs in the family and feels her mum, a grandmother of two, has been let down by authorities.
She claims her parent, who suffered from schizoaffective disorder, begged to be sectioned for months before she was committed to Lakeside and at the height of her illness even asked police to shoot her.
Leah said: ‘My mum was so clever.  Every time she wanted to go back to college she got unwell.
‘She always wanted to help people.
‘She was brilliant but she was been left behind. I have been feeling suicidal over her death but I have lost trust in mental health services.’
A cross-agency investigation into Ms Fletcher’s death is underway.
The family’s loss is compounded by the struggle to afford a funeral, which cost on average £4,000.
Advertisement Advertisement
They have sent up a GoFundme page to raise some money to give their mum a proper send off, and say any little helps.
Leah said: ‘We have hit rock bottom. We have already lost one relative who took her own life. Now we are left with the pressure of the funeral.
‘We don’t want to ask for much. We are so grateful to everyone who has helped so far.
‘Even if it’s just a donation of £1, it all adds up.
‘The kindness from other people is what is keeping me going right now. It gives me faith in humanity and reminds me there are good people out there.’
You can donate to the Gofundme page here
A spokesperson from the Met Police say enquiries are ongoing into Ms Fletcher’s death.
The statement said: ‘Police were called shortly after 16:00hrs on Sunday, 17 November to reports of a woman found deceased on Hounslow Heath.
‘Officers attended. At this early stage, the death is not being treated as suspicious.
‘Next of kin have been informed.
‘Formal identification awaits and a post-mortem examination will be held in due course.
‘Enquiries continue.’
Lakeside Mental Health Unit is part of the West London NHS Trust.
A spokesperson said: ‘The Trust would like to offer our sympathy to Ms Fletcher’s family. We are taking part in the independent, cross-agency investigation into Ms Fletcher’s death, which is currently underway.’


| Class and Description |
|---|
| AccountManager
Handles all account related methods such as login, account creation, updating account info, and lastly account deletion.
|
| AddCommentDialog.AddCommentDialogListener |
| CareProvider |
| Comment
Represents a comment that the user is having.
|
| CommentList
Contains a List of comments, with methods that modify or return comments
|
| EditCommentDialog.EditCommentDialogListener |
| Patient |
| PatientList |
| PatientSearchInfo |
| Photo
Converts a given bitmap to a string, and then back to a bitmap.
|
| Problem
Represents a problem that the user is having.
|
| ProblemList
Contains a List of Problems, with methods that modify or return problems
|
| Record
Record is used to record the patients' problem
Records can have a title, a description, a date the problem started, a location, and a photo
|
| RecordList |
| User |


{% extends 'url_shortener/base.html' %} {% block title %}Analytics - {{ title }}{% endblock %} {% block analytics_nav %}active{% endblock %} {% block local_nav %} {% endblock %} {% block content %} {% if links %}
All short URLs and their click analytics is publicly available. Time is in UTC format.
| Long URL | Created | Short URL | Clicks |
| {{ link.get_long_url_truncated }} | {{ link.get_date_created_human_friendly }} | {{ link.alias }} | {{ link.clicks_count }} |
Zero URLs have been shortened as of now.
{% endif %} {% endblock %}


PM Lee to make official visit to Mexico on Sunday
SINGAPORE: Prime Minister Lee Hsien Loong will make an official visit to Mexico from Sunday (Nov 17) to Wednesday, the Prime Minister’s Office said in a news release on Saturday.
He was invited by Mexican President Andres Manuel Lopez Obrador, who will host him for lunch during the visit.
Mr Lee will also join several Mexican governors at a separate lunch hosted by Mexico’s Secretary of External Relations Ebrard Casaubon.
Additionally, Mr Lee will meet President of the Political Board of the Senate, Ricardo Monreal Avila, as well as Mexican business leaders.
He will also address the Mexican Senate and participate in a dialogue with the Mexican business community.
Mexico City Mayor Dr Claudia Sheinbaum Pardo will present Mr Lee with the Distinguished Guest of the City Medal during his visit.
Memoranda of Understanding will be exchanged between the two countries, covering the areas of science and technology, water resources, culture, industrial property and international development.
Mr Lee will be accompanied by Mrs Lee, Senior Minister of State, Ministry of Defence and Ministry of Foreign Affairs Dr Mohamad Maliki Osman, and Senior Minister of State, Ministry of Trade and Industry and Ministry of Education Chee Hong Tat. Officials from the Prime Minister’s Office, Ministry of Foreign Affairs, Ministry of Trade and Industry and Enterprise Singapore, as well as a business delegation, will also join them.
Deputy Prime Minister Heng Swee Keat will be Acting Prime Minister during Mr Lee’s absence.


| 1 | package fr.sii.ogham.testing.assertion.html; | |
| 2 | ||
| 3 | import java.util.List; | |
| 4 | ||
| 5 | import org.custommonkey.xmlunit.DetailedDiff; | |
| 6 | import org.custommonkey.xmlunit.Difference; | |
| 7 | import org.junit.ComparisonFailure; | |
| 8 | import org.slf4j.Logger; | |
| 9 | import org.slf4j.LoggerFactory; | |
| 10 | import org.w3c.dom.Document; | |
| 11 | ||
| 12 | import fr.sii.ogham.testing.assertion.util.HtmlUtils; | |
| 13 | ||
| 14 | /** | |
| 15 | * Utility class for checking HTML content. | |
| 16 | * | |
| 17 | * @author Aurélien Baudet | |
| 18 | * | |
| 19 | */ | |
| 20 | public final class AssertHtml { | |
| 21 | private static final Logger LOG = LoggerFactory.getLogger(AssertHtml.class); | |
| 22 | ||
| 23 | /** | |
| 24 | * Check if the HTML is identical to the expected. The HTML strings are | |
| 25 | * parsed into {@link Document}s. Two documents are considered to be | |
| 26 | * "identical" if they contain the same elements and attributes in the same | |
| 27 | * order. | |
| 28 | * <p> | |
| 29 | * For each difference, the difference will be logged with error level. It | |
| 30 | * will generate a {@link ComparisonFailure} with the expected string and | |
| 31 | * actual string in order to be able to visualize the differences on sources | |
| 32 | * directly in the IDE. | |
| 33 | * </p> | |
| 34 | * | |
| 35 | * @param expected | |
| 36 | * the expected HTML | |
| 37 | * @param actual | |
| 38 | * the HTML content to check | |
| 39 | */ | |
| 40 | public static void assertEquals(String expected, String actual) { | |
| 41 | DetailedDiff diff = HtmlUtils.compare(expected, actual); | |
| 42 |
4
1. assertEquals : negated conditional → NO_COVERAGE 2. assertEquals : negated conditional → KILLED 3. assertEquals : negated conditional → KILLED 4. assertEquals : negated conditional → KILLED |
if (!diff.identical()) { |
| 43 |
2
1. assertEquals : removed call to fr/sii/ogham/testing/assertion/html/AssertHtml::logDifferences → NO_COVERAGE 2. assertEquals : removed call to fr/sii/ogham/testing/assertion/html/AssertHtml::logDifferences → SURVIVED |
logDifferences(diff); |
| 44 | throw new ComparisonFailure("HTML element different to expected one. See logs for details about found differences.\n", expected, actual); | |
| 45 | } | |
| 46 | } | |
| 47 | ||
| 48 | /** | |
| 49 | * Check if the HTML is similar to the expected. The HTML strings are parsed | |
| 50 | * into {@link Document}s. Two documents are considered to be "similar" if | |
| 51 | * they contain the same elements and attributes regardless of order. | |
| 52 | * <p> | |
| 53 | * For each difference, the difference will be logged with error level. It | |
| 54 | * will generate a {@link ComparisonFailure} with the expected string and | |
| 55 | * actual string in order to be able to visualize the differences on sources | |
| 56 | * directly in the IDE. | |
| 57 | * </p> | |
| 58 | * | |
| 59 | * @param expected | |
| 60 | * the expected HTML | |
| 61 | * @param actual | |
| 62 | * the HTML content to check | |
| 63 | */ | |
| 64 | public static void assertSimilar(String expected, String actual) { | |
| 65 | DetailedDiff diff = HtmlUtils.compare(expected, actual); | |
| 66 |
2
1. assertSimilar : negated conditional → NO_COVERAGE 2. assertSimilar : negated conditional → KILLED |
if (!diff.similar()) { |
| 67 |
2
1. assertSimilar : removed call to fr/sii/ogham/testing/assertion/html/AssertHtml::logUnrecoverableDifferences → NO_COVERAGE 2. assertSimilar : removed call to fr/sii/ogham/testing/assertion/html/AssertHtml::logUnrecoverableDifferences → SURVIVED |
logUnrecoverableDifferences(diff); |
| 68 | throw new ComparisonFailure("HTML element different to expected one. See logs for details about found differences.\n", expected, actual); | |
| 69 | } | |
| 70 | } | |
| 71 | ||
| 72 | @SuppressWarnings("unchecked") | |
| 73 | private static void logDifferences(DetailedDiff diff) { | |
| 74 | for (Difference difference : (List<Difference>) diff.getAllDifferences()) { | |
| 75 | LOG.error(difference.toString()); // NOSONAR | |
| 76 | } | |
| 77 | } | |
| 78 | ||
| 79 | @SuppressWarnings("unchecked") | |
| 80 | private static void logUnrecoverableDifferences(DetailedDiff diff) { | |
| 81 | for (Difference difference : (List<Difference>) diff.getAllDifferences()) { | |
| 82 |
2
1. logUnrecoverableDifferences : negated conditional → NO_COVERAGE 2. logUnrecoverableDifferences : negated conditional → SURVIVED |
if (!difference.isRecoverable()) { |
| 83 | LOG.error(difference.toString()); // NOSONAR | |
| 84 | } | |
| 85 | } | |
| 86 | } | |
| 87 | ||
| 88 | private AssertHtml() { | |
| 89 | super(); | |
| 90 | } | |
| 91 | } | |
Mutations | ||
| 42 |
1.1 2.2 3.3 4.4 |
|
| 43 |
1.1 2.2 |
|
| 66 |
1.1 2.2 |
|
| 67 |
1.1 2.2 |
|
| 82 |
1.1 2.2 |


The history of SUBWAY® restaurants In 1965, Fred Deluca had just audemars piguet replica graduated from high school in Bridgeport, Connecticut, USA. Like many young adults his age, he had dreams of attending college. Although he was a hard-working, competent and dependable young man, the $1.25-per-hour he earned working at the local hardware store wouldn't be enough to finance his education.
Discouraged, Fred decided to ask Dr. Peter Buck, an old family friend, for some advice. The two TAG Heuer Replica Watches had known each other for years and Fred half expected Dr. Buck to loan him the breitling replica watches money for college after telling him of his plans to study to become a medical doctor. Instead, Dr. Buck gave Fred an idea that would change his life and the lives of people around the world.
"I think you should open a submarine sandwich shop," said Dr. Buck.
At first Fred was skeptical, but after Dr. Buck explained how the sandwich shop could finance Fred's future education, he was on board. That night, Fred and Dr. Buck formed a partnership that would lead to the first SUBWAY® restaurant.
By lunchtime on the first day Fred and Pete's submarine shop was open, customers were pouring in. From that day on the company continued to grow. Fred and Pete had a goal of opening 32 submarine sandwich shops within 10 years. By 1974, eight years after they opened their first sandwich shop, Fred and Pete owned and operated sixteen shops throughout the state of Connecticut, only halfway to their goal.
As Fred and Pete looked to grow the business, talk turned to franchising, an idea they had previously dismissed as something only for "the big guys." Determined to succeed, Fred and Pete decided franchising was the key to achieving their led light bulbs for home goal. So Fred met with his friend Brian Dixon and made him an offer he couldn't refuse. He offered Brian a loan to buy one of their restaurants, but to sweeten the deal, Fred told Brian that if he didn't like the business, he could return it and owe nothing.
Brian is known as the very first SUBWAY® franchisee - setting the new standard for the SUBWAY® business model. This enabled Pete and Fred to not only reach their goal, but surpass it. Today, entering their 43rd year of operation, SUBWAY® restaurants is the world's largest submarine sandwich chain operates more units in the US, Canada and Australia than McDonald's® does. Countless awards and accolades have been bestowed upon Fred DeLuca and the SUBWAY® chain - the SUBWAY® name and its products have even appeared in numerous television and motion picture productions. The SUBWAY® franchise has come a long way from the modest sandwich shop in Bridgeport, CT.


Philippe Coutinho, the most valuable loanee in the world
The CIES football observatory have released results of a study on loan players
by Sport.esBrazilian playmaker Philippe Coutinho is the loan player with the most value in the five big leagues, per the CIES Football Observatory.
Their study reports that he is worth 96.5 million euros - a figure under the 120m euro option to buy that Bayern Munich have on the midfielder.
He is not having a great time in Germany where he is no longer essential after a promising start tot he season.
Coutinho is playing where he likes, in attacking midfield, when he does feature.
He is followed by Arsenal's Dani Ceballos (65.7m euros) and Martin Odegaard of Real Sociedad (57.3m), both on loan from Real Madrid.


Triangle Assessment
Enter the sides of a triangle to find out if it is equilateral, isosceles, or scalene:
Side 1:
Side 2:
Side 3:
Find out!
.


FIFA 20 Ultimate Team TOTW 10 predictions Aston Villa star features alongside Cristiano Ronaldo
We predict Piemonte Calcio star Cristiano Ronaldo to be named in the FIFA 20 Ultimate Team TOTW 7 lineup alongside an Aston Villa star who performed excellently for his country in this international break, here are the full predictions for the FUT 20 TOTW 7 lineup.
by Nathan BlissPiemonte Calcio and Portugal forward Cristiano Ronaldo has a great chance of being included in the FUT20 TOTW 10 this week, after an outstanding hat-trick against Lithuania, which would earn him the first in-form card of the FUT20 season.
Ronaldo predicted to be named alongside Aston Villa midfielder John McGinn in the lineup, who scored Scotland's winning goal against Cyprus in the international break.
McGinn could join the likes of Eden Hazard, Raphael Varane, Christian Eriksen, Harry Kane, Toni Kroos and Manuel Neuer in the FIFA 20 Team of the Week 10 lineup, after some outstanding international performances.
This is just a FUT 20 TOTW prediction, so there is no guarantee that any players mentioned will be included.
The FUT20 TOTW line-up is picked on single performances only, so goals and assists are not added accumulatively within the TOTW period.
Here are our FIFA 20 Ultimate Team TOTW week 10 predictions.
FIFA 20 FUT TOTW 10 goalkeeper predictions:
GK: Yann Sommer (Borussia Monchengladbach/Switzerland)
GK: Jan Oblak (Atletico Madrid/Slovenia)
GK: Manuel Neuer (Bayern Munich/Germany)
FIFA 20 FUT TOTW 10 defender predictions:
CB: Francesco Acerbi (Lazio/Italy)
CB: Raphael Varane (Real Madrid/France)
CB: Matthias Ginter (Borussia Monchengladbach/Germany)
RB: Stefan Lainer (Borussia Monchengladbach/Austria)
LB: Ben Chilwell (Leicester City/England)
LB: David Alaba (Bayern Munich/Austria)
Aston Villa latest
This is your round up of all things Villa; the one-stop shop that will keep you updated on the latest goings on at the club and beyond.
Transfers, injuries, match-days and managers, we’ve got you covered.
We’ll be bringing the very latest on the Villains throughout the week and around the clock.
Make sure you keep yourself updated with our handy daily catch up...
Must reads...
- Director reveals John McGinn's reaction to failed transfer
- Martin Keown fires puzzling criticism at Tyrone Mings
- What Jarrad Branthwaite has said about Villa interest
- Dean Smith urged to have a 'quiet word' with Frederic Guilbert
For all your latest AVFC news, opinion, analysis and transfer gossip, click here
You can follow our Villa reporter Ashley Preece on Twitter, and his email address is<EMAIL_ADDRESS>FIFA 20 FUT TOTW 10 midfielder predictions:
CDM: Grzegorz Krychowiak (Lokomotiv Moscow/Russia)
CM: Toni Kroos (Real Madrid/Germany)
CM: Harry Wilson (Bournemouth/Wales)
CAM: John McGinn (Aston Villa/Scotland)
CAM: Christian Eriksen (Tottenham/Denmark)
RM: Gerard Moreno (Villarreal/Spain)
FIFA 20 FUT TOTW 10 forwards predictions:
ST: Harry Kane (Tottenham/England)
ST: Cristiano Ronaldo (Piemonte Calcio/Portugal)
LW: Eden Hazard (Real Madrid/Belgium)
ST: Teemu Pukki (Norwich City/Finland)
ST: Aleksandar Mitrovic (Fulham/Serbia)
Follow Esports and gaming writer Nathan Bliss on social media
To follow Nathan on Twitter, click here.
To follow Reach Gaming on Twitter, click here.
To follow Nathan on Facebook, click here.
The EA Sports FIFA 20 Ultimate Team TOTW 10 will be announced at 3pm on Wednesday, November 20th.


Note 1 : Recommended statistics for this type of classification highlighted in aqua
Note 2 : The recommender system assumes that the input is the result of classification over the whole data rather than just a part of it. If the confusion matrix is the result of test data classification, the recommendation is not valid.
| Actual | Predict
|
| Class | D001289 | D006262 | Description |
| ACC | 0.73462 | 0.73462 | Accuracy |
| AGF | 0.70238 | 0.76636 | Adjusted F-score |
| AGM | 0.75632 | 0.70817 | Adjusted geometric mean |
| AM | -169 | 169 | Difference between automatic and manual classification |
| AUC | 0.73462 | 0.73462 | Area under the ROC curve |
| AUCI | Good | Good | AUC value interpretation |
| AUPR | 0.71831 | 0.75592 | Area under the PR curve |
| BCD | 0.03611 | 0.03611 | Bray-Curtis dissimilarity |
| BM | 0.46923 | 0.46923 | Informedness or bookmaker informedness |
| CEN | 0.78707 | 0.73271 | Confusion entropy |
| DOR | 8.19536 | 8.19536 | Diagnostic odds ratio |
| DP | 0.50368 | 0.50368 | Discriminant power |
| DPI | Poor | Poor | Discriminant power interpretation |
| ERR | 0.26538 | 0.26538 | Error rate |
| F0.5 | 0.74894 | 0.72326 | F0.5 score |
| F1 | 0.71396 | 0.75249 | F1 score - harmonic mean of precision and sensitivity |
| F2 | 0.6821 | 0.78418 | F2 score |
| FDR | 0.22577 | 0.295 | False discovery rate |
| FN | 395 | 226 | False negative/miss/type 2 error |
| FNR | 0.33761 | 0.19316 | Miss rate or false negative rate |
| FOR | 0.295 | 0.22577 | False omission rate |
| FP | 226 | 395 | False positive/type 1 error/false alarm |
| FPR | 0.19316 | 0.33761 | Fall-out or false positive rate |
| G | 0.71613 | 0.7542 | G-measure geometric mean of precision and sensitivity |
| GI | 0.46923 | 0.46923 | Gini index |
| GM | 0.73106 | 0.73106 | G-mean geometric mean of specificity and sensitivity |
| IBA | 0.45725 | 0.61164 | Index of balanced accuracy |
| IS | 0.63083 | 0.4957 | Information score |
| J | 0.55516 | 0.60319 | Jaccard index |
| LS | 1.54845 | 1.41001 | Lift score |
| MCC | 0.4742 | 0.4742 | Matthews correlation coefficient |
| MCCI | Weak | Weak | Matthews correlation coefficient interpretation |
| MCEN | 0.94063 | 0.90448 | Modified confusion entropy |
| MK | 0.47923 | 0.47923 | Markedness |
| N | 1170 | 1170 | Condition negative |
| NLR | 0.41843 | 0.29161 | Negative likelihood ratio |
| NLRI | Poor | Poor | Negative likelihood ratio interpretation |
| NPV | 0.705 | 0.77423 | Negative predictive value |
| OC | 0.77423 | 0.80684 | Overlap coefficient |
| OOC | 0.71613 | 0.7542 | Otsuka-Ochiai coefficient |
| OP | 0.6363 | 0.6363 | Optimized precision |
| P | 1170 | 1170 | Condition positive or support |
| PLR | 3.4292 | 2.38987 | Positive likelihood ratio |
| PLRI | Poor | Poor | Positive likelihood ratio interpretation |
| POP | 2340 | 2340 | Population |
| PPV | 0.77423 | 0.705 | Precision or positive predictive value |
| PRE | 0.5 | 0.5 | Prevalence |
| Q | 0.7825 | 0.7825 | Yule Q - coefficient of colligation |
| RACC | 0.21389 | 0.28611 | Random accuracy |
| RACCU | 0.21519 | 0.28742 | Random accuracy unbiased |
| TN | 944 | 775 | True negative/correct rejection |
| TNR | 0.80684 | 0.66239 | Specificity or true negative rate |
| TON | 1339 | 1001 | Test outcome negative |
| TOP | 1001 | 1339 | Test outcome positive |
| TP | 775 | 944 | True positive/hit |
| TPR | 0.66239 | 0.80684 | Sensitivity, recall, hit rate, or true positive rate |
| Y | 0.46923 | 0.46923 | Youden index |
| dInd | 0.38896 | 0.38896 | Distance index |
| sInd | 0.72496 | 0.72496 | Similarity index |
Generated By PyCM Version 2.4


Screening Instance, also called Screening engine is a service that scans text/message(s) against the Screening Instance which gives alert or no alert result. Screening Instance manages those Screening instances/engines. Currently we only support one physical index and one Screening engine at a time which also means that at any time, there is only one Screening engine running, using the index that was last built (see Build-Index below). The last built index will override the previous one.
Clicking the Screening Instance in the left navigation menu under Screening management will make a new Screening Instance Tab folder be created in the right panel. There are 3 sub-Tab folders: Search Screening Instance, Search Result Screening Instance and Create New Screening Instance.
Search Criteria
| Field Name | Description |
|---|---|
| InstanceId | This is the unique number for the Screening Instance entry in the system . |
| Instance Name | Name of the Screening Instance. |
| AND | Select AND radio box if you want those criteria add together. |
| OR | Select OR radio box if you want to get the result if either criteria meet |
The top part is the table which shows the list of the screening instances that meet the search criteria. The bottom part is the details of the selected entry.
Double Click the selected record in the table to modify this entry. A new Tab folder Update/Delete Screening Instance will be added, as shown below.
Update: – make changes on the screening instance, and save and switch back to the “Search result Screening Instance” Tab. Some of the fields in this form are read only, like Instance Id, created/modified user and date. The configuration Data field is also read only, so it can be modified via using the Re-Configure button.
Reset:– reset the data to its initial value and discard all the changes.
Cancel:– Cancel this change and switch back to the “Search Result Screening Instance” Tab.
Delete:– Delete this entry. Then switch back to the “Search Result Screening Instance” Tab.
Re-Configure – Click this button to open a configure wizard to set up the configuration data, as shown below:
Click the Next Button to go to wizard step 2
This is a Sanction List search Search Sanction List panel, allowing the user to select the sanction list entries to be included in this screening instance. It is pre-populated with the data in the Configuration Data field.
Set search criteria; then clicking the Find Button will get a list of sanction list entries that meet the search criteria. Those sanction list entries will be indexed and used by this screening instance to scan customer data and/or payment transaction.
Click the Next button to go to wizard step 3: Save the configuration
Build Index – Click this button to build search index using the sanction list set in the previous step.
Note
Search index must be re-built in order to affect the configuration data changes. This is a very important step. Screening Instance uses search index to scan against customer data or transaction messages.
Select the “Create New Screening Instance” Tab to create a new entry.
| Field Name | Description |
|---|---|
| InstanceId | This is the unique number for the screening Instance entry in the system. |
| Instance Name | Name of the filter screening. This is a mandatory field. |
| Description | Description of this entry. |
| Data | Configuration data to define what sanction list entries should be included in the search index. User has to set the data value via Configure button. |
| CreatedByDate | Date and Time when this Screening Instance entry is created. It is a read only field. |
| CreatedByUser | User who create this Screening Instance entry. It is a read only field. |
| ModifiedByDate | Last modified date and time; It is a read only field. |
| ModifiedByUser | Last modified user; It is a read only field. |