text:
package br.com.objectos.way.flat;

import static br.com.objectos.way.assertion.Assertion.assertThat;
import static br.com.objectos.way.flat.LocalDatePattern.DDMMYY;
import static br.com.objectos.way.flat.LocalDatePattern.YYYYMMDD;
import static br.com.objectos.way.flat.LocalDateTimePattern.YYYYMMDD_HHMM;

import br.com.objectos.way.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.testng.annotations.Test;

/**
 * @author marcio.endo@objectos.com.br (Marcio Endo)
 */
public class FlatReaderTest {

  @Test
  public void accept() throws FlatException {
    FlatReaderVisitor visitor = new SimpleFlatReaderVisitor();
    try (FlatReader reader = FlatReader.ofString("o7whatever\nisljljlfj\ncox90180\nol080932")) {
      reader.accept(visitor);
    }
    assertThat(visitor).hasToString("o7iscool");
  }

  @Test
  public void booleanValue() {
    try (FlatReader reader = FlatReader.ofString("YNxYN")) {
      assertThat(reader.booleanValue("Y", "N")).isTrue();
      assertThat(reader.booleanValue("Y", "N")).isFalse();
      reader.text(1);
      assertThat(reader.booleanValue("Y", "N")).isTrue();
      assertThat(reader.booleanValue("Y", "N")).isFalse();
    }
  }

  @Test
  public void custom() {
    try (FlatReader reader = FlatReader.ofString("1123")) {
      assertThat(reader.custom(4, LocalTimeFormatter.get())).equalTo(LocalTime.of(11, 23));
    }
  }

  @Test
  public void decimal() {
    try (FlatReader reader = FlatReader.ofString("xxxxx     yyyyyzzzzz67890")) {
      assert reader.decimal(5, 2, ComparisonOperator.EQ.value(0d), "xxxxx") == 0d;
      assert reader.decimal(5, 2, ComparisonOperator.EQ.value(0d), "     ") == 0d;
      assert reader.decimal(5, 2, ComparisonOperator.GT.value(0d), "yyyyy") == 1d;
      assert reader.decimal(5, 2, ComparisonOperator.LT.value(10d), "zzzzz") == 9d;
      assert reader.decimal(5, 2, ComparisonOperator.EQ.value(0d), "-----") == 678.9;
    }
  }

  @Test
  public void decimal_nan() {
    try (FlatReader reader = FlatReader.ofString("12345     67890")) {
      assert reader.decimal(5, 2) == 123.45;
      assert Double.isNaN(reader.decimal(5, 2));
      assert reader.decimal(5, 2) == 678.9;
    }
  }

  @Test
  public void flatEnum() {
    try (FlatReader reader = FlatReader.ofString("DM0CB1SDxptoHS")) {
      assertThat(reader.flatEnum(Suits.class, 2)).equalTo(Suits.DIAMONDS);
      assert reader.integer(1) == 0;
      assertThat(reader.flatEnum(Suits.class, 2)).equalTo(Suits.CLUBS);
      assert reader.integer(1) == 1;
      assertThat(reader.flatEnum(Suits.class, 2)).equalTo(Suits.SPADES);
      assertThat(reader.skip(1)
          .skip(2)
          .skip(1)
          .flatEnum(Suits.class, 2)).equalTo(Suits.HEARTS);
    }
  }

  @Test
  public void integer() {
    try (FlatReader reader = FlatReader.ofString("  12300456xxx   yyy123")) {
      assert reader.integer(5) == 123;
      assert reader.integer(5) == 456;
      assert reader.integer(3, ComparisonOperator.EQ.value(0), "xxx") == 0;
      assert reader.integer(3, ComparisonOperator.EQ.value(0), "   ") == 0;
      assert reader.integer(3, ComparisonOperator.GT.value(0), "yyy") == 1d;
      assert reader.integer(3, ComparisonOperator.EQ.value(0), "xxx") == 123;
    }
  }

  @Test
  public void localDate() {
    try (FlatReader reader = FlatReader.ofString("20141225x99999999x20141225x      x251214")) {
      LocalDate dt = LocalDate.of(2014, 12, 25);
      assertThat(reader.localDate(YYYYMMDD)).equalTo(dt);
      reader.skip(1);
      assertThat(reader.localDate(YYYYMMDD, "99999999")).equalTo(Optional.empty());
      reader.skip(1);
      assertThat(reader.localDate(YYYYMMDD, "99999999")).equalTo(Optional.of(dt));
      reader.skip(1);
      assertThat(reader.localDate(DDMMYY, "      ")).equalTo(Optional.empty());
      reader.skip(1);
      assertThat(reader.localDate(DDMMYY, "      ")).equalTo(Optional.of(dt));
    }
  }

  @Test
  public void localDateTime() {
    try (FlatReader reader = FlatReader.ofString("201412251403x999999999999x201412251403")) {
      LocalDateTime dt = LocalDateTime.of(2014, 12, 25, 14, 3);
      assertThat(reader.localDateTime(YYYYMMDD_HHMM)).equalTo(dt);
      reader.skip(1);
      assertThat(reader.localDateTime(YYYYMMDD_HHMM, "999999999999")).equalTo(Optional.empty());
      reader.skip(1);
      assertThat(reader.localDateTime(YYYYMMDD_HHMM, "999999999999")).equalTo(Optional.of(dt));
    }
  }

  @Test
  public void longValue() {
    try (FlatReader reader = FlatReader.ofString("  12300456")) {
      assert reader.longValue(5) == 123l;
      assert reader.longValue(5) == 456l;
    }
  }

  @Test
  public void peek() {
    try (FlatReader reader = FlatReader.ofString("1234")) {
      assertThat(reader.peek(1)).equalTo("1");
      assertThat(reader.peek(2)).equalTo("12");
      assert reader.integer(1) == 1;
      assert reader.integer(1) == 2;
      assertThat(reader.peek(2)).equalTo("34");
      assertThat(reader.text(2)).equalTo("34");
      assertThat(reader.peek(2)).equalTo("");
    }
  }

  @Test
  public void simple() throws IOException {
    try (FlatReader reader = openReader("simple")) {
      simpleAssertion(reader);
    }
  }

  @Test
  public void simple_smallBuffer() throws IOException {
    try (FlatReader reader = openReader("simple", 2)) {
      simpleAssertion(reader);
    }
  }

  @Test
  public void stream_fabric271() throws IOException {
    try (FlatReader reader = openReader("fabric-271")) {
      List<Fabric271> res = reader.stream()
          .map(Fabric271::parse)
          .collect(Collectors.toList());
      assertThat(res).hasSize(1);
    }
  }

  @Test
  public void text_mustBeTrimmed() {
    try (FlatReader reader = FlatReader.ofString("abc  123")) {
      assertThat(reader.text(5)).equalTo("abc");
      assert reader.integer(3) == 123;
    }
  }

  private void simpleAssertion(FlatReader reader) {
    List<Simple> res = reader.stream()
        .map(Simple::parse)
        .collect(Collectors.toList());
    assertThat(res).equalTo(Simple.abc(), Simple.xyz());
  }

  private InputStream openStream(String filename) throws IOException {
    return File.ofResourceNamed("/flat/" + filename + ".txt").openStream();
  }

  private FlatReader openReader(String filename) throws IOException {
    return FlatReader.open(openStream(filename));
  }

  private FlatReader openReader(String filename, int size) throws IOException {
    return FlatReader.open(openStream(filename), size);
  }

}


text:
<?php

namespace Croogo\Contacts\Model;

use App\Model\AppModel;

/**
 * Contacts App Model
 *
 * @category Contacts.Model
 * @package  Croogo.Contacts.Model
 * @version  1.0
 * @author   Fahad Ibnay Heylaal <contact@fahad19.com>
 * @license  http://www.opensource.org/licenses/mit-license.php The MIT License
 * @link     http://www.croogo.org
 */
class ContactsAppModel extends AppModel
{

}

redpajama_set_name: RedPajamaGithub


text:
package com.alexdupre.shapeshift.models

import play.api.libs.json._

case class Market(input: Coin, output: Coin) {
  override def toString = s"${input}_${output}"
}

object Market {

  implicit val format = new Format[Market] {
    override def reads(json: JsValue): JsResult[Market] = json match {
      case JsString(s) =>
        s.split("_") match {
          case Array(i, o) => JsSuccess(Market(i, o))
          case _           => JsError("error.expected.market")
        }
      case _ => JsError("error.expected.market")
    }
    override def writes(o: Market): JsValue = JsString(o.toString)
  }

}


text:
from flask import flash, redirect, render_template, url_for
from flask_login import login_required, login_user, logout_user

from app.auth import auth
from app.auth.forms import LoginForm, RegistrationForm
from app import db
from app.models import Usuario

@auth.route('/register', methods=['GET', 'POST'])
def register():
    """
    Agrega el usuario a la base de datos
    -- Actualmente todas las funciones están hechas para administradores
    -- y solo se puede poner la marca de admin por base de datos
    -- está creado en el modelo el flag de editor para dar permiso a
    -- todo excepto a datos de seguimiento de gente por privacidad
    """
    form = RegistrationForm()
    if form.validate_on_submit():
        usuario = Usuario(email=form.email.data,
                          username=form.username.data,
                          first_name=form.first_name.data,
                          last_name=form.last_name.data,
                          password=form.password.data)

        try:
            # agregar usuario a la BD
            db.session.add(usuario)
            db.session.commit()
            flash(u'Se ha creado correctamente el usuario.', 'success')
        except Exception as e:
            # error
            flash('Error:', e, 'danger')

        # redirect to the login page
        return redirect(url_for('auth.login'))

    # load registration template
    return render_template('auth/register.html', form=form)

@auth.route('/login', methods=['GET', 'POST'])
def login():
    """
    Gestiona las solicitudes de login
    Loguea un usuario
    """
    form = LoginForm()
    if form.validate_on_submit():

        # check whether user exists in the database and whether
        # the password entered matches the password in the database
        usuario = Usuario.query.filter_by(email=form.email.data).first()
        if usuario is not None and usuario.verify_password(form.password.data):
            login_user(usuario)
            # redirect to the appropriate dashboard page
            return redirect(url_for('home.hub'))

        # when login details are incorrect
        else:
            flash(u'Email o contraseña invalidos.', 'danger')

    # load login template
    return render_template('auth/login.html', form=form)

@auth.route('/logout')
@login_required
def logout():
    """
    Gestiona los logouts
    """
    logout_user()
    flash(u'Has salido correctamente.', 'success')

    # redirect to the login page
    return redirect(url_for('auth.login'))


text:
define([
	"knockout",
    "async!http://maps.google.com/maps/api/js?sensor=true"
], function (ko) {
        //The data object will be the API response for the
        //JSONP data call.

        // found in js fiddle how to create a map with knockout http://jsfiddle.net/t9wcC/
        // Point object for storing cityname , lat, lon + markers with events
        function Point (name, lat, lon, coat_of_arms, mapObj ) {
            var self = this;
            this.name = name;
            this.lat = ko.observable(lat);
            this.lon = ko.observable(lon);

            var marker = new google.maps.Marker({
                position: new google.maps.LatLng(lat, lon),
                title: name,
                map: mapObj,
                icon: coat_of_arms,
                animation: google.maps.Animation.DROP,
                draggable: false
               });

            // set id to reference it for adding customEvent
            // marker.set("id", marker.title);

            // remove marker objects
            self.removeMarker = function () {
                marker.setMap(null);
                marker = null;
            };

            // get Map
            self.getMap = function () {
                var map = marker.map;
                return map;
            };

            google.maps.event.addListener(marker, 'click', function() {
                // get current clicked title and send it to wikipedia
                var title = marker.title;

                //create custom event to subscript to (i could not find any knockout specific way to do so)
                var newCity = document.createEvent("CustomEvent");
                newCity.initCustomEvent("getTitle", true, true, {
                        title : title
                });
                // dispatch custom event, to be listened to by Wikipedia Model
                window.dispatchEvent(newCity);
           }.bind(this));
        }

        return Point;

    }
);


text:
import unittest

from recipe_scrapers import (
    NoSchemaFoundInWildMode,
    WebsiteNotImplementedError,
    scrape_me,
)

class TestExceptions(unittest.TestCase):
    def test_WebsiteNotImplementedError(self):
        with self.assertRaises(WebsiteNotImplementedError):
            scrape_me("https://example.com/recipe")

    def test_NoSchemaFoundInWildMode(self):
        exception = NoSchemaFoundInWildMode("example.com")

        self.assertEqual(exception.url, "example.com")
        self.assertEqual(exception.message, "No Recipe Schema found at example.com.")


text:
package com.reason.ide.console.rescript;

import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.*;
import com.reason.comp.*;
import com.reason.comp.rescript.*;
import com.reason.ide.console.*;
import icons.*;
import org.jetbrains.annotations.*;

public class RescriptResetAction extends CompilerAction {
    public RescriptResetAction() {
        super("Clean", "Clean", ORIcons.RESET);
    }

    @Override
    public void update(@NotNull AnActionEvent e) {
        Project project = e.getProject();
        ResCompiler compiler = project == null ? null : project.getService(ResCompiler.class);
        if (compiler != null) {
            e.getPresentation().setEnabled(!compiler.isRunning());
        }
    }

    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {
        Project project = e.getProject();
        ResCompiler compiler = project == null ? null : project.getService(ResCompiler.class);
        if (compiler != null) {
            doAction(project, CliType.Rescript.CLEAN, (_void) -> e.getPresentation().setEnabled(!compiler.isRunning()));
        }
    }
}


text:
<?php
/**
 * @package Habari
 *
 */

/**
 * Create an XMLRPC client connection
 *
 * To Use:
 *
 * // Create the object using the XMLRPC entrypoint and scope.
 * $rpc= new XMLRPCClient('http://rpc.pingomatic.com', 'weblogUpdates');
 * // Make a weblogUpdates.ping call on the client.
 * $result= $rpc->ping('Blog name', 'http://example.com');
 *
 * // Change the scope on the existing client object.
 * $rpc->set_scope('system');
 * // Make a system.listMethods call on the client.
 * $methods= $rpc->listMethods();
 *
 *
 * @todo Handle XMLRPC fault results by returning some error value.
 */
class XMLRPCClient
{
	private $entrypoint;
	private $scope = 'system';

	/**
	 * Create the XMLRPCClient
	 *
	 * @param string $xmlrpc_entrypoint The entrypoint of the remote server
	 */
	public function __construct($xmlrpc_entrypoint, $scope = null)
	{
		$this->entrypoint = $xmlrpc_entrypoint;
		if(isset($scope)) {
			$this->scope = $scope;
		}
	}

	/**
	 * Set the scope of any subsequent function calls
	 * The default scope is 'system'.
	 *
	 * @param string $scope The scope to use
	 */
	public function set_scope($scope)
	{
		$this->scope = $scope;
	}

	/**
	 * Allow method overloading for this class.
	 * This method allows any method name to be called on this object.  The method
	 * called is the method called via RPC, within the scope defined in $this->scope.
	 *
	 * @param string $fname The function name to call
	 * @param array $args An array of arguments that were called with the function
	 * @return array The result array
	 */
	public function __call($fname, $args)
	{
		if($this->scope != '') {
			$rpc_method = "{$this->scope}.{$fname}";
		}
		else {
			$rpc_method = $fname;
		}

		$rpx = new SimpleXMLElement('<methodCall/>');
		$rpx->addChild('methodName', $rpc_method);
		if(count($args) > 0) {
			$params = $rpx->addchild('params');
			foreach($args as $arg) {
				$param = $params->addchild('param');
				XMLRPCUtils::encode_arg($param, $arg);
			}
		}

		$request = new RemoteRequest($this->entrypoint, 'POST');
		$request->add_header('Content-Type: text/xml');
		$request->set_body($rpx->asXML());

		$request->execute();

		if ( $request->executed() ) {
			$response = $request->get_response_body();
			$enc = mb_detect_encoding($response);
			$responseutf8 = mb_convert_encoding($response, 'UTF-8', $enc);
			try {
				$bit = ini_get('error_reporting');
				error_reporting($bit && !E_WARNING);
				$responsexml = new SimpleXMLElement($responseutf8);
				error_reporting($bit);
				$tmp = $responsexml->xpath('//params/param/value');
				if (!$responsestruct = reset($tmp)) {
					$tmp = $responsexml->xpath('//fault/value');
					if (!$responsestruct = reset($tmp)) {
						throw new Exception(_t('Invalid XML response.'));
					}
				}
				return XMLRPCUtils::decode_args($responsestruct);
			}
			catch (Exception $e){
				//Utils::debug($response, $e);
				error_reporting($bit);
				return false;
			}
		}
	}

	/**
	 * Allow scoped functions to be called in shorthand
	 * Example:
	 *
	 * // Create the XMLRPC object
	 * $rpc= new XMLRPCClient('http://rpc.pingomatic.com');
	 * // Call weblogUpdates.ping RPC call
	 * $rpc->weblogUpdates->ping('Blog name', 'http://example.com');
	 *
	 *
	 * @param string $scope The scope to set this object to.
	 * @return XMLRPCClient This object instance
	 **/
	public function __get($scope)
	{
		$this->set_scope($scope);
		return $this;
	}

	/**
	 * Convenience method to create a new XMLRPCClient object
	 * Example:
	 *
	 * XMLRPCClient::open('http://rpc.pingomatic.com')->weblogUpdates->ping('Blog name', 'http://example.com');
	 *
	 * @param string $xmlrpc_entrypoint The entrypoint of the remote server
	 * @return XMLRPCClient The created client object
	 **/
	public static function open( $xmlrpc_entrypoint )
	{
		return new XMLRPCClient( $xmlrpc_entrypoint );
	}

}

?>


text:
layout: post
title: "Regular Expressions"
date: "July 25, 2015"
categories: Software
tags: Wrangling
---

* TOC
{:toc}

# Regex

To search for an exact pattern, simply search for the pattern.

{% highlight r %}
# detect the name Charlie
x %>% str_detect("Charlie")
{% endhighlight %}

## Character Classes

Rather than searching for a specific character, the regex engine can search for a class of characters. There are three classes or groups of characters in which there are special regex expressions for.

pattern | matches
--------|---------
`\d`      | digit character
`\w`      | word character (letter, digit, '_')
`\s`      | space character (space, tab, new line)

## Metacharacters

To allow for greater flexibility, there are a number of metacharacters that convey special meaning in regex pattern matching.

pattern | matches
--------|-------------
`.`       | any single character
`\|`       | or (matches preceding or succeding string)
`(...)`   | used for backreference
`[...]`   | customized group of characters
`{...}`   | repetition quantifier
`*`      | matches previous character 0 or more times
`+`       | matches previous character 1 or more times
`?`     | matches previous character 0 or 1 times
`^`      | matches at the beginning of a string
`$`       | matches at the end of a string

Here are further specifications on several of the characters listed above.

**[...]**

`[...]` can be used to select from a customized group of characters. To specify characters, list them out inside the brackets. To not match a customized group of characters, add a negation character like so: `[^...]`.

To specifically search for only uppercase letters, use `[A-Z]`; for lowercase letters `[a-z]`. To search for both uppercase and lowercase letters, use `[A-Za-z]`.

**{...}**

To match a character (or a group of characters) multiple times, repetition quantifiers come in handy: `{...}`, `*`, or `+`.

pattern | matches
--------|---------
`{n}`     | matches previous character exactly n times
`{n,}`    | matches previous character n or more times
`{n, m}`  | matches previous character n to m times
`*`       | matches previous character 0 or more times
`+`       | matches previous character 1 or more times
`?`       | matches previous character 0 or 1 times

**(...)**

The metacharacters `(...)` are very useful in replacing strings. When wrapped around a string, it "remembers" the matched pattern. Then when specifying the replacement, it allows users to refer to the matched pattern by using `\n` where n refers to the nth wrapped expression.

We can look at this example in R:

{% highlight r %}
x <- "Flintstone,Fred  *111-222-3333 fflinstone@gmail.com crane operator"
pattern <- "(\\w+)[, ]+(\\w+)\\s+([\\d-*]+)\\s+([\\w@.]+)\\s+(.+)"
## 1st () references the last name
## 2nd () references the first name
## 3rd () references the phone number
## 4th () references the email address
## 5th () references the person's occupation
x %>% str_replace(pattern = pattern, replacement = "\\2 \\1 is a \\5")
{% endhighlight %}

{% highlight text %}
## [1] "Fred Flintstone is a crane operator"
{% endhighlight %}

**^ and $**

The metacharacters `^` and `$` are used to match patterns at specific positions of a string.

{% highlight r %}
grep "^\d"
grep "\w$"
{% endhighlight %}

**Using Metacharacters as Normal Characters**

To use these characters as regular characters, precede the character with escape characters or wrap then in square brackets. For example, to search for the character `+`, type `\+` or `[+]` into the search pattern string.

# Implementation

## In R

In order to match these special regex expressions in R, type the backslashes twice, like so:

{% highlight r %}
# count the number of space characters in each string of x
x %>% str_count("\\s")
{% endhighlight %}

Function | Description
---------|--------------
`str_to_upper()`, `str_to_lower()`, `str_to_title()` | change string case
`str_dup()` | duplicate and concatenate character vector
`paste()` | join multiple strings into single string
`nchar()` | number of characters
`str_count()` | count number of matches in string
`str_sub()` | extract and replace substrings
`str_subset()` | keep strings matching a pattern
`str_detect()` | detect presence of a pattern
`str_locate()`, `str_locate_all()` | locate positions of patterns
`str_extract()`, `str_extract_all()` | extract pieces that match pattern
`str_match()`, `str_match_all()` | extract matched groups
`str_replace()`, `str_replace_all()` | replace matched patterns
`str_replace_na()` | replace NA
`str_split()` | split by pattern
`str_trim()` | trim white space
`str_pad()` | pad string
`str_wrap()` | wrap strings into formatted paragraphs
`word()` | extract words from sentence

## In SAS

Additional metacharacters for SAS

* `%` substitute for 0 or more characters

Function | Description
---------|---------------
`lengthn()` | length of string
`upcase()`, `lowcase()`, `propcase()` | change string case
`compbl()` | combines >1 blank to 1 blank
`compress()` | removes specified character/char class
`cat()` | concatenates characters
`cats()` | strips leading & trailing blanks before joining
`catx()` | concatenates characters, 1st arg is separator
`left()`, `trim()`, `strip()` | removes blanks from L, R, both sides
`find()` | finds characters
`findc()` | finds individual characters
`findw()` | finds words
`anyalnum()`, `anyalpha()`, `anydigit()`, `anyspace()` | finds any of listed; can also replace any with not
`substr()` | takes substring
`scan()` | scans string
`compare()` | compares strings
`translate()`| translates one to another

## In SQL

Regular expressions can be specified in SQL using the `where` clause.

Here is an example of selecting names that start with vowels.

{% highlight r %}
select * from table
where name like '[aeiou]%'
;
{% endhighlight %}

The metacharacters that can be used with SQL are a little different than those listed above.

* `[...]` brackets, same as above (including negation)
* `%` substitute for 0 or more characters
* `_` substitute for a single character

## In Python

Function | Description
---------|--------------
`len()` | length of strings
`strip()`, `rstrip()`, `lstrip()` | remove trailing white space
`lower()`, `upper()`, `capitalize()` | change string case
`translate()` | map from one thing to another
`startswith()`, `endswith()` | checks for string at location
`isalpha()`, `isdigit()`, `isalnum()`, `isspace()` | tests string for type
`split()` | splits a string
`match()` | whether there is a match
`extract()` | extracts match
`findall()` | finds all matches in string
`replace()` | replace occurance of specificed string
`contains()` | searchs for pattern inside string
`count()` | counts occurances of specified string
`pad()` | adds white space
`join()`, `cat()` | combines strings
`cat()` | concatenates strings
`repeat()` | repeats values

The class `pd.Series.str` allows for vectorized string operations.


text:
from __future__ import unicode_literals

from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('argus', '0014_astu_is_online'),
        ('net', '0020_job_ne_ids'),
    ]

    operations = [
        migrations.RemoveField(
            model_name='job',
            name='ne',
        ),
        migrations.RemoveField(
            model_name='job',
            name='ne_ids',
        ),
        migrations.AddField(
            model_name='job',
            name='ne_ids',
            field=models.ManyToManyField(to='argus.ASTU'),
        ),
    ]


text:
module.exports = {
  description: "",
  ns: "react-material-ui",
  type: "ReactNode",
  dependencies: {
    npm: {
      "material-ui/svg-icons/action/perm-phone-msg": require('material-ui/svg-icons/action/perm-phone-msg')
    }
  },
  name: "ActionPermPhoneMsg",
  ports: {
    input: {},
    output: {
      component: {
        title: "ActionPermPhoneMsg",
        type: "Component"
      }
    }
  }
}


text:
MemberCollecter
===============

Calls Meetup API and EventBrite API to create a single list of members from both services to be exported into Excel. (For now)


text:
NWCPE is the preeminent Performance Excellence thought leader in the Pacific Northwest

NWCPE founders and leaders are distinguished contributors to successful process optimization for diverse industries. They are committed to supporting their clients with substantive and practical approaches. NWCPE leaders are concerned first and foremost with your and your organization's success. NWCPE offers training and certification in collaboration with recognized institutions of higher learning including Portland State University in Portland, OR, Chemeketa Center for Business and Industry in Salem, OR and the Universidad de San Francisco de Quito in Quito, Ecuador, via stand-alone open-registration NWCPE workshops and in-house customized training programs.

NWCPE leaders practice what they preach. They offer turn-key transformational and ad hoc consulting, training and coaching to support your organization's continuous improvement initiatives positioning you to become the leader in your industry.

 Invite us in for a free Lunch and Learn session to sample how it works. Support is available worldwide and in English and Spanish. In addition, NWCPE offers customized certificate courses and their associated stand-alone workshops on-site, one on one coaching, or consulting for a specific project. We offer those services as well, so invite us to come in for a free "lunch and learn" hour to learn how you can transform your organization and become best in class.

 "We cannot solve our problems with the same kind of thinking we used to create them"

- Albert Einstein

Consulting Services

In addition to our courses, we provide on-site training, consulting, and coaching to individuals and teams

Learn More

Education & Certifications

Learn more about our workshops and certification programs in Lean and Six Sigma

Learn More

About Us

Learn more about our experienced team of performance excellence instructors

Learn More

Upcoming Events

We hold over 60 workshops and certification courses throughout the year in collaboration with Portland State University Center for Executive and Professional Education and independently. Here's a list of our events in the next month:

Introduction to statistical methods

Learn More

Upcoming Events

We hold over 60 workshops and certification courses throughout the year in collaboration with Portland State University Center for Executive and Professional Education and independently. Here's a list of our events in the next month:

Introduction to statistical methods

Register before March 29th, 2016

Register

Certifications

Certifications in Lean, Six Sigma, Lean Six Sigma, and Statistical Process Control are available.

Six Sigma Yellow Belt Certification Requirements:

Completion of Six Sigma Yellow Belt designated workshops

Completion of a Yellow Belt qualification exam

Completion of project incorporating methodologies introduced in the Yellow Belt curriculum

Six Sigma Green Belt Certification Requirements

Completion of Six Sigma Green Belt designated workshops

Completion of the Six Sigma Green Belt exam

Completion of a project incorporating methodologies introduced in the Green Belt curriculum

Six Sigma Black Belt Certification:

Completion of Six Sigma Black Belt designated workshops

Completion of the Six Sigma Black Belt exam

Completion of a project incorporating methodologies learned in the Six Sigma Black Belt curriculum

Statistical Process Control (SPC) Professional Certification:

Completion of SPC designated workshops

Completion of the SPC exam

Completion of a project incorporating methodologies learned in the SPC curriculum

Learn more about our workshops and certification programs in Lean and Six Sigma

Learn More

Testimonials

"The principal product is – Value! The engineers are talented, conscientious and thorough. The methods work. We met and exceeded performance in key functional areas in less than one year what others haven't accomplished in six."

- Dr. Lisa LangFormer Senior Manager of Metal R&D and QualityAnheuser-Busch

Workshops

A hallmark of NWCPE workshops is the approach of creating experiences with simulations and activities for participants so that they learn by the hearing, seeing, doing, summarizing and planning for application to their everyday work lives.

You will find workshops to introduce you to a world of continual improvement and give you the background and perspective to make the best decisions for you or your organization's paths to process excellence.

You will find workshops to help you learn or reinforce the fundamental concepts and application of basic tools essential to get you there.

You will find workshops that will take you to next level by introducing you to the most powerful and advanced tools and methods available today.

Learn more about our workshops and certification programs in Lean and Six Sigma

Learn More

Onsite training and coaching

Effective consulting and coaching takes on many forms but is always based on your organization's goals, culture, and level of process maturity.

The support can be ad hoc or a complete and comprehensive approach to transformational change and continual improvement. NWCPE provides in-house training, consulting, and one-on-one coaching.

You benefit from our more than 35 years of experience in small, medium, and very large organizations in industries as diverse as plastics molding, high tech, food and beverage, medical device manufacturing, healthcare, IT, and government agencies. We know how to manage both the common denominators and differences in organizations. NWCPE is agile and effective at adapting training and support to assure its relevance to you and your organization.

In addition to our courses, we provide on-site training and coaching to individuals and teams

Learn More


text:
from __future__ import unicode_literals

from django.db import migrations

def forwards(apps, schema_editor):

    try:
        apps.get_model('accounts', 'AccountDB')
    except LookupError:
        return
    AccountDB = apps.get_model('accounts', 'AccountDB')
    ScriptDB = apps.get_model('scripts', 'ScriptDB')

    for script in ScriptDB.objects.all():
        account = script.db_account
        if account:
            account = AccountDB.objects.get(id=account.id)
            script.db_account = account
            script.save(update_fields=['db_account'])

class Migration(migrations.Migration):

    dependencies = [
        ('scripts', '0009_scriptdb_db_account'),
    ]

    operations = [
        migrations.RunPython(forwards)
    ]


text:
class ApplicationHelper::Toolbar::CloudVolumeSnapshotCenter < ApplicationHelper::Toolbar::Basic
  button_group('cloud_volume_snapshot_policy', [
    select(
      :cloud_volume_snapshot_policy_choice,
      'fa fa-shield fa-lg',
      t = N_('Policy'),
      t,
      :items => [
        button(
          :cloud_volume_snapshot_tag,
          'pficon pficon-edit fa-lg',
          N_('Edit tags for this Cloud Volume Snapshot'),
          N_('Edit Tags')),
      ]
    ),
  ])
end


text:
'use strict';

import { IContextListener } from './../icontext';
import { IStackTraceContext } from './istackTraceContext';

export interface IStackTraceListener extends IContextListener<IStackTraceContext> {

}


text:
            Admin
            Contact Us


text:
<?php

if ( ! defined('BASEPATH')) exit('No direct script access allowed');

?>

<?php if($this->session->flashdata('msg') != ''){?>

			<button class="close" data-dismiss="alert"> × </button>

			<?php echo $this->session->flashdata('msg');?>

<?php }?>
<?php if($this->session->flashdata('error') != ''){?>

			<button class="close" data-dismiss="alert"> × </button>

			<?php echo $this->session->flashdata('error');?>

<?php }?>

		<?php echo lang('orders_admin_orders_title'); ?>

	<?php
	$attribute = array('class' => 'form-orders', 'id' => 'form-orders');
	echo form_open(site_url('admin/orders'), $attribute);
	?>

						<?php $option_s = array(''=>  lang('all'), '5'=>5, '10'=>10, '15'=>15, '20'=>20, '25'=>25, '100'=>100); ?>
						<?php echo form_dropdown('per_page', $option_s, $per_page, 'class="form-control" id="per_page"'); ?>

						<?php
							$search = array('name' => 'search', 'id' => 'search', 'class' => 'form-control datepicker', 'placeholder' => lang('orders_admin_search_place'), 'autocomplete'=>'off', 'value'=>$search);
							echo form_input($search);
						?>

						<?php
							if(isset($myorders))
								$option_s = array('order_number' => lang('orders_admin_search_order_number'), 'date' => lang('orders_admin_search_date'));
							else
								$option_s = array('order_number' => lang('orders_admin_search_order_number'), 'customer' => lang('orders_admin_search_customer'), 'date' => lang('orders_admin_search_date'));
							echo form_dropdown('option', $option_s, $option, 'class="form-control" id="option_s"');
						?>

						<button type="submit" class="btn btn-primary"><?php echo lang('search');?></button>

					<a id="btn-delete" class="btn btn-bricky tooltips" title="<?php echo lang('delete'); ?>" href="javascript:void(0);" >

								<input id="select_all" type="checkbox" name='check_all' />

					<?php echo lang('orders_admin_order_number_title'); ?>
					<?php echo lang('orders_admin_customer_title'); ?>
					<?php echo lang('total'); ?>
					<?php echo lang('status'); ?>
					<?php echo lang('date'); ?>
					<?php echo lang('action'); ?>

			<?php if (count($orders)) { ?>

				<?php foreach($orders as $order) { ?>

								<input type="checkbox" name="checkb[]" class="checkb" name="check" value="<?php echo $order->id; ?>">

						<a href="<?php echo site_url('admin/orders/detail/'.$order->id); ?>"><?php echo $order->order_number; ?>

					<a href="<?php if(isset($myorders)) echo $myorders; else echo site_url('admin/users/edit/'.$order->user_id); ?>"><?php echo $order->name; ?>
					<?php echo settingValue($setting, 'currency_symbol', '$'); ?><?php echo number_format($order->total, 2); ?>

							<?php if ($order->status == 'pending') { ?>

									<a class="btn btn btn-yellow btn-xs tooltips dropdown-toggle" data-toggle="dropdown" href="javascript:void();" data-original-title="<?php echo lang('orders_status_setting');?>">
										<?php echo lang('pending');?>

											<a href="<?php echo site_url('admin/orders/status/completed/'.$order->id); ?>"><?php echo lang('completed');?>

											<a href="<?php echo site_url('admin/orders/status/refused/'.$order->id); ?>"><?php echo lang('refused');?>

							<?php } elseif ($order->status == 'completed') { ?>

									<a class="btn btn btn-success btn-xs tooltips dropdown-toggle" data-toggle="dropdown" href="javascript:void();" data-original-title="<?php echo lang('orders_status_setting');?>">
										<?php echo lang('completed');?>

											<a href="<?php echo site_url('admin/orders/status/pending/'.$order->id); ?>"><?php echo lang('pending');?>

											<a href="<?php echo site_url('admin/orders/status/refused/'.$order->id); ?>"><?php echo lang('refused');?>

							<?php }else{ ?>

									<a class="btn btn btn-danger btn-xs tooltips dropdown-toggle" data-toggle="dropdown" href="javascript:void();" data-original-title="<?php echo lang('orders_status_setting');?>">
										<?php echo lang('refused');?>

											<a href="<?php echo site_url('admin/orders/status/completed/'.$order->id); ?>"><?php echo lang('completed');?>

											<a href="<?php echo site_url('admin/orders/status/pending/'.$order->id); ?>"><?php echo lang('pending');?>

							<?php } ?>

					<?php echo date("Y-m-d", strtotime($order->created_on)); ?>

						<a class="remove btn btn-bricky tooltips" onclick="return confirm('<?php echo lang('orders_admin_confirm_delete');?>');" href="<?php echo site_url('admin/orders/delete/'.$order->id); ?>" data-original-title="<?php echo lang('remove');?>" data-placement="top">

				<?php } ?>

			<?php } ?>

			<?php echo $links; ?>

	<?php echo form_close(); ?>


text:
var WebpackIsomorphicToolsPlugin = require('webpack-isomorphic-tools/plugin');

// see this link for more info on what all of this means
// https://github.com/halt-hammerzeit/webpack-isomorphic-tools
module.exports = {

  // when adding "js" extension to asset types
  // and then enabling debug mode, it may cause a weird error:
  //
  // [0] npm run start-prod exited with code 1
  // Sending SIGTERM to other processes..
  //
  // debug: true,

  assets: {
    images: {
      extensions: [
        'jpeg',
        'jpg',
        'png',
        'gif'
      ],
      parser: WebpackIsomorphicToolsPlugin.url_loader_parser
    },
    fonts: {
      extensions: [
        'woff',
        'woff2',
        'ttf',
        'eot'
      ],
      parser: WebpackIsomorphicToolsPlugin.url_loader_parser
    },
    svg: {
      extension: 'svg',
      parser: WebpackIsomorphicToolsPlugin.url_loader_parser
    },
    // this whole "bootstrap" asset type is only used once in development mode.
    // the only place it's used is the Html.js file
    // where a <style/> tag is created with the contents of the
    // './src/theme/bootstrap.config.js' file.
    // (the aforementioned <style/> tag can reduce the white flash
    //  when refreshing page in development mode)
    //
    // hooking into 'js' extension require()s isn't the best solution
    // and I'm leaving this comment here in case anyone finds a better idea.

    // bootstrap: {
    //   extension: 'js',
    //   include: ['./src/theme/bootstrap.config.js'],
    //   filter: function(module, regex, options, log) {
    //     function is_bootstrap_style(name) {
    //       return name.indexOf('./src/theme/bootstrap.config.js') >= 0;
    //     }
    //     if (options.development) {
    //       return is_bootstrap_style(module.name) && WebpackIsomorphicToolsPlugin.style_loader_filter(module, regex, options, log);
    //     }
    //     // no need for it in production mode
    //   },
    //   // in development mode there's webpack "style-loader",
    //   // so the module.name is not equal to module.name
    //   path: WebpackIsomorphicToolsPlugin.style_loader_path_extractor,
    //   parser: WebpackIsomorphicToolsPlugin.css_loader_parser
    // },

    style_modules: {
      extensions: ['css','less','scss'],
      filter: function(module, regex, options, log) {
        if (options.development) {
          // in development mode there's webpack "style-loader",
          // so the module.name is not equal to module.name
          return WebpackIsomorphicToolsPlugin.style_loader_filter(module, regex, options, log);
        } else {
          // in production mode there's no webpack "style-loader",
          // so the module.name will be equal to the asset path
          return regex.test(module.name);
        }
      },
      path: function(module, options, log) {
        if (options.development) {
          // in development mode there's webpack "style-loader",
          // so the module.name is not equal to module.name
          return WebpackIsomorphicToolsPlugin.style_loader_path_extractor(module, options, log);
        } else {
          // in production mode there's no webpack "style-loader",
          // so the module.name will be equal to the asset path
          return module.name;
        }
      },
      parser: function(module, options, log) {
        if (options.development) {
          return WebpackIsomorphicToolsPlugin.css_modules_loader_parser(module, options, log);
        } else {
          // in production mode there's Extract Text Loader which extracts CSS text away
          return module.source;
        }
      }
    }
  }
}


text:
class QToolButton;

class LineEdit: public QLineEdit {
	Q_OBJECT
public:
	enum ButtonStyle {
		kNormal,
		kAutoRaise,
		kLightAutoRaise,
		kTransparent
	};

	LineEdit(QWidget* parent = nullptr);

	bool hasButton() const;
	void setButtonEnabled(bool enabled);

	ButtonStyle buttonStyle() const;
	void setButtonStyle(ButtonStyle style);

	bool isAutoClearMode() const;
	void setAutoClearMode(bool enabled);

	QString buttonToolTip() const;
	void setButtonToolTip(const QString& toolTip);

	QIcon buttonIcon() const;
	void setButtonIcon(const QIcon& icon);

	uint editTimeout() const;
	void setEditTimeout(uint msecs);

	bool hasIcon() const;
	void setIcon(const QIcon& icon);

	QString prefix() const;
	void setPrefix(const QString& prefix);

	QColor prefixColor() const;
	void setPrefixColor(const QColor& color);

	QString suffix() const;
	void setSuffix(const QString& suffix);

	QColor suffixColor() const;
	void setSuffixColor(const QColor& color);

signals:
	void buttonClicked();
	void textEditTimeout(const QString& text);

protected:
	virtual void paintEvent(QPaintEvent* event);
	virtual void resizeEvent(QResizeEvent* event);
	virtual void keyPressEvent(QKeyEvent* event);
	virtual void mouseMoveEvent(QMouseEvent* event);

private:
	bool hasButton_;
	QToolButton* button_;
	ButtonStyle buttonStyle_;
	bool isAutoClearMode_;
	QTimer timer_;
	QPixmap icon_;
	QString prefix_;
	QString suffix_;
	QColor prefixColor_;
	QColor suffixColor_;

	void updateLayout();

private slots:
	void onButtonClicked();
	void onTextChanged();
	void onTimeout();
};

#endif // MINDCACHE_WIDGETS_LINEEDIT_H


text:
'use strict';

import AnimatedNode from './AnimatedNode';
import AnimatedWithChildren from './AnimatedWithChildren';
import NativeAnimatedHelper from '../NativeAnimatedHelper';

class AnimatedTransform extends AnimatedWithChildren {
  constructor(transforms) {
    super();
    this._transforms = transforms;
  }

  __makeNative() {
    this._transforms.forEach(transform => {
      for (const key in transform) {
        const value = transform[key];

        if (value instanceof AnimatedNode) {
          value.__makeNative();
        }
      }
    });

    super.__makeNative();
  }

  __getValue() {
    return this._transforms.map(transform => {
      const result = {};

      for (const key in transform) {
        const value = transform[key];

        if (value instanceof AnimatedNode) {
          result[key] = value.__getValue();
        } else {
          result[key] = value;
        }
      }

      return result;
    });
  }

  __getAnimatedValue() {
    return this._transforms.map(transform => {
      const result = {};

      for (const key in transform) {
        const value = transform[key];

        if (value instanceof AnimatedNode) {
          result[key] = value.__getAnimatedValue();
        } else {
          // All transform components needed to recompose matrix
          result[key] = value;
        }
      }

      return result;
    });
  }

  __attach() {
    this._transforms.forEach(transform => {
      for (const key in transform) {
        const value = transform[key];

        if (value instanceof AnimatedNode) {
          value.__addChild(this);
        }
      }
    });
  }

  __detach() {
    this._transforms.forEach(transform => {
      for (const key in transform) {
        const value = transform[key];

        if (value instanceof AnimatedNode) {
          value.__removeChild(this);
        }
      }
    });

    super.__detach();
  }

  __getNativeConfig() {
    const transConfigs = [];

    this._transforms.forEach(transform => {
      for (const key in transform) {
        const value = transform[key];

        if (value instanceof AnimatedNode) {
          transConfigs.push({
            type: 'animated',
            property: key,
            nodeTag: value.__getNativeTag()
          });
        } else {
          transConfigs.push({
            type: 'static',
            property: key,
            value: NativeAnimatedHelper.transformDataType(value)
          });
        }
      }
    });

    NativeAnimatedHelper.validateTransform(transConfigs);
    return {
      type: 'transform',
      transforms: transConfigs
    };
  }

}

export default AnimatedTransform;


text:
package com.dangdang.ddframe.job.restful;

import org.junit.Test;

import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.assertThat;

public final class RestfulExceptionTest {

    @Test
    public void assertRestfulException() {
        assertThat(new RestfulException(new RuntimeException()).getCause(), instanceOf(RuntimeException.class));
    }
}


text:
class TdToolbelt < Cask
  version :latest
  sha256 :no_check

  url 'http://toolbelt.treasuredata.com/mac'
  homepage 'http://toolbelt.treasuredata.com/'

  container_type :naked
  preflight do
    system '/bin/mv', '--', "#{destination_path}/mac", "#{destination_path}/td-toolbelt.pkg"
  end

  pkg 'td-toolbelt.pkg'
  uninstall :pkgutil => 'com.td.toolbelt'
  # zap :pkgutil => 'org.ruby-lang.installer'
end


text:
require 'spec_helper'

describe School do

  subject { Factory(:school) }

  it { should validate_presence_of(:address_1) }
  it { should validate_presence_of(:city) }
  it { should validate_presence_of(:name) }
  it { should validate_presence_of(:state) }
  it { should validate_presence_of(:zipcode) }

  it { should have_many(:profiles) }

  describe "zipcode formatting" do
    it "should only persist the first five digits" do
      lambda{ Factory(:school, :zipcode => '123456') }.should raise_error
    end

    it "should only accept numerical values" do
      lambda{ Factory(:school, :zipcode => 'a2345') }.should raise_error
    end

    it "should require full five digits" do
      lambda{ Factory(:school, :zipcode => '1234') }.should raise_error
    end
  end

  describe "search" do
    context "there are no schools" do
      it "it should return no results" do
        School.search('whatever').should be_empty
      end
    end

    context "there exist two schools with different names but the same zipcodes" do
      before do
        @shared_zipcode = '12345'
        @temple = Factory :school, :name => 'Temple University', :zipcode => @shared_zipcode
        @drexel = Factory :school, :name => 'Drexel University', :zipcode => @shared_zipcode
        @unc    = Factory :school, :name => 'University of North Carolina', :zipcode => '00000'
      end

      it "should return no schools if no search terms match" do
        School.search('whatever').should be_empty
      end

      it "should only return schools that contain the search term in their name" do
        (School.search(@temple.name) - [@temple]).should be_empty
      end

      it "should return all schools that match the search terms by zipcode" do
        (School.search(@shared_zipcode) - [@temple, @drexel]).should be_empty
      end

    end
  end

  describe "user_count" do
    context "there are two schools, each with different amounts of users" do
      before do
        @school_a = Factory :school
        @school_b = Factory :school
        @school_a_users = 1
        @school_b_users = 3
        @school_a_users.times { Factory :profile, :school => @school_a }
        @school_b_users.times { Factory :profile, :school => @school_b }
      end

      it "should return the number of profiles associated with the school" do
        @school_a.user_count.should == @school_a_users
        @school_b.user_count.should == @school_b_users
      end
    end
  end

  describe "migrate_users_to" do
    before do
      @school = Factory :school
    end

    it "should throw an error if target school is nil" do
      lambda { @school.migrate_users_to(nil) }.should raise_error
    end

    context "there is a valid target school" do
      before do
        @target_school = Factory :school
      end

      it "should migrate and return 0 users" do
        @school.migrate_users_to(@target_school).should be_empty
      end

      context "there are multiple useres in a school" do
        before do
          2.times { Factory :profile, :school => @school }
          @users = @school.profiles.map{ |p| p.user }
        end

        it "should return all users that were in the school" do
          (@school.migrate_users_to(@target_school) - @users).should be_empty
        end

        it "should remove all users from that school" do
          @school.migrate_users_to(@target_school)
          @school.user_count.should == 0
        end

        it "should add all users to the target school" do
          migrated_users = @school.migrate_users_to(@target_school)
          (@users - migrated_users).should be_empty
        end
      end
    end

  end # describe migrate_users_to

  describe "learner_form_search" do
    before do
      @zipcode = '99999'
    end

    context "when searching by a bad zipcode" do
      it "will return an empty result set" do
        School.learner_form_search('abcde').should be_empty
      end
    end

    context "there are no schools" do
      it "will return an empty result set" do
        School.learner_form_search(@zipcode).should be_empty
      end

      context "and a user-created school is passed as a paramter" do
        before do
          @user_created_school = Factory :school, :approved => false, :zipcode => '31415'
        end

        it "will return only the user created school" do
          School.learner_form_search(@user_created_school.zipcode, @user_created_school).should == [@user_created_school]
        end

        context "and the user-created school is from a zipcode different from the search parameter" do
          it "should return an empty result set" do
            School.learner_form_search(@zipcode, @user_created_school).should be_empty
          end
        end
      end
    end

    context "there are several schools in different zipcodes" do
      before do
        @c_school = Factory :school, :name => 'C School', :zipcode => @zipcode
        @b_school = Factory :school, :name => 'B School'
        @a_school = Factory :school, :name => 'A School', :zipcode => @zipcode
      end

      context "when searching by a zipcode with two schools in it;" do
        it "should return the two schools, sorted ascending by name" do
          School.learner_form_search(@zipcode).should == [@a_school, @c_school]
        end

        context "and a user-created school (with the same zipcode) is passed as a paramter" do
          before { @user_created_school = Factory :school, :name => 'Ac School', :approved => false, :zipcode => @zipcode }

          it "will return the two existing schools and the user-created school" do
            School.learner_form_search(@zipcode, @user_created_school).should == [@a_school, @user_created_school, @c_school]
          end

          context "and the user-created school is from a zipcode different from the search parameter" do
            before do
              @user_created_school.zipcode = '31415'
              @user_created_school.save
            end

            it "should the original result set without the user created school" do
              School.learner_form_search(@zipcode, @user_created_school).should == [@a_school, @c_school]
            end

            context "the user-created school is nil" do
              before { @user_created_school = nil }

              it "should the original result set without the user created school" do
                School.learner_form_search(@zipcode, @user_created_school).should == [@a_school, @c_school]
              end
            end
          end
        end # user-created school passed as a parameter
      end

      context "when searching by a zipcode with two schools, one pending admin approval" do
        before do
          @c_school.approved = false
          @c_school.save
          @results = School.learner_form_search(@zipcode)
        end

        it "should only return the school that is approved" do
          @results.should == [@a_school]
        end
      end

      context "when searching by a bad zipcode" do
        it "will return an empty result set" do
          School.learner_form_search('abcde').should be_empty
        end
      end

    end # several schools

  end # describe learner_form_search

  describe "render_form?" do
    context "when there do not exist any schools" do
      before { School.stub(:count).and_return(0) }

      it "will return false" do
        School.render_form?.should be_false
      end
    end

    context "when there exists a school" do
      before do
        School.stub(:count).and_return(1)
        Audience.stub(:count).and_return(0)
      end

      it "will return false" do
        School.render_form?.should be_false
      end

      context "and an audience" do
        before { Audience.stub(:count).and_return(1) }

        it "will return true" do
          School.render_form?.should be_true
        end
      end
    end
  end # describe render_form?

  describe "to_client_model_json" do
    context "the record is new" do
      it "should not contain created_at" do
        School.new.to_client_model_json.include?('created_at').should be_false
      end

      it "should not contain updated_at" do
        School.new.to_client_model_json.include?('updated_at').should be_false
      end
    end

    context "the record has been persisted" do
      it "should not contain created_at" do
        subject.to_client_model_json.include?('created_at').should be_false
      end

      it "should not contain updated_at" do
        subject.to_client_model_json.include?('updated_at').should be_false
      end
    end
  end

  describe "phone validation" do
    before { @school = Factory :school }

    context "the phone number is valid;" do
      context "it contains extra characters" do
        before { @school.phone = '987-654-2310' }

        it "should return a value without extra characters" do
          @school.phone.should == '(987) 654-2310'
        end
      end
    end

    context "the phone number is missing" do
      before { @school.phone = '' }

      it "should not validate" do
        @school.valid?.should be_false
      end
    end

    context "the phone number contains only non-numeric values" do
      before { @school.phone = 'abcdefg' }

      it "should not validate" do
        @school.valid?.should be_false
      end
    end

    context "the phone number is invalid (too short);" do
      before { @school.phone = '123' }

      it "should not validate" do

        @school.valid?.should be_false
      end
    end
  end

end


text:
from __future__ import print_function, absolute_import

import netaddr
import os
import logging
import re

from wifi import Scheme
from wifi.exceptions import BindError
from wifi.utils import mac_addr_pattern
import wifi.subprocess_compat as subprocess

bound_ap_re = re.compile(r"^Using interface (?P<interface>\w+) with hwaddr %s and ssid '(?P<ssid>[^']+)'" % mac_addr_pattern, flags=re.MULTILINE)

class Hostapd(object):
    """
    A wrapper for managing hostapd configuration files stored under /etc/hostapd/conf.d and
    managing hostapd service instances based on them.

    Note: The directory /etc/hostapd/conf.d does not usually exist and has to be created before using
    this class. Alternatively provide a different location for file storage by creating a custom type
    wrapper using `Hostapd.for_hostapd_and_confd(hostapd=<hostapd>, confd=<config folder>)`.
    """

    # location of hostapd binary
    hostapd = "/usr/sbin/hostapd"

    # location of hostapd config folder
    confd = "/etc/hostapd/conf.d/"

    # our logger instance
    logger = logging.getLogger(__name__)

    @classmethod
    def for_hostapd_and_confd(cls, hostapd, confd):
        return type(cls)(cls.__name__, (cls,), {
            'hostapd': hostapd if hostapd is not None else cls.hostapd,
            'confd': confd if confd is not None else cls.confd,
        })

    def __init__(self, interface, name, ssid, channel, driver=None, psk=None, options=None):
        self.interface = interface
        self.driver = driver if driver is not None else "nl80211"
        self.name = name
        self.ssid = ssid
        self.channel = channel
        self.psk = psk

        self.options = options if options else dict()

    def __str__(self):
        # default parameters for a simply ap
        conf = [
            "interface={interface}",
            "driver={driver}",
            "ssid={ssid}",
            "channel={channel}"
        ]

        if self.psk is not None:
            # parameters for encryption via WPA
            conf += [
                "wpa=3",
                "wpa_passphrase={psk}",
                "wpa_key_mgmt=WPA-PSK",
                "wpa_pairwise=TKIP CCMP",
                "rsn_pairwise=CCMP"
            ]

        if self.options:
            # any additional options given
            conf += ["{k}={v}".format(k=k, v=v) for k, v in self.options.items()]

        return "\n".join(conf).format(**vars(self))

    def __repr__(self):
        return "Hostapd(interface={interface!r}, driver={driver!r}, name={name!r}, ssid={ssid!r})"\
            .format(**vars(self))

    def save(self, allow_overwrite=False):
        existing_hostapd = self.__class__.find(self.interface, self.name)
        if existing_hostapd:
            if not allow_overwrite:
                raise RuntimeError("Config for interface %s named %s does already exists and overwrite is not allowed" % (self.interface, self.name))
            existing_hostapd.delete()

        with open(self.configfile, "w") as f:
            f.write(str(self))

    def delete(self):
        if self.is_running():
            self.deactivate()

        try:
            os.remove(self.configfile)
        except OSError as e:
            self._logger.warn("Could not delete %s: %s" % (self.configfile, e))

    def activate(self):
        try:
            output = subprocess.check_output([self.__class__.hostapd, "-dd", "-B", self.configfile], stderr=subprocess.STDOUT)
            self._logger.info("Started hostapd: {output}".format(output=output))
            return True
        except subprocess.CalledProcessError as e:
            self._logger.warn("Error while starting hostapd: {output}".format(output=e.output))
            raise e

    def deactivate(self):
        pid = self.get_pid()
        if pid is None:
            return
        subprocess.check_call(["kill", pid])

    def get_pid(self):
        pids = [pid for pid in os.listdir("/proc") if pid.isdigit()]
        for pid in pids:
            try:
                with open(os.path.join("/proc", pid, "cmdline"), "r") as f:
                    line = f.readline()
                    if self.__class__.hostapd in line and self.configfile in line:
                        return pid
            except:
                # the pid might just have vanished because the process exited normally, no need to worry
                pass
        return None

    def is_running(self):
        return self.get_pid() is not None

    @property
    def configfile(self):
        return os.path.join(self.__class__.confd, "{name}.conf".format(name=self.name))

    @property
    def _logger(self):
        return self.__class__.logger

    @classmethod
    def all(cls):
        result = []
        for conf in os.listdir(cls.confd):
            if conf.endswith(".conf"):
                filename = os.path.join(cls.confd, conf)
                try:
                    ap = cls.from_hostapd_conf(filename)
                    result.append(ap)
                except:
                    cls.logger.exception("Could not retrieve hostapd from file %s:" % filename)
        return result

    @classmethod
    def find(cls, interface, name):
        try:
            return cls.where(lambda x: x.name == name and x.interface == interface)[0]
        except IndexError:
            return None

    @classmethod
    def where(cls, fn):
        return list(filter(fn, cls.all()))

    @classmethod
    def from_hostapd_conf(cls, configfile):
        if not os.path.exists(configfile):
            raise IOError("Configfile not found: %s" % configfile)

        name = os.path.basename(configfile)[:-len(".conf")]

        conf_options = dict()
        with open(configfile, "r") as f:
            for line in f:
                k, v = line.strip().split("=", 1)
                conf_options[k] = v

        for key in ("interface", "ssid", "channel"):
            if not key in conf_options or conf_options[key] is None:
                raise RuntimeError("Invalid config, %s is missing or none" % key)

        options = dict((k, conf_options[k]) for k in conf_options if not k in ["interface", "driver", "ssid", "channel", "wpa", "wpa_passphrase", "wpa_key_mgmt", "wpa_pairwise", "rsn_pairwise"])
        psk = conf_options["wpa_passphrase"] if "wpa_passphrase" in conf_options else None
        try:
            channel = int(conf_options["channel"])
        except ValueError as e:
            raise RuntimeError("Invalid config, %r is an invalid channel" % conf_options["channel"], e)

        return cls(conf_options["interface"], name, conf_options["ssid"], channel, driver=conf_options["driver"], psk=psk, options=options)

    def parse_hostapd_output(self, output):
        print(output)
        matches = bound_ap_re.search(output)
        if matches:
            return True
        else:
            raise BindError("Could not bind hostapd %r to interface %s:\n%s" % (self, self.interface, output))

class Dnsmasq(object):
    """
    A wrapper for managing dnsmasq configurations (stored as .conf files under /etc/dnsmasq.conf.d)
    and managing dnsmasq service instances based on them.

    Note: The directory /etc/dnsmasq.conf.d does not usually exist and has to be created before using
    this class. Alternatively provide a different location for file storage by creating a custom type
    wrapper using `Dnsmasq.for_dnsmasq_and_confd(dnsmasq=<dnsmasq>, confd=<config folder>)`.
    """

    # dnsmasq binary
    dnsmasq = "/usr/sbin/dnsmasq"

    # dnsmasq configuration storage
    confd = "/etc/dnsmasq.conf.d"

    # our logger
    logger = logging.getLogger(__name__)

    @classmethod
    def for_dnsmasq_and_confd(cls, dnsmasq, confd):
        return type(cls)(cls.__name__, (cls,), {
            'dnsmasq': dnsmasq if dnsmasq is not None else cls.dnsmasq,
            'confd': confd if confd is not None else cls.confd,
        })

    @classmethod
    def all(cls):
        result = []
        for conf in os.listdir(cls.confd):
            if conf.endswith(".conf"):
                filename = os.path.join(cls.confd, conf)
                try:
                    dnsmasq = cls.from_dnsmasq_conf(os.path.join(cls.confd, conf))
                    result.append(dnsmasq)
                except:
                    cls.logger.exception("Could not retrieve dnsmasq config from file %s" % filename)
        return result

    @classmethod
    def where(cls, fn):
        return list(filter(fn, cls.all()))

    @classmethod
    def find(cls, interface, name):
        try:
            return cls.where(lambda x: x.name == name and x.interface == interface)[0]
        except IndexError:
            return None

    @classmethod
    def from_dnsmasq_conf(cls, configfile):
        """
        Creates a :class:`Dnsmasq` config from a given dnsmasq configuration file.

        :param configfile: path of config file to create instance from
        :return: created instance
        """

        if not os.path.exists(configfile):
            raise IOError("Configfile not found: %s" % configfile)

        name = os.path.basename(configfile)[:-len(".conf")]

        conf = dict()
        additional_options = dict()
        with open(configfile, "r") as f:
            for line in f:
                line = line.strip()
                if not line:
                    continue

                # split or "key=value" pairs
                split_line = map(str.strip, line.split("=", 1))
                if len(split_line) > 1:
                    # this is an actual "key=value" pair
                    k, v = split_line
                else:
                    # this is only a single "key" option without value
                    k = split_line[0]
                    v = None

                if k == "interface":
                    conf["interface"] = v
                    continue

                elif k == "dhcp-range":
                    # format is either "dhcp-range=<ip1>,<ip2>,<leasetime>" or
                    # "dhcp-range=<tag>,<ip1>,<ip2>,<leasetime>"
                    opts = v.split(",")
                    if len(opts) > 3:
                        # strip off tags, we don't care about them
                        opts = opts[-3:]
                    conf["start"], conf["end"], lease_time = opts

                    # lease time can be given as "<hours>h", "<minutes>m" or "<seconds>"
                    if lease_time.endswith("h"):
                        # hours = 60 minutes * 60 seconds
                        factor = 60 * 60
                        lease_time = lease_time[:-1]
                    elif lease_time.endswith("m"):
                        # minutes = 60 seconds
                        factor = 60
                        lease_time = lease_time[:-1]
                    else:
                        # seconds
                        factor = 1

                    try:
                        conf["lease_time"] = int(lease_time) * factor
                        continue
                    except ValueError:
                        cls.logger.exception("Could not convert lease time value %s" % lease_time)

                elif k == "domain":
                    conf["domain"] = v
                    continue

                elif k == "dhcp-option":
                    # parse dhcp options, right now we only support gateway definition, which
                    # is provided in the format "dhcp-option=option:router,<gateway>" or
                    # "dhcp-option=3,<gateway>"
                    opts = v.split(",")
                    if len(opts) == 2 and (opts[0] == "option:router" or opts[0] == "3"):
                        conf["gateway"] = opts[1]
                        continue

                elif k in ("bind-interfaces", "local", "expand-hosts"):
                    # ignore known parameters that are used for general setup or domain setup
                    continue

                # if we came this far then we have an additional option at hand
                if v is not None:
                    # if the value is not None, we create a key => list entry and add the value to it
                    if not k in additional_options:
                        additional_options[k] = list()
                    additional_options[k].append(v)
                else:
                    # if the value is None it's a key only entry, so we add a key => None entry
                    additional_options[k] = None

        # make sure the mandatory parameters are all there
        for key in "interface", "start", "end":
            if not key in conf or conf[key] is None:
                raise RuntimeError("Invalid config, %s is missing or None" % key)

        # make sure the optional arguments that are not supplied are all set to None
        for key in "lease_time", "domain", "gateway":
            if not key in conf:
                conf[key] = None

        return Dnsmasq(conf["interface"], name, conf["start"], conf["end"], lease_time=conf["lease_time"],
                       gateway=conf["gateway"], domain=conf["domain"], options=additional_options)

    def __init__(self, interface, name, start, end, lease_time=None, gateway=None, domain=None, options=None):
        """
        :param interface: the interface on which to listen
        :param name: the name of the configuration
        :param start: the start ip of the managed dhcp range
        :param end: the end ip of the managed dhcp range
        :param lease_time: the lease time for given dhcp leases, defaults to 600s
        :param gateway: the gateway to hand out via dhcp, defaults to no gateway
        :param domain: the local domain to define, default to no domain
        :param options: additional options, dict of either key => list (for possibly
               multiple key-value-pairs) or key => None for key-only-statements
               in the config
        """

        self.interface = interface
        self.name = name
        self.start = start
        self.end = end
        self.lease_time = lease_time if lease_time else 600
        self.gateway = gateway
        self.domain = domain
        self.options = options if options else dict()

    def __str__(self):
        # basic dhcp setup for dnsmasq
        conf = [
            "interface={interface}",
            "bind-interfaces",
            "dhcp-range={start},{end},{lease_time}"
        ]

        # if a local domain is configured, add the corresponding configuration lines
        if self.domain:
            conf += [
                "local=/{domain}/",
                "domain={domain}",
                "expand-hosts"
            ]

        # if a gateway is configured, add the corresponding configuration line
        if self.gateway:
            conf += [
                "dhcp-option=option:router,{gateway}"
            ]

        # add any additional dnsmasq options that were provided
        if self.options:
            for k, l in self.options.items():
                if l is not None:
                    for v in l:
                        conf.append("{key}={value}".format(key=k, value=v))
                else:
                    conf.append(k)

        return "\n".join(conf).format(**vars(self))

    def __repr__(self):
        return "Dnsmasq(interface={interface}, name={name}, start={start}, end={end})".format(**vars(self))

    def save(self, allow_overwrite=False):
        """
        Saves the config to the defined `confd` directory.

        :param allow_overwrite: whether to overwrite an existing config of the same name, raises an
                                exception if such a config is found and set to `False` (the default)
        """

        existing_dnsmasq = self.__class__.find(self.interface, self.name)
        if existing_dnsmasq:
            if not allow_overwrite:
                raise RuntimeError("Config for interface %s named %s does already exists and overwrite is not allowed" % (self.interface, self.name))
            existing_dnsmasq.delete()

        with open(self.configfile, "w") as f:
            f.write(str(self))

    def delete(self):
        """ Deletes the config, deactivates it before if it's currently active. """

        if self.is_running():
            self.deactivate()
        try:
            os.remove(self.configfile)
        except OSError as e:
            self._logger.warn("Could not delete %s: %s" % (self.configfile, e))

    def activate(self):
        """ Activates this config. """

        try:
            output = subprocess.check_output([self.__class__.dnsmasq, "--conf-file={file}".format(file=self.configfile)], stderr=subprocess.STDOUT)
            self._logger.info("Started dnsmasq: {output}".format(output=output))
        except subprocess.CalledProcessError as e:
            self._logger.warn("Error while starting dnsmasq: {output}".format(output=e.output))
            raise e

    def deactivate(self):
        """ Deactivates this config. """

        pid = self.get_pid()
        if pid is None:
            return
        subprocess.check_call(["kill", pid])

    def get_pid(self):
        """ Get's the pid of the dnsmasq process running this config, or None if not currently running. """

        pids = [pid for pid in os.listdir("/proc") if pid.isdigit()]
        for pid in pids:
            try:
                with open(os.path.join("/proc", pid, "cmdline"), "r") as f:
                    line = f.readline()
                    if self.__class__.dnsmasq in line and self.configfile in line:
                        return pid
            except:
                pass
        return None

    def is_running(self):
        """ Returns a boolean indicating whether this config is currently active or not. """

        return self.get_pid() is not None

    @property
    def configfile(self):
        return os.path.join(self.__class__.confd, "{name}.conf".format(name=self.name))

    @property
    def _logger(self):
        return self.__class__.logger

class AccessPoint(object):
    """
    Manages access point configurations by wrapping the hostapd, dnsmasq and scheme configurations
    they are based on and allows starting and stopping the access point altogether.
    """

    # class providing the hostapd wrapper
    hostapd_cls = Hostapd

    # class providing the dnsmasq wrapper
    dnsmasq_cls = Dnsmasq

    # class providing the scheme wrapper
    scheme_cls = Scheme

    @classmethod
    def for_classes(cls, hostapd_cls=None, dnsmasq_cls=None, scheme_cls=None):
        return type(cls)(cls.__name__, (cls,), {
            'hostapd_cls': hostapd_cls if hostapd_cls is not None else cls.hostapd_cls,
            'dnsmasq_cls': dnsmasq_cls if dnsmasq_cls is not None else cls.dnsmasq_cls,
            'scheme_cls': scheme_cls if scheme_cls is not None else cls.scheme_cls
        })

    @classmethod
    def all(cls):
        hostapds = {(hostapd.interface, hostapd.name): hostapd for hostapd in cls.hostapd_cls.all()}
        dnsmasqs = {(dnsmasq.interface, dnsmasq.name): dnsmasq for dnsmasq in cls.dnsmasq_cls.all()}
        schemes = {(scheme.interface, scheme.name): scheme for scheme in cls.scheme_cls.all()}

        result = []
        for key in hostapds:
            if key in dnsmasqs and key in schemes:
                result.append(AccessPoint(hostapds[key], dnsmasqs[key], schemes[key]))
        return result

    @classmethod
    def where(cls, fn):
        return list(filter(fn, cls.all()))

    @classmethod
    def find(cls, interface, name):
        try:
            return cls.where(lambda x: x.name == name and x.interface == interface)[0]
        except IndexError:
            return None

    @classmethod
    def for_arguments(cls, interface, name, ssid, channel, ip, network, start, end, forwarding_to=None,
                      hostap_options=None, dnsmasq_options=None, scheme_options=None):
        """
        Creates a new access point configuration for the given arguments.

        :param string interface: the interface on which to create the access point
        :param string name: the configuration name
        :param string ssid: the SSID to create
        :param int channel: the channel on which to create the access point
        :param string ip: the ip to assign to the interface serving as access point
        :param string network: the network of the access point
        :param string start: start address of IP address range handled by dhcp server
        :param string end: end address of IP address range handled by dhcp server
        :param string forwarding_to: interface to forward to, defaults to None for no
               forwarding enabled
        :param dict hostap_options: hostap options, defaults to None. Parameters
               `driver` and `psk` will be used as their counterparts during
               `Hostapd` construction, all other options will be given as
               `options` to the Hostapd constructor.
        :param dict dnsmasq_options: dnsmasq options, defaults to None. Parameters
               `lease_time`, `domain` and `gateway` will be used as their
               counterparts during `Dnsmasq` construction, all other options
               will be given as `options` to the Dnsmasq constructor.
        :param dict scheme_options: scheme options, defaults to None. Note that
               `address`, `netmask` and `broadcast` will be overwritten with
               the values derived from `ip` and `network`. If `forwarding_to`
               is set `post-up` and `pre-down` will be extended to include
               the necessary firewalling rules and forward-sysctl-calls
        :return: the resulting `AccessPoint` instance
        """

        network_address = netaddr.IPNetwork(network)

        # prepare hostapd options
        if hostap_options is None:
            hostap_options = dict()

        if "driver" in hostap_options:
            driver = hostap_options["driver"]
            del hostap_options["driver"]
        else:
            driver = None

        if "psk" in hostap_options:
            psk = hostap_options["psk"]
            del hostap_options["psk"]
        else:
            psk = None

        # create hostapd config
        hostapd = cls.hostapd_cls(interface, name, ssid, channel, driver, psk=psk, options=hostap_options)

        #  prepare dnsmasq options
        if dnsmasq_options is None:
            dnsmasq_options = dict()

        if "lease_time" in dnsmasq_options:
            lease_time = dnsmasq_options["lease_time"]
            del dnsmasq_options["lease_time"]
        else:
            lease_time = None

        if "domain" in dnsmasq_options:
            domain = dnsmasq_options["domain"]
            del dnsmasq_options["domain"]
        else:
            domain = None

        if "gateway" in dnsmasq_options:
            gateway = dnsmasq_options["gateway"]
            del dnsmasq_options["gateway"]
        else:
            gateway = None

        # create dnsmasq
        dnsmasq = cls.dnsmasq_cls(interface, name, start, end, lease_time=lease_time, gateway=gateway, domain=domain, options=dnsmasq_options)

        # prepare scheme options
        if scheme_options == None:
            scheme_options = dict()

        # create a scheme with static configuration, given ip and netmask -- those parameters will be ruthlessly
        # overridden if they were already present in the supplied scheme_options
        scheme_options.update(dict(
            address=[ip],
            netmask=[str(network_address.netmask)],
            broadcast=[str(network_address.broadcast)]
        ))

        if forwarding_to is not None:
            # if forwarding is enabled, also add some rules and stuff
            if not "post-up" in scheme_options:
                scheme_options["post-up"] = []
            scheme_options["post-up"] += [
                # flush current tables
                "/sbin/iptables -F",
                "/sbin/iptables -X",
                "/sbin/iptables -t nat -F",
                # setup forwarding rules
                "/sbin/iptables -A FORWARD -o {forward} -i {interface} -s {network} -m conntrack --ctstate NEW -j ACCEPT".format(forward=forwarding_to, network=str(network_address), interface=interface),
                "/sbin/iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT",
                "/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE",
                # enable forwarding
                "/sbin/sysctl -w net.ipv4.ip_forward=1"
            ]

            if not "pre-down" in scheme_options:
                scheme_options["pre-down"] = []
            scheme_options["pre-down"] += [
                # disable forwarding
                "/sbin/sysctl -w net.ipv4.ip_forward=0",
                # flush current tables
                "/sbin/iptables -F",
                "/sbin/iptables -X",
                "/sbin/iptables -t nat -F",
            ]
        scheme = cls.scheme_cls(interface, name, type="static", options=scheme_options)

        return cls(hostapd, dnsmasq, scheme)

    def __init__(self, hostapd, dnsmasq, scheme):
        """
        Constructor for the :class:`AccessPoint` instance, takes :class:`Hostapd`, :class:`Dnsmasq` and :class:`Scheme`
        instance to utilize.

        Should normally not be used directly from calling code, instead use the provided factory `for_arguments`.

        :param hostapd: :class:`Hostapd` instance
        :param dnsmasq: :class:`Dnsmasq` instance
        :param scheme: :class:`Scheme` instance
        """

        self._logger = logging.getLogger(__name__)

        self.hostapd = hostapd
        self.dnsmasq = dnsmasq
        self.scheme = scheme

    def save(self, allow_overwrite=False):
        """
        Saves all wrapped configurations.
        :param allow_overwrite: whether to allow overwriting of existing configs, defaults to False
        """

        self.hostapd.save(allow_overwrite=allow_overwrite)
        self.dnsmasq.save(allow_overwrite=allow_overwrite)
        self.scheme.save(allow_overwrite=allow_overwrite)

    def delete(self):
        """ Deletes all wrapped configurations. """

        self.hostapd.delete()
        self.dnsmasq.delete()
        self.scheme.delete()

    def activate(self):
        """ Activates the access point by activating all wrapped configurations. """

        self.hostapd.activate()
        self.scheme.activate()
        self.dnsmasq.activate()

    def deactivate(self):
        """ Deactivates the access point by deactivating all wrapped configurations. """

        self.dnsmasq.deactivate()
        self.scheme.deactivate()
        self.hostapd.deactivate()

    @property
    def name(self):
        return self.hostapd.name

    @property
    def interface(self):
        return self.hostapd.interface

    def is_running(self):
        """ Returns whether the access point is currently running (either hostap or dnsmasq) or not. """
        return self.hostapd.is_running() or self.dnsmasq.is_running()

    def __repr__(self):
        return "AccessPoint(hostapd={hostapd!r}, dnsmasq={dnsmasq!r}, scheme={scheme!r})".format(**vars(self))


text:
package co.cask.coopr.store.provisioner;

import co.cask.coopr.BaseTest;
import co.cask.coopr.codec.json.guice.CodecModules;
import co.cask.coopr.common.conf.Configuration;
import co.cask.coopr.common.conf.guice.ConfigurationModule;
import co.cask.coopr.store.guice.TestStoreModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.junit.BeforeClass;

/**
 *
 */
public class SQLProvisionerStoreTest extends ProvisionerStoreTest {
  private static SQLProvisionerStore store;

  @BeforeClass
  public static void setupTestClass() throws Exception {
    Configuration sqlConf = BaseTest.createTestConf();
    Injector injector = Guice.createInjector(
      new ConfigurationModule(sqlConf),
      new TestStoreModule(),
      new CodecModules().getModule()
    );
    store = injector.getInstance(SQLProvisionerStore.class);
    store.startAndWait();
  }

  @Override
  ProvisionerStore getProvisionerStore() {
    return store;
  }

  @Override
  void clearData() throws Exception {
    store.clearData();
  }
}