Openshift cartridges: python 2.7

Django 1.8

According to this thread, “Files in $OPENSHIFT_REPO_DIR/wsgi/static folder are served by Apache directly”, so we have the following setting works well.


STATIC_URL = ‘/static/’

STATIC_ROOT = os.path.join(DJ_PROJECT_DIR, ‘../../static’)






    os.path.join(DJ_PROJECT_DIR, ‘../../dist’),



1) STATIC_URL and STATIC_ROOT map yourdomain.com/static/ to the $OPENSHIFT_REPO_DIR/wsgi/static.

2) We also set STATICFILES_DIRS to wsgi/dist as we also use browserify to bundle the sources, which are in /wsgi/static_src

3) Collecting static files to STATIC_ROOT is part of openshift’s deploy job. See the 4th step of this instruction.


React.js unit test

The recent project uses React.js, and React Bootstrap library. We found the following unittest setting works well:

  • runner: karma
  • framework:  mocha
  • JSX transformer: babel
  • dependency management: webpack



SUT (subject under test) : e.g. ./static/js/components/myComponent.js
tests: e.g. /static/js/components/__tests__/myComponent-test.js


"devDependencies": {
"babel-core": "^5.3.0",
"babel-loader": "^5.3.0",     # default install babel 6.+, but we need version 5.3+ to compile react-booststrap library
"expect": "^1.13.4",
"karma": "^0.13.16",
"karma-chrome-launcher": "^0.2.2",
"karma-cli": "^0.1.2",
"karma-mocha": "^0.2.1",
"karma-webpack": "^1.7.0",
"mocha": "^2.3.4",
"react": "^0.14.3",
"react-addons-test-utils": "*",
"react-bootstrap": "*",
"react-dom": "~0.14.0",
"webpack": "^1.12.9",


var webpack = require(‘webpack’);

module.exports = function (config) {
        browsers: [‘Chrome’],
        singleRun: true,
        frameworks: [‘mocha’],
        files: [
        preprocessors: {
            ‘tests.webpack.js’: [‘webpack’]
        reporters: [‘dots’],
        webpack: {
            module: {
                loaders: [
                    {test: /\.jsx?$/, exclude: /node_modules/, loader: ‘babel-loader’}
            watch: true
        webpackServer: {
            noInfo: true


var context = require.context(‘./static/js/components’, true, /-test\.jsx?$/);

Run test

npm test

Test strategies

Render the SUT

var myComponent = TestUtils.renderIntoDocument(<MyComponent prop1={prop1}/>);

Verify the SUT


Verify SUT’s DOM

// assume SUT is rendered as


var node = ReactDOM.findDOMNode(myComponent);


Verify SUT’s child component

Several ways to access SUT’s child nodes:

  • Using React component’s ref property
  • Via the rendered DOM
  • TestUtils methods, e.g. TestUtils.scryRenderedDOMComponentsWithClass

Need to distinguish between an React component instance and a DOM node instance.

var childComponent = myComponent.refs.childRef;

Verify SUT’s multiple child components of the same class/tag

var childNodes = TestUtils.scryRenderedDOMComponentsWithClass(myComponent, ‘label’); 

Verify SUT’s child node

var childComponent = myComponent.ref.childRef;
var childNode = ReactDOM.findDOMNode(childComponent);

Simulate SUT event

// assume SUT is rendered as


var nodeHavingOnClickEvent = ReactDOM.findDOMNode(myComponent).firstChild;
TestUtils.Simulate.click(nodeHavingOnClickEvent);    // invoke node <span>’s onClick event

Simulate changes to SUT’ properties or state

myComponent.state.state1 = ‘anotherState’;

Simulate changes to ReactBootstrap.Input’s value

/** e.g. render() : function() {
      return (




var input = myComponent.refs.input;
input.getInputDOMNode().value = ‘newValue’;

Test ReactBooststrap’s modal


ReactBooststrap’s modal has many child components, e.g. title, body, etc.
e.g. MyModal
render: function() {
        return (


    it(‘does not render when props.show is false’, ()=>{
        // render in the document
        var modal = TestUtils.renderIntoDocument(
            <MyModal show={false} />
        var notFound = ReactDOM.findDOMNode(modal.refs.title);
    it(‘renders when props.show is true’, () => {
        // render in the document
        var modal = TestUtils.renderIntoDocument(
            <MyModal show={true} />
        var found = ReactDOM.findDOMNode(modal.refs.title);



I prefer a comfort-for-eye background colour:  C7EDCC. Edit Sublime Text 3 Colour Theme is surprisingly easy.


Install PackageResourceViewer.


PackageResourceViewer: OpenResource


Then walk through the package resources, we need to open:

Color Scheme – Default


Edit the the background value, and that’s it!

Winking smile


There is also an amazing cool colour theme editor:


I bought TP-LINK AV500 wifi Powerline extender starter kits, including one TL-PA4010 and two TL-WPA4220. The best part of this solution is to extend the network as far as power line covers, and wifi clone.

The setup should be as easy as the following diagram and several button pressing. Unified Home Network

But, it was not. I could not tell why/how, but it did not work for me…

Lucky we can do it hard way, which guarantee success.

We need TP-LINK Powerline Scan tool (find in the product CD or this link). We then plug all powerline devices into wall sockets. We need at least one Ethernet cable.

We need to accomplish the following two tasks:

1) Add two TL-WPA4220 to TL-PA4010’s network.

Connect laptop to any TL-WPA4220 using Ethernet cable. Use the Powerline Scan tool to find and connect to the device. Login user and password are both ‘admin’. In the page, write down ‘Device Password’ and ‘Mac Address’. Find the info for the two TL-WPA4220.

Then connect to TL-PA4010 using Ethernet cable. Use the Powerline Scan tool to find and connect to the device. Login user and password are both ‘admin’. Click ‘Powerline’ -> ‘Station Setting’ in the left side menu. On the right side main page, click ‘Add New…’, enter a TL-WPA4220’s  Device Password, and any Device Name. And we are done adding TL-WPA4220 to TL-PA4010’s network.

2) Set TL-WPA4220 to clone home wifi. (necessary if home wifi router does not support WPS feature)

Use Ethernet cable to connect to TL-WPA4220. In the admin website, Click ‘Wireless’ -> ‘Wireless Setting’, edit SSID the same as home wifi SSID. ‘Wireless’ -> ‘Wireless Security’ to set the same authentication method and login password. Reboot the device to save the settings. Then we are done to set TL-WPA4220 to clone home wifi.

That’s it. I now have strong wifi signal in garden.

Google chromecast

Google Chromecast + Google Chrome brower + unlock youku extension. Ultimate solution. 🙂

Key words include: Windows 7 64bit, MinGW, Sublime Text 2 and CMake. github has this sublime text 2 c++ project boilerplate, which includes a CMakeLists.txt demonstrating linking to the Boost regex library.

Install MinGW

Download from MinGW Distro. This distribution includes up-to-date MinGW, as well as several often used libraries, e.g. Boost. Installation is as easy as extracting. Note that, GCC’s mode is C++11 by default since v11.2.

After extracting to C:\, add the following paths to the system environment variable PATH: (If not installed to C:\MinGW, we need further update cmake commond’s CMAKE_MAKE_PROGRAM in the project boilerplate.)

  • C:\MinGW\bin
  • C:\MinGW\lib
  • C:\MinGW\include

Install CMake

Download the Windows installer (only 32bit) from the official site.

After installed to the default path, add C:\Program Files (x86)\CMake 2.8\bin to PATH.

Set up Sublime Text 2

Assume Sublime Text 2 and Package Manager installed.

Use Package Manager to install CMake Syntax.

Download the project boilerplate.

Use the project boilerplate

Set the default Build System as make (Tools -> Build System –> make).

Ctrl+Shift+P –> cmake to run cmake

Ctrl+B to make


Will add “run” and “debug” two commands. And perhaps add auto complete suggestions supports for Sublime Text 2.

Reference Sites



  • Herpes labialis,中文意思是唇疱疹。这个是SNOMED CT推荐的术语。也是“嘴唇上火”的医学术语。
  • Herpes simplex,中文的意思是单纯疱疹,唇疱疹的更一般病症表述。
  • 略微口语化的表达可以是Cold sore或者Fever blister。值得一提的是,这两个略微口语化的表达是非常准确且有医学专业背景的。Cold sore是NHS官网上的。同时,两者都被SNOMED CT收录为Herpes labialis的同义词。


我的分析,要从症状入手翻译:嘴唇上火的症状是嘴唇上起燎泡。水泡或者燎泡译为blister是准确的。其次,要从医学术语入手寻找翻译,那些燎泡是一种疱疹(herpes)。进一步,唇部的疱疹,即嘴唇上火,就是Herpes labialis。其中,labialis是唇的意思。


题外话:在确认“嘴唇上火”怎么翻译的过程中,也简单了解了这个病症:嘴唇上火,即唇疱疹,或者单纯疱疹,是一种病毒引起的局部病变。初次感染后,病毒会永远潜伏在人体内(感觉神经细胞内),然后因为某种诱因,再度发作。西医发现感冒/发烧是常见的诱因,所以被称作Cold sore或者Fever blister。

此外,我们熟知的“出水痘”也和“嘴唇上火”有点联系:水痘是病毒引起的,这个我们都知道了。而水痘的后遗症(远期并发症),叫做带状疱疹(Herpes Zoster,或者shingles),中医称作“缠腰龙”。“缠腰龙”的发作和“嘴唇上火”的发作原因类似,是因为长期潜伏在人体内的病毒(水痘病毒Varicella Zoster)再度发作引起的。



  1. SNOMED CT: Systematized Nomenclature of Medicine Clinical Terms。是一个医学术语的国际标准。
  2. Wikipedia (小心各种疱疹的照片,比较恶心)
  3. “嘴唇上火”英文翻译的讨论:http://bbs.tianya.cn/post-english-126757-1.shtml
  4. Cord sore NHS page: http://www.nhs.uk/conditions/Cold-sore/Pages/Introduction.aspx