Tuesday, 18 September 2018

Introduction to Rollup.js

rollup.js is a module bundler which compiles JavaScript  modules into a library or application.

In this article I want to go through Rollup Tutorial and:

  • install Rolllup.js
  • create an application which consists of modules 
  • demonstrate how Rollup bundles multiple files into a single one


Rollup Installation 



Instead of installing Rollup.js globally as in the tutorial, I'll install it locally as I want to make it portable - all clones of this project will use the same Rollup version.

Let's see how package.json looks after executing npm init:

C:\wherever\rollup-js-demo>type package.json
{
  "name": "rollup-js-demo",
  "version": "1.0.0",
  "description": "Application which demoes Rollup.JS basic features.",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/BojanKomazec/rollup-js-demo.git"
  },
  "keywords": [
    "rollup.js",
    "demo"
  ],
  "author": "Bojan Komazec",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/BojanKomazec/rollup-js-demo/issues"
  },
  "homepage": "https://github.com/BojanKomazec/rollup-js-demo#readme"
}

To install Rollout.js locally (per project) we'll omit -g in npm install. By default npm install rollout would add Rollout to dependencies but as it is a dependency used in development we'll use --save-dev option:

C:\wherever\rollup-js-demo>npm install --save-dev rollup
+ rollup@0.66.0
added 3 packages from 33 contributors and audited 3 packages in 0.903s
found 0 vulnerabilities

If we now check package.json, Rollout will be listed in devDependencies:

C:\wherever\rollup-js-demo>type package.json
{
  "name": "rollup-js-demo",
  "version": "1.0.0",
  "description": "Application which demoes Rollup.JS basic features.",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/BojanKomazec/rollup-js-demo.git"
  },
  "keywords": [
    "rollup.js",
    "demo"
  ],
  "author": "Bojan Komazec",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/BojanKomazec/rollup-js-demo/issues"
  },
  "homepage": "https://github.com/BojanKomazec/rollup-js-demo#readme",
  "devDependencies": {
    "rollup": "^0.66.0"
  }
}

As this package is installed locally we won't be able to access its executable from anywhere - we have to go to its directory. We can execute it and for example check Rollout.js version first:

C:\wherever\rollup-js-demo\node_modules\.bin>rollup --version
rollup v0.66.0


Writing an Application in a Modular Way



Now when we have Rollup installed, we can create our project which consist of an entry point script which imports a module:

C:\wherever\rollup-js-demo\src\scripts\modules\foo.js:

export default 'hello world!';

C:\wherever\rollup-js-demo\src\scripts\main.js:

// application entry point
import foo from "./modules/foo.js";
export default function() {
    console.log(foo);
}


Bundling Modules With Rollup



Let's create a bundle and push it onto stdout:

C:\wherever\rollup-js-demo\node_modules\.bin>rollup ../../src/scripts/main.js -f cjs

../../src/scripts/main.js → stdout...
'use strict';

// a module

// export a primitive (string in this case)
var foo = 'hello world!';

// application entry point
function main() {
    console.log(foo);
}

module.exports = main;
created stdout in 39ms

Rollup took couple of parameters:
  • path to the JS script which is application's entry point
  • -f cjs - bundle format specification; in this case cjs - CommonJS runnable by Node.js


Running the Bundle in Node Console



To run this bundle with Node.js we have to save it to the file:

C:\wherever\rollup-js-demo\node_modules\.bin>rollup ../../src/scripts/main.js -f cjs -o ../../build/js/bundle.js

../../src/scripts/main.js → ../../build/js/bundle.js...
created ../../build/js/bundle.js in 40ms

Let's run the bundle now with Node.js:

C:\wherever\rollup-js-demo\node_modules\.bin>node
> let bundle = require('../../build/js/bundle.js');
undefined
> bundle()
hello world!
undefined

For each function Node outputs its return value. If function has only side effects (like printing something on the stdout) Node will output undefined as its return value. [source]


Using Configuration File



Instead of passing a (potentially long) list of parameters and options to rollup executable, we can place them into a configuration file.

C:\wherever\rollup-js-demo\rollup.config.js:

export default {
    input: '../../src/scripts/main.js',
    output: {
        file: '../../build/js/bundle.js',
        format: 'cjs'
    }
}

Paths in configuration file have to be relative to the path of the Rollup executable.

Rollup now only needs to be passed the path to configuration file:

C:\wherever\rollup-js-demo\node_modules\.bin>rollup -c ../../rollup.config.js

../../src/scripts/main.js → ../../build/js/bundle.js...
created ../../build/js/bundle.js in 18ms

Rollup creates all directories in specified path to the output file. In this case that is: build/js.



Creating a Bundle Loadable Into Web Page



Let's now create a bundle script that can be loaded into an HTML file. Let's say that now instead of printing foo value into console we want to print it in HTML page. Let's define first HTML page.

C:\wherever\rollup-js-demo\test\index.html:

<!DOCTYPE html>
  <head>
    <meta charset="utf-8">
    <title>Rollup.js Demo</title>
  </head>
  <body>
    <p id="log"></p>
    <script src="../build/js/bundle-browser.js" async defer></script>
  </body>
</html>

bundle-browser.js is a bundle output that will be created for this test.

Let's create another entry point JS file which is adjusted to the web page it will be loaded into.

C:\wherever\rollup-js-demo\src\scripts\main-browser.js:

// application entry point
import foo from "./modules/foo.js";

const log = document.getElementById('log');
log.innerText = 'foo value (loaded from a module) is: \n';
log.innerText += foo;

As we now have different input and output files, we can create another Rollup config file.

C:\wherever\rollup-js-demo\rollup.config.browser.js:

export default {
    input: '../../src/scripts/main-browser.js',
    output: {
        file: '../../build/js/bundle-browser.js',
        format: 'iife',
        name: 'main'
    }
}

The content of the JS file aimed to be loaded into web page should be wrapped in the auto-executed function - therefore we have to use iife output format.

If output.name is not specified Rollup gives the following error:
Error: You must supply output.name for IIFE bundles

Let's now create a bundle:

C:\wherever\rollup-js-demo\node_modules\.bin>rollup -c ../../rollup.config.browser.js

../../src/scripts/main-browser.js → ../../build/js/bundle-browser.js...
created ../../build/js/bundle-browser.js in 25ms

C:\wherever\rollup-js-demo\build\js\bundle-browser.js:

(function () {
'use strict';

// a module

// export a primitive (string in this case)
var foo = 'hello world!';

// application entry point

const log = document.getElementById('log');
log.innerText = `Demo app: \n\n`;
log.innerText += foo;

}());

If we open index.html in browser, we can see:


Check out the source code for this demo (on my GitHub).

Thursday, 13 September 2018

node-gyp and Python support on Windows

node-gyp is a cross-platform command-line tool written in Node.js for compiling native addon modules for Node.js. [node-gyp on GitHub] [node-gyp]

If you try to run node-gyp on a machine with no Python installed you might get an error similar to this:

gyp ERR! configure error
gyp ERR! stack Error: Can't find Python executable "python", you can set the PYTHON env variable.
gyp ERR! stack at PythonFinder.failNoPython (C:\Users\user\AppData\Roaming\npm\node_modules\npm\node_modules\node-gyp\lib\configure.js:484:19)
gyp ERR! stack at PythonFinder. (C:\Users\user\AppData\Roaming\npm\node_modules\npm\node_modules\node-gyp\lib\configure.js:509:16)
gyp ERR! stack at C:\Users\user\AppData\Roaming\npm\node_modules\npm\node_modules\graceful-fs\polyfills.js:284:29
gyp ERR! stack at FSReqWrap.oncomplete (fs.js:158:21)
gyp ERR! System Windows_NT 10.0.17134
gyp ERR! command "C:\\Program Files\\nodejs\\node.exe" "C:\\Users\\user\\AppData\\Roaming\\npm\\node_modules\\npm\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild"
gyp ERR! cwd C:\whatever\my-app\node_modules\dtrace-provider
gyp ERR! node -v v10.7.0
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok

(cwd in this output message stands for Current Working Directory)

If you have Python 3 installed, the same command will fail for Python 3 interpreter not be able to parse Python 2 code...This happens as node-gyp (still) doesn't support Python 3 so you'll need to install Python 2 (2.7.x).

When installing Python 2 DO NOT opt for adding its path to PATH environment variable as otherwise it will make Python 2 the default one on the machine.

The easiest way to make node-gyp working with Python 2 while not interfering with existing Python 3 paths is to follow the suggestion from the error message above, create PYTHON env variable and set its value to Python 2 path (C:\Python27). Then we can have this setup before we execute node node-gyp.js:

>python --version
Python 3.7.0

>echo %PYTHON%
C:\Python27


How to install Python on Windows?

How to install the latest version of Python?

  • Go to Python Releases for Windows page and click the link for the latest release, e.g. Latest Python 3 Release - Python 3.7.0
  • Scroll to the bottom of the page and click on the link of the installer to download it. I opted for "Windows x86-64 web-based installer".
  • Run the installer. On the first page of the installer opt for adding Python to PATH.
  • Python will be installed in C:\Users\User\AppData\Local\Programs\Python\Python37.

If you haven't opted for adding Python to PATH during installation, you open a Terminal and try to run Python interpreter by typing python you'll get:

>python
'python' is not recognized as an internal or external command,
operable program or batch file.

To resolve this and make python binary visible from every directory add its path to Path environment variable. After that, python interpreter is visible from anywhere (in a new Terminal session):

>python
Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>


How to install multiple versions of Python on the same system?


Sometimes you need to have on your machine installed various versions of Python e.g. some applications might require Python 2 and some Python 3. I already installed Python 3 above and now I'm gonna install Python 2:
  • Go to Python Releases for Windows page and click the link for the latest release, e.g. Latest Python 2 Release - Python 2.7.15
  • Scroll to the bottom of the page and click on the link of the installer to download it. I opted for "Windows x86-64 MSI installer".
  • Run the installer. On the first page of the installer you can opt for adding Python 2 to PATH.
  • Python will be installed in C:\Python27.
If you opt for adding Python 2 to Path, restart the Terminal (so it can pick up the latest values of environment variables) and type python, Terminal will pick Python 2:

>python
Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

Python 2 installer has added C:\Python27 (and C:\Python27\Scripts) as first entries in PATH variable so Terminal now picks python.exe from this directory.

To make sure you are using desired version of Python interpreter in Terminal the best is to remove all Python paths from PATH and then set path to desired Python version for the current Terminal session (temporarily) by executing:

>set PATH=path\to\desired\python;%PATH%

Friday, 7 September 2018

"The Vue Handbook" Annotations - Part 2: Vue CLI and intro in Vue Components

This is the second article in the series of my annotations to The Vue Handbook. It covers the Vue CLI (command line interface), CLI applications and components. If you missed reading the first article (which covers the introduction in Vue.js and creating the very first application) go here.



What is Vue CLI?

  • command line utility 

What is Vue CLI used for?

  • to speed up development - it provides initial Vue.js project setup and scaffolding application skeleton with a sample app in place
  • vue-cli README on GitHub
  • makes sure all the tools you need are working along

How to install Vue CLI?


Vue CLI can be installed via:
  • npm
  • Yarn


Installing Vue CLI via npm

  • https://cli.vuejs.org/guide/installation.html
  • package name changed from vue-cli (in v1 and v2) to @vue/cli (in v3)
  • Vue CLI requires Node.js version 8.9 or above (8.11.0+ recommended).
  • https://www.npmjs.com/package/@vue/cli

    Commands and output in terminal:



    How to test that Vue is installed and check command line arguments?



    How to check Vue's version?




    How to create a Vue project with CLI?


    Vue project can be created by using:
    • only a command line (vue create)
    • browser-based UI (vue ui)
    Read: 


    How to create a Vue project from command line only?


    The Vue Handbook uses the name "example" for the new application so let's follow it:



    First select if you want only default or extended tooling to be installed

    Custom toolset selection

    You can add more plugins later by using vue add.

    Linting tools selection



    Linting features selection

    Configuration location options

    Vue app setup can be saved and reused for setting future projects
    Running the setup
    This is the entire terminal output:



    I don't have Yarn installed so I assume that is a reason this wizard didn't ask me if I want to use npm or Yarn and it automatically selected npm.

    To see which scripts can be run we can use:



    And indeed, package.json contains scripts object with CLI commands listed above:


    This is the role of each of them:
    • serve (short of service) - starts a dev server, compiles and hot-reloads for development 
    • build - performs production build  (compiles and minifies the code); prepares the project for deployment in dist/
    • lint - lints and fixes files

    What is hot reloading?

    Hot reloading only refreshes the files that were changed without losing the state of the app. For example, if you were four links deep into your navigation and saved a change to some styling, the state would not change, but the new styles would appear on the page without having to navigate back to the page you are on because you would still be on the same page.[source]

    The idea behind hot reloading is to keep the app running and to inject new versions of the files that you edited at runtime. This way, you don't lose any of your state which is especially useful if you are tweaking the UI. [source]

    How to run example app? As the last lines in the terminal output suggest, lets run serve:



    If we navigate browser to the given local URL, we can see our Vue CLI application:


    To terminate local web server, go to terminal and press CTLR-C.

    My repository for this app: https://github.com/BojanKomazec/the-vue-handbook-demo-cli-example

    So, let's explore files in the created project:



    index.html:
    • main app file (Vue CLI by default uses main.js and index.js as its entry point)
    • contains div with id="app"; we'll attach to this div a new Vue application

    Before we analyze other files, let's learn some more of the Vue stuff:

    What are Vue components?


    Components are reusable blocks of code that can have both structure and functionality. They help create a more modular and maintainable codebase. (...) In a Vue application, we don’t want all of our data, methods, computed properties, etc. living on the root instance. Over time, that would become unmanageable. Instead, we’ll want to break up our code into modular pieces so that it is easier and more flexible to work with. [source]

    Components are reusable Vue instances with a name. [from Components Basics; read here a quick intro in the logic behind how are components created and used]

    The main/root instance is the root component, it has no parent component.

    See some examples of Vue UI components.


    How to define/register Vue component?

    • programmatically (new Vue() and Vue.component())
    • via Single File Component (.vue) file


    Defining components via Vue.component()


    Programmatical definition of Vue component is done by calling a function Vue.component(component_name, properties). properties object contains:

    • HTML - as a value of template property.
    • JavaScript -  as a function which is a value of data property.

    Example:



    Defining components as Single File Components


    Files with .vue extension are Single File Components - self-contained components that have all they need in a single file. .vue file contains:
    • HTML - within <template> element.
    • JavaScript - within <script> element.
    • CSS - within <style> element. CSS can be scoped (<style scoped>) or not. 
    Example: src/components/HelloWorld.vue (analyzed later in this article)


    What is scoped CSS?


    Scoped CSS means that CSS is targeting the component uniquely, CSS won’t leak to other parts of the page, it is limited to this component only. CSS is scoped when style tag has scoped attribute.

    We can now better understand a global picture - a Vue application.

    What is Vue application?


    A Vue application consists of a root Vue instance created with new Vue, optionally organized into a tree of nested, reusable components. All Vue components are also Vue instances, and so accept the same options object (except for a few root-specific options). [Creating a Vue instance]


    HelloWorld.vue:
    • a Vue component
    • implemented as Single File Component
    • outputs a set of links, along with a message
    • has scoped CSS
    • name property has value 'HelloWorld'. This defines a custom HTML element with this name and which can be imported to another component simply by stating <HelloWorld/>
    • props (properties) object contains custom property msg. This defines msg as a (custom) property of HelloWorld (custom) element. When using this component elsewhere we'll write: <HelloWorld msg="whatever"/>
    • The message the component outputs is stored in the data property of the Vue instance, and outputted in the template as {{ msg }}
    • Anything that’s stored in data is reachable directly in the template via its own name. We didn't need to say data.msg, just msg.

    So, who is using HelloWorld component and how? Let's look into the next file.

    src/App.vue


    App.vue:
    • a Vue component
    • implemented as Single File Component
    • has global (non-scoped) CSS
    • imports another component (HelloWorld) simply by adding <HelloWorld/> element. HelloWorld is a dependency of App.

    Who is using App component and how? Let's look into the next file.




    main.js:
    • application's main script
    • creates a Vue application (creates Vue instance via new Vue(...)
    • imports App component by specifying it in the value of components property in application's options object 



    Monday, 3 September 2018

    "The Vue Handbook" Annotations - Part 1: Introduction and the first Vue.js app

    Driven by professional needs and my curiosity, I decided to start learning Vue.js. It is a very popular JavaScript framework which can be used for UI development of variety of products, from web front-end, browser extensions to native mobile and desktop applications.

    I decided to start my journey by reading The Vue Handbook: a thorough introduction to Vue.js by Flavio Copes. I will use a series of blog posts to track my learning progress and document annotations to this book I find useful to me and to other readers.

    So, let's start.



    Introduction - General info about Vue.js


    Vue.js is a progressive framework meaning that it allows initial intervention at small pieces of code with no need to change existing architecture which can gradually expand onto the entire view layer.

    It uses Virtual DOM (idea taken from React but in Vue has better performance and it's easier to use)
    Vue uses HTML template syntax. Think of it as the syntax extension of HTML which facilitates dynamic binding of values in user-facing elements and underlying components that contain data. Many similar frameworks have such concept:
    • Angular template syntax
    • Handlebars
    • The Django template language (this is Python but general explanation about templates applies to Vue as well)
      • Django template system is not simply Python embedded into HTML. This is by design: the template system is meant to express presentation, not program logic.
      • A template is simply a text file. It can generate any text-based format (HTML, XML, CSV, etc.).
      • A template contains variables, which get replaced with values when the template is evaluated, and tags, which control the logic of the template.
      • Variables look like this: {{ variable }}. When the template engine encounters a variable it evaluates that variable and replaces it with the result.
      • React does NOT have templates! Here's why. It uses JSX.
        Vue's official state management library is Vuex (vuex package). It follows the Flux architecture [docs],


        What is state management in front-end?
        • What does state-management even mean and why does it matter in Front End Web Development with frameworks like React or Vue?
          • In front-end programming, one of the most essential demands is that the UI/display always reflect current application state, especially as state changes in response to user interaction. Binding JavaScript values to the display (the DOM) is the essence of React, Vue and Angular.
          • (...) create an architecture in which all the values in state are stored in a central location, with their current values funneled down to whatever components display these values. Thus modern state management of the Flux/Redux/ngrx model demands the creation of a “store” — a centralized object where all of the values in state are collected.
          • The key idea (...) is to make sure that state (meaning any one or more of the values in state) cannot be changed except by defined “actions” that are processed by a “reducer” function. The idea is to create a definite and exclusive list of ways in which state can possibly be changed, and then to process these actions in a distinct sequence.
          • Learn State Management
          • State Management

          Its routing package is: vue-router


              The very first example


              Source:


              Page with console log:


              Vue is like a glue between a UI (subset of DOM elements that are matching UI template) and underlying data. Each instance of Vue binds together UI template with data source in a fully reactive way: as soon as data is changed, matching DOM elements are re-rendered.

              new Vue() creates a (root) instance of Vue app [Creating a Vue Instance]. Its argument is an options object. In the simplest case it has to define two main things: DOM elements and data source.
              • el - provides the Vue instance an existing DOM element to mount on. It can be a CSS selector string or an actual HTMLElement. The provided element merely serves as a mounting point. The mounted element will be replaced with Vue-generated DOM in all cases. It is therefore not recommended to mount the root instance to <html> or <body>. [el]. In our case the Vue instance will be bound to a div element with id "example".
              • data - The data object for the Vue instance [data].
                {{hello}} is a template and hello itself is template variable which gets evaluated into value of the data member with the matching name. Personally, I would have used some different name for this variable like message for example as 'hello' is actually a kind of a message text.
                  Let's test reactiveness by modifying the source code by naming the Vue application instance. This will allow us to access and modify its properties from the code or from the browser console.

                  Source:


                  If we modify data, we can see how text in the bound DOM element changes instantly:


                  Vue.js script is downloaded from the URL https://unpkg.com/vue used in script tag. unpkg is a global CDN used for distribution of various JavaScript packages. If you type in the browser the same URL and append a slash to it, you can see the latest available version of that package and its files:

                  If we check the Sources tab of our index page, we can see that exactly this version has been downloaded. We didn't specify any particular Vue version in the URL so the latest version was fetched:




                  Read the next article in series: "Part 2: Vue CLI and intro in Vue Components"

                  Sources:

                  The Vue Handbook: a thorough introduction to Vue.js
                  A Comparative Study of Progressive JS Frameworks: Angular.js & Vue.js

                  Wednesday, 29 August 2018

                  How to emulate No Internet connection on Guest Windows OS in VirtualBox

                  Emulating OS being disconnected from Internet is a frequent scenario in testing various software features.

                  Let's assume we are running Windows as a Guest OS in VirtualBox and want to emulate it being disconnected from Internet.



                  Before taking any action it is always good to check that you are running the latest version of VirtualBox.

                  Disconnecting the Guest from Internet can be achieved in several ways:
                  • From within Guest Windows OS:
                    • If host is using WiFi:
                      • Turn off WiFi
                      • Disconnect Wireless NIC from WiFi network
                      • Disable Wireless NIC
                    • If host is using LAN:
                      • Disable Ethernet NIC
                  • From VirtualBox settings:
                    • Devices >> Network >> Network Settings >> Attached to and select Not attached.


                      Tooltip text above the combo box says: Selects how this virtual adapter is attached to the real network of the Host OS.

                      Virtual Box Manual says: "In this mode, VirtualBox reports to the guest that a network card is present, but that there is no connection -- as if no Ethernet cable was plugged into the card. This way it is possible to "pull" the virtual Ethernet cable and disrupt the connection, which can be useful to inform a guest operating system that no network connection is available and enforce a reconfiguration."

                      NOTE: My current VB installation (version 5.2.18 r124319) seems to have a problem with this option: setting "Not attached" makes guest freezing so I need to power off the machine (sending Shutdown signal does not help) but then booting the machine gets frozen as well.
                    • Go to Devices >> Network >> Network Settings... and un-check Cable Connected. 


                      I tried to find out more what this "Cable connected" actually means. This option is not mentioned in the VirtualBox Manual but there are some explanations on the forum:

                      Cable-connected means that you enable/disable the "physical" connection, be it wired or wireless. Like connecting/disconnecting a physical cable on a NIC card, or pulling the plug on your wireless router. It hoes nothing to do with a "cable", rather than "Is there anyone at the end of my connection?" kind of thing...

                      What the box does is control whether the emulated NIC is reporting that a link is established or not. You have to imagine that there's a cable between the emulated NIC that a guest OS sees and a NAT "router", a bridged adapter, or any other connection. The imaginary cable can always be plugged or unplugged independent of what's on the other end. This is very similar to having an Ethernet bridge which is "invisible" (has no IP address of its own) but is still connected with a cable that can be plugged in or not. Unplugging and re-plugging the virtual cable is most commonly used to force a guest OS to rediscover the network environment (typically re-request a DHCP lease). Whether the host is wired, wireless, or has no networking capabilities at all is not relevant.

                      The "Cable Connected" box controls whether the virtual CAT5/5e/6 network cable (or equivalent ability to communicate, in the case of wireless) is plugged or unplugged. (Sometimes, it's useful to virtualize a system which has a network adapter installed but nothing to talk to.)[source]

                      "Cable connected" does not do anything if virtual NIC is Not attached: connecting and disconnecting the cable would do nothing much. It would be like connecting and disconnected a physical cable to your physical Ethernet NIC while your router/server is switched off. [source]
                    • Previous action has a shortcut: Devices >> Network >> Connect Network Adapter

                  Wednesday, 21 March 2018

                  How to install Anaconda in OSX Terminal


                  What is Anaconda?
                  Anaconda distribution = Python + Data Science Python packages (like Scikit-learn, TensorFlow, SciPy) + conda package and virtual environment manager.

                  Download Anaconda installer for OSX here. I chose Python 3.6 version, 64-Bit Command-Line Installer. At the time of writing that was file: Anaconda3-5.1.0-MacOSX-x86_64.sh.

                  How to install Anaconda in OSX Terminal?

                  Output:


                  $ bash Anaconda3-5.1.0-MacOSX-x86_64.sh

                  Welcome to Anaconda3 5.1.0

                  In order to continue the installation process, please review the license
                  agreement.
                  Please, press ENTER to continue
                  >>>
                  ===================================
                  Anaconda End User License Agreement
                  ===================================

                  Copyright 2015, Anaconda, Inc.

                  All rights reserved under the 3-clause BSD License:

                  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

                  * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
                  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
                  * Neither the name of Anaconda, Inc. ("Anaconda, Inc.") nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

                  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANACONDA, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

                  Notice of Third Party Software Licenses
                  =======================================

                  Anaconda Distribution contains open source software packages from third parties. These are available on an "as is" basis and subject to their individual license agreements. These licenses are available in Anaconda Distribution or at http://docs.anaconda.com/anaconda/pkg-docs. Any binary packages of these third party tools you obtain via Anaconda Distribution are subject to their individual licenses as well as the Anaconda license. Anaconda, Inc. reserves the right to change which third party tools are provided in Anaconda Distribution.

                  In particular, Anaconda Distribution contains re-distributable, run-time, shared-library files from the Intel(TM) Math Kernel Library ("MKL binaries"). You are specifically authorized to use the MKL binaries with your installation of Anaconda Distribution. You are also authorized to redistribute the MKL binaries with Anaconda Distribution or in the conda package that contains them. Use and redistribution of the MKL binaries are subject to the licensing terms located at https://software.intel.com/en-us/license/intel-simplified-software-license. If needed, instructions for removing the MKL binaries after installation of Anaconda Distribution are available at http://www.anaconda.com.

                  Anaconda Distribution also contains cuDNN software binaries from NVIDIA Corporation ("cuDNN binaries"). You are specifically authorized to use the cuDNN binaries with your installation of Anaconda Distribution. You are also authorized to redistribute the cuDNN binaries with an Anaconda Distribution package that contains them. If needed, instructions for removing the cuDNN binaries after installation of Anaconda Distribution are available at http://www.anaconda.com.


                  Anaconda Distribution also contains Visual Studio Code software binaries from Microsoft Corporation ("VS Code"). You are specifically authorized to use VS Code with your installation of Anaconda Distribution. Use of VS Code is subject to the licensing terms located at https://code.visualstudio.com/License.

                  Cryptography Notice
                  ===================

                  This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See the Wassenaar Arrangement http://www.wassenaar.org/ for more information.

                  Anaconda, Inc. has self-classified this software as Export Commodity Control Number (ECCN) 5D992b, which includes mass market information security software using or performing cryptographic functions with asymmetric algorithms. No license is required for export of this software to non-embargoed countries. In addition, the Intel(TM) Math Kernel Library contained in Anaconda, Inc.'s software is classified by Intel(TM) as ECCN 5D992b with no license required for export to non-embargoed countries.

                  The following packages are included in this distribution that relate to cryptography:

                  openssl
                  The OpenSSL Project is a collaborative effort to develop a robust, commercial-grade, full-featured, and Open Source toolkit implementing the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols as well as a full-strength general purpose cryptography library.

                  pycrypto
                  A collection of both secure hash functions (such as SHA256 and RIPEMD160), and various encryption algorithms (AES, DES, RSA, ElGamal, etc.).

                  pyopenssl
                  A thin Python wrapper around (a subset of) the OpenSSL library.

                  kerberos (krb5, non-Windows platforms)
                  A network authentication protocol designed to provide strong authentication for client/server applications by using secret-key cryptography.

                  cryptography
                  A Python library which exposes cryptographic recipes and primitives.


                  Do you accept the license terms? [yes|no]
                  [no] >>> yes

                  Anaconda3 will now be installed into this location:
                  /Users/Bojan/anaconda3

                  - Press ENTER to confirm the location
                  - Press CTRL-C to abort the installation
                  - Or specify a different location below

                  [/Users/Bojan/anaconda3] >>>
                  PREFIX=/Users/Bojan/anaconda3
                  installing: python-3.6.4-hc167b69_1 ...
                  Python 3.6.4 :: Anaconda, Inc.
                  installing: bzip2-1.0.6-hd86a083_4 ...
                  installing: ca-certificates-2017.08.26-ha1e5d58_0 ...
                  installing: conda-env-2.6.0-h36134e3_0 ...
                  installing: intel-openmp-2018.0.0-h8158457_8 ...
                  installing: jbig-2.1-h4d881f8_0 ...
                  installing: jpeg-9b-he5867d9_2 ...
                  installing: libcxxabi-4.0.1-hebd6815_0 ...
                  installing: libgfortran-3.0.1-h93005f0_2 ...
                  installing: libiconv-1.15-hdd342a3_7 ...
                  installing: libsodium-1.0.15-hd9e47c5_0 ...
                  installing: lzo-2.10-h362108e_2 ...
                  installing: pandoc-1.19.2.1-ha5e8f32_1 ...
                  installing: tk-8.6.7-h35a86e2_3 ...
                  installing: unixodbc-2.3.4-h4cb4dde_1 ...
                  installing: xz-5.2.3-h0278029_2 ...
                  installing: yaml-0.1.7-hc338f04_2 ...
                  installing: zlib-1.2.11-hf3cbc9b_2 ...
                  installing: libcxx-4.0.1-h579ed51_0 ...
                  installing: libpng-1.6.34-he12f830_0 ...
                  installing: mkl-2018.0.1-hfbd8650_4 ...
                  installing: openssl-1.0.2n-hdbc3d79_0 ...
                  installing: expat-2.2.5-hb8e80ba_0 ...
                  installing: freetype-2.8-h12048fb_1 ...
                  installing: gmp-6.1.2-hb37e062_1 ...
                  installing: hdf5-1.10.1-ha036c08_1 ...
                  installing: icu-58.2-h4b95b61_1 ...
                  installing: libffi-3.2.1-h475c297_4 ...
                  installing: libssh2-1.8.0-h322a93b_4 ...
                  installing: libtiff-4.0.9-h0dac147_0 ...
                  installing: ncurses-6.0-hd04f020_2 ...
                  installing: pcre-8.41-hfb6ab37_1 ...
                  installing: zeromq-4.2.2-ha360ad0_2 ...
                  installing: gettext-0.19.8.1-h15daf44_3 ...
                  installing: libcurl-7.58.0-hf30b1f0_0 ...
                  installing: libedit-3.1-hb4e282d_0 ...
                  installing: libxml2-2.9.7-hab757c2_0 ...
                  installing: mpfr-3.1.5-h711e7fd_2 ...
                  installing: readline-7.0-hc1231fa_4 ...
                  installing: curl-7.58.0-ha441bb4_0 ...
                  installing: glib-2.53.6-h33f6a65_2 ...
                  installing: libxslt-1.1.32-hb819dd2_0 ...
                  installing: mpc-1.0.3-h7a72875_5 ...
                  installing: sqlite-3.22.0-h3efe00b_0 ...
                  installing: dbus-1.12.2-h5243cc1_1 ...
                  installing: qt-5.6.2-h9975529_14 ...
                  installing: alabaster-0.7.10-py36h174008c_0 ...
                  installing: appnope-0.1.0-py36hf537a9a_0 ...
                  installing: appscript-1.0.1-py36h9e71e49_1 ...
                  installing: asn1crypto-0.24.0-py36_0 ...
                  installing: attrs-17.4.0-py36_0 ...
                  installing: backports-1.0-py36ha3c1827_1 ...
                  installing: beautifulsoup4-4.6.0-py36h72d3c9f_1 ...
                  installing: bitarray-0.8.1-py36h1de35cc_1 ...
                  installing: boto-2.48.0-py36hdbc59ac_1 ...
                  installing: certifi-2018.1.18-py36_0 ...
                  installing: chardet-3.0.4-py36h96c241c_1 ...
                  installing: click-6.7-py36hec950be_0 ...
                  installing: cloudpickle-0.5.2-py36_1 ...
                  installing: colorama-0.3.9-py36hd29a30c_0 ...
                  installing: contextlib2-0.5.5-py36hd66e5e7_0 ...
                  installing: dask-core-0.16.1-py36_0 ...
                  installing: decorator-4.2.1-py36_0 ...
                  installing: docutils-0.14-py36hbfde631_0 ...
                  installing: entrypoints-0.2.3-py36hd81d71f_2 ...
                  installing: et_xmlfile-1.0.1-py36h1315bdc_0 ...
                  installing: fastcache-1.0.2-py36h1de35cc_2 ...
                  installing: filelock-2.0.13-py36hf9de95b_0 ...
                  installing: glob2-0.6-py36h94c9186_0 ...
                  installing: gmpy2-2.0.8-py36hf9c35bd_2 ...
                  installing: greenlet-0.4.12-py36hf09ba7b_0 ...
                  installing: heapdict-1.0.0-py36_2 ...
                  installing: idna-2.6-py36h8628d0a_1 ...
                  installing: imagesize-0.7.1-py36h3495948_0 ...
                  installing: ipython_genutils-0.2.0-py36h241746c_0 ...
                  installing: itsdangerous-0.24-py36h49fbb8d_1 ...
                  installing: jdcal-1.3-py36h1986823_0 ...
                  installing: lazy-object-proxy-1.3.1-py36h2fbbe47_0 ...
                  installing: llvmlite-0.21.0-py36hff739e7_0 ...
                  installing: locket-0.2.0-py36hca03003_1 ...
                  installing: lxml-4.1.1-py36hef8c89e_1 ...
                  installing: markupsafe-1.0-py36h3a1e703_1 ...
                  installing: mccabe-0.6.1-py36hdaeb55d_0 ...
                  installing: mistune-0.8.3-py36_0 ...
                  installing: mkl-service-1.1.2-py36h7ea6df4_4 ...
                  installing: mpmath-1.0.0-py36hf1b8295_2 ...
                  installing: msgpack-python-0.5.1-py36h04f5b5a_0 ...
                  installing: multipledispatch-0.4.9-py36hc5f92b5_0 ...
                  installing: numpy-1.14.0-py36h8a80b8c_1 ...
                  installing: olefile-0.45.1-py36_0 ...
                  installing: pandocfilters-1.4.2-py36h3b0b094_1 ...
                  installing: parso-0.1.1-py36hc90e01c_0 ...
                  installing: path.py-10.5-py36h7bcb313_0 ...
                  installing: pep8-1.7.1-py36_0 ...
                  installing: pickleshare-0.7.4-py36hf512f8e_0 ...
                  installing: pkginfo-1.4.1-py36h25bf955_0 ...
                  installing: pluggy-0.6.0-py36hb1d0581_0 ...
                  installing: ply-3.10-py36h10e714e_0 ...
                  installing: psutil-5.4.3-py36h1de35cc_0 ...
                  installing: ptyprocess-0.5.2-py36he6521c3_0 ...
                  installing: py-1.5.2-py36ha69170d_0 ...
                  installing: pycodestyle-2.3.1-py36h83e8646_0 ...
                  installing: pycosat-0.6.3-py36hee92d8f_0 ...
                  installing: pycparser-2.18-py36h724b2fc_1 ...
                  installing: pycrypto-2.6.1-py36h1de35cc_7 ...
                  installing: pycurl-7.43.0.1-py36hdbc3d79_0 ...
                  installing: pyodbc-4.0.22-py36h0a44026_0 ...
                  installing: pyparsing-2.2.0-py36hb281f35_0 ...
                  installing: pysocks-1.6.7-py36hfa33cec_1 ...
                  installing: python.app-2-py36h54569d5_7 ...
                  installing: pytz-2017.3-py36hf0bf824_0 ...
                  installing: pyyaml-3.12-py36h2ba1e63_1 ...
                  installing: pyzmq-16.0.3-py36he48b5ad_0 ...
                  installing: qtpy-1.3.1-py36h16bb863_0 ...
                  installing: rope-0.10.7-py36h68959ac_0 ...
                  installing: ruamel_yaml-0.15.35-py36h1de35cc_1 ...
                  installing: send2trash-1.4.2-py36_0 ...
                  installing: simplegeneric-0.8.1-py36_2 ...
                  installing: sip-4.18.1-py36h2824476_2 ...
                  installing: six-1.11.0-py36h0e22d5e_1 ...
                  installing: snowballstemmer-1.2.1-py36h6c7b616_0 ...
                  installing: sortedcontainers-1.5.9-py36_0 ...
                  installing: sphinxcontrib-1.0-py36h9364dc8_1 ...
                  installing: sqlalchemy-1.2.1-py36h1de35cc_0 ...
                  installing: tblib-1.3.2-py36hda67792_0 ...
                  installing: testpath-0.3.1-py36h625a49b_0 ...
                  installing: toolz-0.9.0-py36_0 ...
                  installing: tornado-4.5.3-py36_0 ...
                  installing: typing-3.6.2-py36haa2d9ef_0 ...
                  installing: unicodecsv-0.14.1-py36he531d66_0 ...
                  installing: wcwidth-0.1.7-py36h8c6ec74_0 ...
                  installing: webencodings-0.5.1-py36h3b9701d_1 ...
                  installing: werkzeug-0.14.1-py36_0 ...
                  installing: wrapt-1.10.11-py36hc29e774_0 ...
                  installing: xlrd-1.1.0-py36h336f4a2_1 ...
                  installing: xlsxwriter-1.0.2-py36h3736301_0 ...
                  installing: xlwt-1.2.0-py36h5ad1178_0 ...
                  installing: babel-2.5.3-py36_0 ...
                  installing: backports.shutil_get_terminal_size-1.0.0-py36hd7a2ee4_2 ...
                  installing: bottleneck-1.2.1-py36hbd380ad_0 ...
                  installing: cffi-1.11.4-py36h342bebf_0 ...
                  installing: conda-verify-2.0.0-py36he837df3_0 ...
                  installing: cycler-0.10.0-py36hfc81398_0 ...
                  installing: cytoolz-0.9.0-py36h1de35cc_0 ...
                  installing: h5py-2.7.1-py36h39cdac5_0 ...
                  installing: html5lib-1.0.1-py36h2f9c1c0_0 ...
                  installing: jedi-0.11.1-py36_0 ...
                  installing: networkx-2.1-py36_0 ...
                  installing: nltk-3.2.5-py36h1190bce_0 ...
                  installing: numba-0.36.2-np114py36hc2f221f_0 ...
                  installing: numexpr-2.6.4-py36habcfcfe_0 ...
                  installing: openpyxl-2.4.10-py36_0 ...
                  installing: packaging-16.8-py36he5e8135_0 ...
                  installing: partd-0.3.8-py36hf5c4cb8_0 ...
                  installing: pathlib2-2.3.0-py36h877a6d8_0 ...
                  installing: pexpect-4.3.1-py36_0 ...
                  installing: pillow-5.0.0-py36hfcce615_0 ...
                  installing: pyqt-5.6.0-py36he5c6137_6 ...
                  installing: python-dateutil-2.6.1-py36h86d2abb_1 ...
                  installing: pywavelets-0.5.2-py36h2710a04_0 ...
                  installing: qtawesome-0.4.4-py36h468c6fb_0 ...
                  installing: scipy-1.0.0-py36h1de22e9_0 ...
                  installing: setuptools-38.4.0-py36_0 ...
                  installing: singledispatch-3.4.0.3-py36hf20db9d_0 ...
                  installing: sortedcollections-0.5.3-py36he9c3ed6_0 ...
                  installing: sphinxcontrib-websupport-1.0.1-py36h92f4a7a_1 ...
                  installing: sympy-1.1.1-py36h7f3cf04_0 ...
                  installing: terminado-0.8.1-py36_1 ...
                  installing: traitlets-4.3.2-py36h65bd3ce_0 ...
                  installing: xlwings-0.11.5-py36_0 ...
                  installing: zict-0.1.3-py36h71da714_0 ...
                  installing: astroid-1.6.1-py36_0 ...
                  installing: bleach-2.1.2-py36_0 ...
                  installing: clyent-1.2.2-py36hae3ad88_0 ...
                  installing: cryptography-2.1.4-py36h842514c_0 ...
                  installing: cython-0.27.3-py36h6ecb376_0 ...
                  installing: datashape-0.5.4-py36hfb22df8_0 ...
                  installing: distributed-1.20.2-py36_0 ...
                  installing: get_terminal_size-1.0.0-h7520d66_0 ...
                  installing: gevent-1.2.2-py36ha70b9d6_0 ...
                  installing: imageio-2.2.0-py36h5e01289_0 ...
                  installing: isort-4.2.15-py36hceb2a01_0 ...
                  installing: jinja2-2.10-py36hd36f9c5_0 ...
                  installing: jsonschema-2.6.0-py36hb385e00_0 ...
                  installing: jupyter_core-4.4.0-py36h79cf704_0 ...
                  installing: matplotlib-2.1.2-py36h6d6146d_0 ...
                  installing: navigator-updater-0.1.0-py36h7aee5fb_0 ...
                  installing: nose-1.3.7-py36h73fae2b_2 ...
                  installing: pandas-0.22.0-py36h0a44026_0 ...
                  installing: patsy-0.5.0-py36_0 ...
                  installing: pyflakes-1.6.0-py36hea45e83_0 ...
                  installing: pygments-2.2.0-py36h240cd3f_0 ...
                  installing: pytables-3.4.2-py36hfbd7ab0_2 ...
                  installing: pytest-3.3.2-py36_0 ...
                  installing: scikit-learn-0.19.1-py36hffbff8c_0 ...
                  installing: wheel-0.30.0-py36h5eb2c71_1 ...
                  installing: astropy-2.0.3-py36h1de35cc_0 ...
                  installing: bkcharts-0.2-py36h073222e_0 ...
                  installing: bokeh-0.12.13-py36h2f9c1c0_0 ...
                  installing: flask-0.12.2-py36h5658096_0 ...
                  installing: jupyter_client-5.2.2-py36_0 ...
                  installing: nbformat-4.4.0-py36h827af21_0 ...
                  installing: pip-9.0.1-py36h1555ced_4 ...
                  installing: prompt_toolkit-1.0.15-py36haeda067_0 ...
                  installing: pylint-1.8.2-py36_0 ...
                  installing: pyopenssl-17.5.0-py36h51e4350_0 ...
                  installing: statsmodels-0.8.0-py36h9c68fc9_0 ...
                  installing: dask-0.16.1-py36_0 ...
                  installing: flask-cors-3.0.3-py36h7387b97_0 ...
                  installing: ipython-6.2.1-py36h3dda519_1 ...
                  installing: nbconvert-5.3.1-py36h810822e_0 ...
                  installing: seaborn-0.8.1-py36h595ecd9_0 ...
                  installing: urllib3-1.22-py36h68b9469_0 ...
                  installing: ipykernel-4.8.0-py36_0 ...
                  installing: odo-0.5.1-py36hc1af34a_0 ...
                  installing: requests-2.18.4-py36h4516966_1 ...
                  installing: scikit-image-0.13.1-py36h1de35cc_1 ...
                  installing: anaconda-client-1.6.9-py36_0 ...
                  installing: blaze-0.11.3-py36h02e7a37_0 ...
                  installing: jupyter_console-5.2.0-py36hccf5b1c_1 ...
                  installing: notebook-5.4.0-py36_0 ...
                  installing: qtconsole-4.3.1-py36hd96c0ff_0 ...
                  installing: sphinx-1.6.6-py36_0 ...
                  installing: anaconda-project-0.8.2-py36h9ee5d53_0 ...
                  installing: jupyterlab_launcher-0.10.2-py36_0 ...
                  installing: numpydoc-0.7.0-py36he54d08e_0 ...
                  installing: widgetsnbextension-3.1.0-py36_0 ...
                  installing: anaconda-navigator-1.7.0-py36_0 ...
                  installing: ipywidgets-7.1.1-py36_0 ...
                  installing: jupyterlab-0.31.5-py36_0 ...
                  installing: spyder-3.2.6-py36_0 ...
                  installing: _ipyw_jlab_nb_ext_conf-0.1.0-py36h2fc01ae_0 ...
                  installing: jupyter-1.0.0-py36_4 ...
                  installing: anaconda-5.1.0-py36_2 ...
                  installing: conda-4.4.10-py36_0 ...
                  installing: conda-build-3.4.1-py36_0 ...
                  installation finished.
                  Do you wish the installer to prepend the Anaconda3 install location
                  to PATH in your /Users/Bojan/.bash_profile ? [yes|no]
                  [yes] >>> yes

                  Appending source /Users/Bojan/anaconda3/bin/activate in
                  newly created /Users/Bojan/.bash_profile

                  For this change to become active, you have to open a new terminal.

                  Thank you for installing Anaconda3!

                  ===========================================================================

                  Anaconda is partnered with Microsoft! Microsoft VSCode is a streamlined
                  code editor with support for development operations like debugging, task
                  running and version control.

                  To install Visual Studio Code, you will need:
                  - Internet connectivity

                  Visual Studio Code License: https://code.visualstudio.com/license

                  Do you wish to proceed with the installation of Microsoft VSCode? [yes|no]
                  >>> no



                  To verify that installation was successful, we can open Anaconda Prompt by opening the Terminal in /bin directory and run conda's activate script: source activate <envname>.

                  Before that let's check the list of available environments (environment names):


                  /Users/Bojan/anaconda3/bin$ conda info --envs
                  # conda environments:
                  #
                  base * /Users/Bojan/anaconda3



                  To activate Anaconda go to <path_to>/anaconda3/bin and execute:


                  $ source activate base
                  (base) $



                  Note the (base) at the beginning of the command line prompt.

                  We can now start Python interpreter environment:


                  (base) $ python
                  Python 3.6.4 |Anaconda, Inc.| (default, Jan 16 2018, 12:04:33)
                  [GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
                  Type "help", "copyright", "credits" or "license" for more information.
                  >>>