text:
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.trino.sql.query;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import io.trino.Session;
import io.trino.connector.MockConnectorFactory;
import io.trino.metadata.QualifiedObjectName;
import io.trino.plugin.tpch.TpchConnectorFactory;
import io.trino.spi.connector.CatalogSchemaTableName;
import io.trino.spi.connector.ConnectorMaterializedViewDefinition;
import io.trino.spi.connector.ConnectorViewDefinition;
import io.trino.spi.connector.SchemaTableName;
import io.trino.spi.security.Identity;
import io.trino.spi.security.ViewExpression;
import io.trino.spi.type.BigintType;
import io.trino.spi.type.VarcharType;
import io.trino.testing.LocalQueryRunner;
import io.trino.testing.TestingAccessControlManager;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import java.util.Optional;

import static io.trino.plugin.tpch.TpchMetadata.TINY_SCHEMA_NAME;
import static io.trino.testing.TestingAccessControlManager.TestingPrivilegeType.SELECT_COLUMN;
import static io.trino.testing.TestingAccessControlManager.privilege;
import static io.trino.testing.TestingSession.testSessionBuilder;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

@Test(singleThreaded = true)
public class TestColumnMask
{
    private static final String CATALOG = "local";
    private static final String MOCK_CATALOG = "mock";
    private static final String USER = "user";
    private static final String VIEW_OWNER = "view-owner";
    private static final String RUN_AS_USER = "run-as-user";

    private static final Session SESSION = testSessionBuilder()
            .setCatalog(CATALOG)
            .setSchema(TINY_SCHEMA_NAME)
            .setIdentity(Identity.forUser(USER).build())
            .build();

    private QueryAssertions assertions;
    private TestingAccessControlManager accessControl;

    @BeforeClass
    public void init()
    {
        LocalQueryRunner runner = LocalQueryRunner.builder(SESSION).build();

        runner.createCatalog(CATALOG, new TpchConnectorFactory(1), ImmutableMap.of());

        ConnectorViewDefinition view = new ConnectorViewDefinition(
                "SELECT nationkey, name FROM local.tiny.nation",
                Optional.empty(),
                Optional.empty(),
                ImmutableList.of(new ConnectorViewDefinition.ViewColumn("nationkey", BigintType.BIGINT.getTypeId()), new ConnectorViewDefinition.ViewColumn("name", VarcharType.createVarcharType(25).getTypeId())),
                Optional.empty(),
                Optional.of(VIEW_OWNER),
                false);

        ConnectorMaterializedViewDefinition materializedView = new ConnectorMaterializedViewDefinition(
                "SELECT * FROM local.tiny.nation",
                Optional.empty(),
                Optional.empty(),
                Optional.empty(),
                ImmutableList.of(
                        new ConnectorMaterializedViewDefinition.Column("nationkey", BigintType.BIGINT.getTypeId()),
                        new ConnectorMaterializedViewDefinition.Column("name", VarcharType.createVarcharType(25).getTypeId()),
                        new ConnectorMaterializedViewDefinition.Column("regionkey", BigintType.BIGINT.getTypeId()),
                        new ConnectorMaterializedViewDefinition.Column("comment", VarcharType.createVarcharType(152).getTypeId())),
                Optional.empty(),
                VIEW_OWNER,
                ImmutableMap.of());

        ConnectorMaterializedViewDefinition freshMaterializedView = new ConnectorMaterializedViewDefinition(
                "SELECT * FROM local.tiny.nation",
                Optional.of(new CatalogSchemaTableName("local", "tiny", "nation")),
                Optional.empty(),
                Optional.empty(),
                ImmutableList.of(
                        new ConnectorMaterializedViewDefinition.Column("nationkey", BigintType.BIGINT.getTypeId()),
                        new ConnectorMaterializedViewDefinition.Column("name", VarcharType.createVarcharType(25).getTypeId()),
                        new ConnectorMaterializedViewDefinition.Column("regionkey", BigintType.BIGINT.getTypeId()),
                        new ConnectorMaterializedViewDefinition.Column("comment", VarcharType.createVarcharType(152).getTypeId())),
                Optional.empty(),
                VIEW_OWNER,
                ImmutableMap.of());

        MockConnectorFactory mock = MockConnectorFactory.builder()
                .withGetViews((s, prefix) -> ImmutableMap.of(
                        new SchemaTableName("default", "nation_view"), view))
                .withGetMaterializedViews((s, prefix) -> ImmutableMap.of(
                        new SchemaTableName("default", "nation_materialized_view"), materializedView,
                        new SchemaTableName("default", "nation_fresh_materialized_view"), freshMaterializedView))
                .build();

        runner.createCatalog(MOCK_CATALOG, mock, ImmutableMap.of());

        assertions = new QueryAssertions(runner);
        accessControl = assertions.getQueryRunner().getAccessControl();
    }

    @AfterClass(alwaysRun = true)
    public void teardown()
    {
        assertions.close();
        assertions = null;
    }

    @Test
    public void testSimpleMask()
    {
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "custkey",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "-custkey"));
        assertThat(assertions.query("SELECT custkey FROM orders WHERE orderkey = 1")).matches("VALUES BIGINT '-370'");

        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "custkey",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "NULL"));
        assertThat(assertions.query("SELECT custkey FROM orders WHERE orderkey = 1")).matches("VALUES CAST(NULL AS BIGINT)");
    }

    @Test
    public void testMultipleMasksOnSameColumn()
    {
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "custkey",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "-custkey"));

        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "custkey",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "custkey * 2"));

        assertThat(assertions.query("SELECT custkey FROM orders WHERE orderkey = 1")).matches("VALUES BIGINT '-740'");
    }

    @Test
    public void testMultipleMasksOnDifferentColumns()
    {
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "custkey",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "-custkey"));

        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderstatus",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "'X'"));

        assertThat(assertions.query("SELECT custkey, orderstatus FROM orders WHERE orderkey = 1"))
                .matches("VALUES (BIGINT '-370', 'X')");
    }

    @Test
    public void testReferenceInUsingClause()
    {
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "IF(orderkey = 1, -orderkey)"));

        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "lineitem"),
                "orderkey",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "IF(orderkey = 1, -orderkey)"));

        assertThat(assertions.query("SELECT count(*) FROM orders JOIN lineitem USING (orderkey)")).matches("VALUES BIGINT '6'");
    }

    @Test
    public void testCoercibleType()
    {
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "clerk",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "CAST(clerk AS VARCHAR(5))"));
        assertThat(assertions.query("SELECT clerk FROM orders WHERE orderkey = 1")).matches("VALUES CAST('Clerk' AS VARCHAR(15))");
    }

    @Test
    public void testSubquery()
    {
        // uncorrelated
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "clerk",
                USER,
                new ViewExpression(USER, Optional.of(CATALOG), Optional.of("tiny"), "(SELECT cast(max(name) AS VARCHAR(15)) FROM nation)"));
        assertThat(assertions.query("SELECT clerk FROM orders WHERE orderkey = 1")).matches("VALUES CAST('VIETNAM' AS VARCHAR(15))");

        // correlated
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "clerk",
                USER,
                new ViewExpression(USER, Optional.of(CATALOG), Optional.of("tiny"), "(SELECT cast(max(name) AS VARCHAR(15)) FROM nation WHERE nationkey = orderkey)"));
        assertThat(assertions.query("SELECT clerk FROM orders WHERE orderkey = 1")).matches("VALUES CAST('ARGENTINA' AS VARCHAR(15))");
    }

    @Test
    public void testMaterializedView()
    {
        // mask materialized view columns
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(MOCK_CATALOG, "default", "nation_fresh_materialized_view"),
                "name",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "reverse(name)"));
        accessControl.columnMask(
                new QualifiedObjectName(MOCK_CATALOG, "default", "nation_materialized_view"),
                "name",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "reverse(name)"));

        assertThat(assertions.query(
                Session.builder(SESSION)
                        .setIdentity(Identity.forUser(USER).build())
                        .build(),
                "SELECT name FROM mock.default.nation_fresh_materialized_view WHERE nationkey = 1"))
                .matches("VALUES CAST('ANITNEGRA' AS VARCHAR(25))");

        assertThat(assertions.query(
                Session.builder(SESSION)
                        .setIdentity(Identity.forUser(USER).build())
                        .build(),
                "SELECT name FROM mock.default.nation_materialized_view WHERE nationkey = 1"))
                .matches("VALUES CAST('ANITNEGRA' AS VARCHAR(25))");
    }

    @Test
    public void testView()
    {
        // mask on the underlying table for view owner when running query as different user
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "nation"),
                "name",
                VIEW_OWNER,
                new ViewExpression(VIEW_OWNER, Optional.empty(), Optional.empty(), "reverse(name)"));

        assertThat(assertions.query(
                Session.builder(SESSION)
                        .setIdentity(Identity.forUser(RUN_AS_USER).build())
                        .build(),
                "SELECT name FROM mock.default.nation_view WHERE nationkey = 1"))
                .matches("VALUES CAST('ANITNEGRA' AS VARCHAR(25))");

        // mask on the underlying table for view owner when running as themselves
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "nation"),
                "name",
                VIEW_OWNER,
                new ViewExpression(VIEW_OWNER, Optional.of(CATALOG), Optional.of("tiny"), "reverse(name)"));

        assertThat(assertions.query(
                Session.builder(SESSION)
                        .setIdentity(Identity.forUser(VIEW_OWNER).build())
                        .build(),
                "SELECT name FROM mock.default.nation_view WHERE nationkey = 1"))
                .matches("VALUES CAST('ANITNEGRA' AS VARCHAR(25))");

        // mask on the underlying table for user running the query (different from view owner) should not be applied
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "nation"),
                "name",
                RUN_AS_USER,
                new ViewExpression(RUN_AS_USER, Optional.of(CATALOG), Optional.of("tiny"), "reverse(name)"));

        assertThat(assertions.query(
                Session.builder(SESSION)
                        .setIdentity(Identity.forUser(RUN_AS_USER).build())
                        .build(),
                "SELECT name FROM mock.default.nation_view WHERE nationkey = 1"))
                .matches("VALUES CAST('ARGENTINA' AS VARCHAR(25))");

        // mask on the view
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(MOCK_CATALOG, "default", "nation_view"),
                "name",
                USER,
                new ViewExpression(USER, Optional.of(CATALOG), Optional.of("tiny"), "reverse(name)"));
        assertThat(assertions.query("SELECT name FROM mock.default.nation_view WHERE nationkey = 1")).matches("VALUES CAST('ANITNEGRA' AS VARCHAR(25))");
    }

    @Test
    public void testTableReferenceInWithClause()
    {
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "custkey",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "-custkey"));
        assertThat(assertions.query("WITH t AS (SELECT custkey FROM orders WHERE orderkey = 1) SELECT * FROM t")).matches("VALUES BIGINT '-370'");
    }

    @Test
    public void testOtherSchema()
    {
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                USER,
                new ViewExpression(USER, Optional.of(CATALOG), Optional.of("sf1"), "(SELECT count(*) FROM customer)")); // count is 15000 only when evaluating against sf1
        assertThat(assertions.query("SELECT max(orderkey) FROM orders")).matches("VALUES BIGINT '150000'");
    }

    @Test
    public void testDifferentIdentity()
    {
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                RUN_AS_USER,
                new ViewExpression(RUN_AS_USER, Optional.of(CATALOG), Optional.of("tiny"), "100"));

        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                USER,
                new ViewExpression(RUN_AS_USER, Optional.of(CATALOG), Optional.of("tiny"), "(SELECT sum(orderkey) FROM orders)"));

        assertThat(assertions.query("SELECT max(orderkey) FROM orders")).matches("VALUES BIGINT '1500000'");
    }

    @Test
    public void testRecursion()
    {
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                USER,
                new ViewExpression(USER, Optional.of(CATALOG), Optional.of("tiny"), "(SELECT orderkey FROM orders)"));

        assertThatThrownBy(() -> assertions.query("SELECT orderkey FROM orders"))
                .hasMessageMatching(".*\\QColumn mask for 'local.tiny.orders.orderkey' is recursive\\E.*");

        // different reference style to same table
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                USER,
                new ViewExpression(USER, Optional.of(CATALOG), Optional.of("tiny"), "(SELECT orderkey FROM local.tiny.orders)"));

        assertThatThrownBy(() -> assertions.query("SELECT orderkey FROM orders"))
                .hasMessageMatching(".*\\QColumn mask for 'local.tiny.orders.orderkey' is recursive\\E.*");

        // mutual recursion
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                RUN_AS_USER,
                new ViewExpression(RUN_AS_USER, Optional.of(CATALOG), Optional.of("tiny"), "(SELECT orderkey FROM orders)"));

        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                USER,
                new ViewExpression(RUN_AS_USER, Optional.of(CATALOG), Optional.of("tiny"), "(SELECT orderkey FROM orders)"));

        assertThatThrownBy(() -> assertions.query("SELECT orderkey FROM orders"))
                .hasMessageMatching(".*\\QColumn mask for 'local.tiny.orders.orderkey' is recursive\\E.*");
    }

    @Test
    public void testLimitedScope()
    {
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "customer"),
                "custkey",
                USER,
                new ViewExpression(USER, Optional.of(CATALOG), Optional.of("tiny"), "orderkey"));
        assertThatThrownBy(() -> assertions.query(
                "SELECT (SELECT min(custkey) FROM customer WHERE customer.custkey = orders.custkey) FROM orders"))
                .hasMessage("line 1:34: Invalid column mask for 'local.tiny.customer.custkey': Column 'orderkey' cannot be resolved");
    }

    @Test
    public void testSqlInjection()
    {
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "nation"),
                "name",
                USER,
                new ViewExpression(USER, Optional.of(CATALOG), Optional.of("tiny"), "(SELECT name FROM region WHERE regionkey = 0)"));
        assertThat(assertions.query(
                "WITH region(regionkey, name) AS (VALUES (0, 'ASIA'))" +
                        "SELECT name FROM nation ORDER BY name LIMIT 1"))
                .matches("VALUES CAST('AFRICA' AS VARCHAR(25))"); // if sql-injection would work then query would return ASIA
    }

    @Test
    public void testInvalidMasks()
    {
        // parse error
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                USER,
                new ViewExpression(RUN_AS_USER, Optional.of(CATALOG), Optional.of("tiny"), "$$$"));

        assertThatThrownBy(() -> assertions.query("SELECT orderkey FROM orders"))
                .hasMessage("line 1:22: Invalid column mask for 'local.tiny.orders.orderkey': mismatched input '$'. Expecting: <expression>");

        // unknown column
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                USER,
                new ViewExpression(RUN_AS_USER, Optional.of(CATALOG), Optional.of("tiny"), "unknown_column"));

        assertThatThrownBy(() -> assertions.query("SELECT orderkey FROM orders"))
                .hasMessage("line 1:22: Invalid column mask for 'local.tiny.orders.orderkey': Column 'unknown_column' cannot be resolved");

        // invalid type
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                USER,
                new ViewExpression(RUN_AS_USER, Optional.of(CATALOG), Optional.of("tiny"), "'foo'"));

        assertThatThrownBy(() -> assertions.query("SELECT orderkey FROM orders"))
                .hasMessage("line 1:22: Expected column mask for 'local.tiny.orders.orderkey' to be of type bigint, but was varchar(3)");

        // aggregation
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                USER,
                new ViewExpression(RUN_AS_USER, Optional.of(CATALOG), Optional.of("tiny"), "count(*) > 0"));

        assertThatThrownBy(() -> assertions.query("SELECT orderkey FROM orders"))
                .hasMessage("line 1:10: Column mask for 'orders.orderkey' cannot contain aggregations, window functions or grouping operations: [count(*)]");

        // window function
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                USER,
                new ViewExpression(RUN_AS_USER, Optional.of(CATALOG), Optional.of("tiny"), "row_number() OVER () > 0"));

        assertThatThrownBy(() -> assertions.query("SELECT orderkey FROM orders"))
                .hasMessage("line 1:22: Column mask for 'orders.orderkey' cannot contain aggregations, window functions or grouping operations: [row_number() OVER ()]");

        // grouping function
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                USER,
                new ViewExpression(USER, Optional.of(CATALOG), Optional.of("tiny"), "grouping(orderkey) = 0"));

        assertThatThrownBy(() -> assertions.query("SELECT orderkey FROM orders"))
                .hasMessage("line 1:20: Column mask for 'orders.orderkey' cannot contain aggregations, window functions or grouping operations: [GROUPING (orderkey)]");
    }

    @Test
    public void testShowStats()
    {
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                USER,
                new ViewExpression(USER, Optional.of(CATALOG), Optional.of("tiny"), "7"));

        assertThat(assertions.query("SHOW STATS FOR (SELECT * FROM orders)"))
                .containsAll("VALUES " +
                        "(CAST('orderkey' AS varchar), CAST(NULL AS double), 1e0, 0e1, NULL, '7', '7')," +
                        "(CAST('clerk' AS varchar), 15e3, 1e3, 0e1, NULL, CAST(NULL AS varchar), CAST(NULL AS varchar))," +
                        "(NULL, NULL, NULL, NULL, 15e3, NULL, NULL)");
        assertThat(assertions.query("SHOW STATS FOR (SELECT orderkey FROM orders)"))
                .matches("VALUES " +
                        "(CAST('orderkey' AS varchar), CAST(NULL AS double), 1e0, 0e1, NULL, CAST('7' AS varchar), CAST('7' AS varchar))," +
                        "(NULL, NULL, NULL, NULL, 15e3, NULL, NULL)");
        assertThat(assertions.query("SHOW STATS FOR (SELECT clerk FROM orders)"))
                .matches("VALUES " +
                        "(CAST('clerk' AS varchar), 15e3, 1e3, 0e1, NULL, CAST(NULL AS varchar), CAST(NULL AS varchar))," +
                        "(NULL, NULL, NULL, NULL, 15e3, NULL, NULL)");
    }

    @Test
    public void testJoin()
    {
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                USER,
                new ViewExpression(USER, Optional.of(CATALOG), Optional.of("tiny"), "orderkey + 1"));
        assertThat(assertions.query("SELECT count(*) FROM orders JOIN orders USING (orderkey)")).matches("VALUES BIGINT '15000'");

        // multiple masks
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "-orderkey"));

        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "orderkey * 2"));

        assertThat(assertions.query("SELECT count(*) FROM orders JOIN orders USING (orderkey)")).matches("VALUES BIGINT '15000'");
    }

    @Test
    public void testColumnMaskingUsingRestrictedColumn()
    {
        accessControl.reset();
        accessControl.deny(privilege("orders.custkey", SELECT_COLUMN));
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "orderkey",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "custkey"));
        assertThatThrownBy(() -> assertions.query("SELECT orderkey FROM orders"))
                .hasMessage("Access Denied: Cannot select from columns [orderkey, custkey] in table or view local.tiny.orders");
    }

    @Test
    public void testInsertWithColumnMasking()
    {
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "clerk",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "clerk"));
        assertThatThrownBy(() -> assertions.query("INSERT INTO orders SELECT * FROM orders"))
                .hasMessage("Insert into table with column masks is not supported");
    }

    @Test
    public void testDeleteWithColumnMasking()
    {
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "clerk",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "clerk"));
        assertThatThrownBy(() -> assertions.query("DELETE FROM orders"))
                .hasMessage("line 1:1: Delete from table with column mask");
    }

    @Test
    public void testUpdateWithColumnMasking()
    {
        accessControl.reset();
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "clerk",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "clerk"));
        assertThatThrownBy(() -> assertions.query("UPDATE orders SET clerk = 'X'"))
                .hasMessage("line 1:1: Updating a table with column masks is not supported");
        assertThatThrownBy(() -> assertions.query("UPDATE orders SET orderkey = -orderkey"))
                .hasMessage("line 1:1: Updating a table with column masks is not supported");
        assertThatThrownBy(() -> assertions.query("UPDATE orders SET clerk = 'X', orderkey = -orderkey"))
                .hasMessage("line 1:1: Updating a table with column masks is not supported");
    }

    @Test
    public void testNotReferencedAndDeniedColumnMasking()
    {
        // mask on not used varchar column
        accessControl.reset();
        accessControl.deny(privilege("orders.clerk", SELECT_COLUMN));
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "clerk",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "clerk"));
        assertThat(assertions.query("SELECT orderkey FROM orders WHERE orderkey = 1")).matches("VALUES BIGINT '1'");

        // mask on long column
        accessControl.reset();
        accessControl.deny(privilege("orders.totalprice", SELECT_COLUMN));
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "totalprice",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "totalprice"));
        assertThat(assertions.query("SELECT orderkey FROM orders WHERE orderkey = 1")).matches("VALUES BIGINT '1'");

        // mask on not used varchar column with subquery masking
        accessControl.reset();
        accessControl.deny(privilege("orders.clerk", SELECT_COLUMN));
        accessControl.deny(privilege("orders.orderstatus", SELECT_COLUMN));
        accessControl.columnMask(
                new QualifiedObjectName(CATALOG, "tiny", "orders"),
                "clerk",
                USER,
                new ViewExpression(USER, Optional.empty(), Optional.empty(), "(SELECT orderstatus FROM local.tiny.orders)"));
        assertThat(assertions.query("SELECT orderkey FROM orders WHERE orderkey = 1")).matches("VALUES BIGINT '1'");
    }
}


text:
const char* backend::detail::get_path(const char* env_name) {
    char* path = getenv(env_name);
    if (path != nullptr) {
        return path;
    } else {
        return "";
    }
}

redpajama_set_name: RedPajamaGithub


text:
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->statusBar->addPermanentWidget(new QLabel("Anidater v0.1.0.3"));

    //Set pointers
    m_currentScrobbler = nullptr;
    m_pPluginActionMapper = new QSignalMapper(this);
    m_pPluginMessagesMapper = new QSignalMapper(this);

    //Load previous gui state
    QSettings settings;
    setWindowState((Qt::WindowState) settings.value("gui/state", false).toInt());
    QRect screenSize = QApplication::desktop()->availableGeometry();
    setGeometry(settings.value("gui/geometry", QRect(screenSize.width() / 3, screenSize.height() / 3, screenSize.width() / 3, screenSize.height() / 3)).toRect());
    qDebug() << "Loaded previous gui state";

    //Connect signals
    connect(ui->actionExit, SIGNAL(triggered()), this, SLOT(close()));
    connect(m_pPluginActionMapper, SIGNAL(mapped(int)), this, SLOT(openDialog(int)), Qt::UniqueConnection);
    connect(m_pPluginMessagesMapper, SIGNAL(mapped(int)), this, SLOT(displayStatusMessage(int)));

    loadPlugins();
    qDebug() << "MainWindow loaded";
}

MainWindow::~MainWindow()
{
    QSettings settings;
    settings.setValue("gui/state", (int) windowState());
    settings.setValue("gui/geometry", geometry());

    delete m_pPluginActionMapper;
    qDeleteAll(m_lScrobblers);
    m_lScrobblers.clear();
    delete ui;
}

void MainWindow::openDialog(int i)
{
    ScrobblerInterface *iScrobbler = m_lScrobblers.at(i);
    if(iScrobbler->opendialogConnect())
    {
        qInfo() << "Successfully connected to " << iScrobbler->getSiteName();
        displayStatusMessage("Successfully connected to " + iScrobbler->getSiteName());
    }
}

void MainWindow::displayStatusMessage(QString message)
{
    ui->statusBar->showMessage(message, message.length() * 67 + 2000);
}

void MainWindow::loadPlugins()
{
    QDir m_pPluginsDir = QDir(qApp->applicationDirPath());

#if defined(Q_OS_WIN)
    if (m_pPluginsDir.dirName().toLower() == "debug" || m_pPluginsDir.dirName().toLower() == "release")
        m_pPluginsDir.cdUp();
#elif defined(Q_OS_MAC)
    if (pluginsDir.dirName() == "MacOS") {
        pluginsDir.cdUp();
        pluginsDir.cdUp();
        pluginsDir.cdUp();
    }
#endif
    m_pPluginsDir.cd("plugins");

    ui->menuConnect->clear();
    int nbPlugins = 0;

    qDebug() << "Searching for plugin file(s)";

    foreach (QString fileName, m_pPluginsDir.entryList(QDir::Files)) {
        QPluginLoader loader(m_pPluginsDir.absoluteFilePath(fileName));
        QObject *plugin = loader.instance();
        if (plugin) {
            ScrobblerInterface *iScrobbler = qobject_cast<ScrobblerInterface *>(plugin);
            if(iScrobbler)
            {
                //TODO Implement refreshing of the plugins
                //IMPL Clear WebsiteList and relaunch function
                //Create and add action in menu
                QAction *pluginAction = ui->menuConnect->addAction(iScrobbler->getSiteName(), m_pPluginActionMapper, SLOT(map()));

                //Set tooltip
                QString tooltip(QString("%1\n\n%2\n\n%3").arg(iScrobbler->getSiteName()).arg(iScrobbler->getSiteDescription()).arg(iScrobbler->getSiteUrl()));
                pluginAction->setWhatsThis(tooltip);
                pluginAction->setToolTip(tooltip);

                //Set the signal mapping
                m_pPluginActionMapper->setMapping(ui->menuConnect->actions().at(nbPlugins), nbPlugins);
                connect(plugin, SIGNAL(statusMessage(QString)), this, SLOT(displayStatusMessage(QString)), Qt::UniqueConnection);

                m_lScrobblers.append(iScrobbler);

                nbPlugins++;
            }
        }
    }

    if(nbPlugins > 0)
    {
        m_currentScrobbler = m_lScrobblers.at(0);
    }
    else {
        qWarning() << "No plugin found";
        m_currentScrobbler = nullptr;
    }
}


text:
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace Sandwych.Reporting
{
    public interface IDocument
    {
        bool IsNew { get; }
        byte[] AsBuffer();
        void Save(Stream outStream);
        Task SaveAsync(Stream outStream);
    }
}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;

namespace csCommon.Plugins.MgrsGrid
{
    /// <summary>
    /// The Cohen Sutherland line clipping algorithm
    /// http://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm
    /// http://www.bluetoque.ca/2012/01/cohen-sutherland-line-clipping/
    /// </summary>
   public static class SutherlandHodgman
    {
        #region Class: Edge

        /// <summary>
        /// This represents a line segment
        /// </summary>
        private class Edge
        {
            public Edge(Point from, Point to)
            {
                this.From = from;
                this.To = to;
            }

            public readonly Point From;
            public readonly Point To;
        }

        #endregion

        /// <summary>
        /// This clips the subject polygon against the clip polygon (gets the intersection of the two polygons)
        /// </summary>
        /// <remarks>
        /// Based on the psuedocode from:
        /// http://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman
        /// </remarks>
        /// <param name="subjectPoly">Can be concave or convex</param>
        /// <param name="clipPoly">Must be convex</param>
        /// <returns>The intersection of the two polygons (or null)</returns>
        public static Point[] GetIntersectedPolygon(Point[] subjectPoly, Point[] clipPoly)
        {
            if (subjectPoly.Length < 3 || clipPoly.Length < 3)
            {
                throw new ArgumentException(string.Format("The polygons passed in must have at least 3 points: subject={0}, clip={1}", subjectPoly.Length.ToString(), clipPoly.Length.ToString()));
            }

            List<Point> outputList = subjectPoly.ToList();

            //	Make sure it's clockwise
            if (!IsClockwise(subjectPoly))
            {
                outputList.Reverse();
            }

            //	Walk around the clip polygon clockwise
            foreach (Edge clipEdge in IterateEdgesClockwise(clipPoly))
            {
                List<Point> inputList = outputList.ToList();		//	clone it
                outputList.Clear();

                if (inputList.Count == 0)
                {
                    //	Sometimes when the polygons don't intersect, this list goes to zero.  Jump out to avoid an index out of range exception
                    break;
                }

                Point S = inputList[inputList.Count - 1];

                foreach (Point E in inputList)
                {
                    if (IsInside(clipEdge, E))
                    {
                        if (!IsInside(clipEdge, S))
                        {
                            Point? point = GetIntersect(S, E, clipEdge.From, clipEdge.To);
                            if (point == null)
                            {
                                throw new ApplicationException("Line segments don't intersect");		//	may be colinear, or may be a bug
                            }
                            else
                            {
                                outputList.Add(point.Value);
                            }
                        }

                        outputList.Add(E);
                    }
                    else if (IsInside(clipEdge, S))
                    {
                        Point? point = GetIntersect(S, E, clipEdge.From, clipEdge.To);
                        if (point == null)
                        {
                            throw new ApplicationException("Line segments don't intersect");		//	may be colinear, or may be a bug
                        }
                        else
                        {
                            outputList.Add(point.Value);
                        }
                    }

                    S = E;
                }
            }

            //	Exit Function
            return outputList.ToArray();
        }

        #region Private Methods

        /// <summary>
        /// This iterates through the edges of the polygon, always clockwise
        /// </summary>
        private static IEnumerable<Edge> IterateEdgesClockwise(Point[] polygon)
        {
            if (IsClockwise(polygon))
            {
                #region Already clockwise

                for (int cntr = 0; cntr < polygon.Length - 1; cntr++)
                {
                    yield return new Edge(polygon[cntr], polygon[cntr + 1]);
                }

                yield return new Edge(polygon[polygon.Length - 1], polygon[0]);

                #endregion
            }
            else
            {
                #region Reverse

                for (int cntr = polygon.Length - 1; cntr > 0; cntr--)
                {
                    yield return new Edge(polygon[cntr], polygon[cntr - 1]);
                }

                yield return new Edge(polygon[0], polygon[polygon.Length - 1]);

                #endregion
            }
        }

        /// <summary>
        /// Returns the intersection of the two lines (line segments are passed in, but they are treated like infinite lines)
        /// </summary>
        /// <remarks>
        /// Got this here:
        /// http://stackoverflow.com/questions/14480124/how-do-i-detect-triangle-and-rectangle-intersection
        /// </remarks>
        private static Point? GetIntersect(Point line1From, Point line1To, Point line2From, Point line2To)
        {
            Vector direction1 = line1To - line1From;
            Vector direction2 = line2To - line2From;
            double dotPerp = (direction1.X * direction2.Y) - (direction1.Y * direction2.X);

            // If it's 0, it means the lines are parallel so have infinite intersection points
            if (IsNearZero(dotPerp))
            {
                return null;
            }

            Vector c = line2From - line1From;
            double t = (c.X * direction2.Y - c.Y * direction2.X) / dotPerp;
            //if (t < 0 || t > 1)
            //{
            //    return null;		//	lies outside the line segment
            //}

            //double u = (c.X * direction1.Y - c.Y * direction1.X) / dotPerp;
            //if (u < 0 || u > 1)
            //{
            //    return null;		//	lies outside the line segment
            //}

            //	Return the intersection point
            return line1From + (t * direction1);
        }

        private static bool IsInside(Edge edge, Point test)
        {
            bool? isLeft = IsLeftOf(edge, test);
            if (isLeft == null)
            {
                //	Colinear points should be considered inside
                return true;
            }

            return !isLeft.Value;
        }
        private static bool IsClockwise(Point[] polygon)
        {
            for (int cntr = 2; cntr < polygon.Length; cntr++)
            {
                bool? isLeft = IsLeftOf(new Edge(polygon[0], polygon[1]), polygon[cntr]);
                if (isLeft != null)		//	some of the points may be colinear.  That's ok as long as the overall is a polygon
                {
                    return !isLeft.Value;
                }
            }

            throw new ArgumentException("All the points in the polygon are colinear");
        }

        /// <summary>
        /// Tells if the test point lies on the left side of the edge line
        /// </summary>
        private static bool? IsLeftOf(Edge edge, Point test)
        {
            Vector tmp1 = edge.To - edge.From;
            Vector tmp2 = test - edge.To;

            double x = (tmp1.X * tmp2.Y) - (tmp1.Y * tmp2.X);		//	dot product of perpendicular?

            if (x < 0)
            {
                return false;
            }
            else if (x > 0)
            {
                return true;
            }
            else
            {
                //	Colinear points;
                return null;
            }
        }

        private static bool IsNearZero(double testValue)
        {
            return Math.Abs(testValue) <= .000000001d;
        }

        #endregion
    }

}


text:
import numpy as np
from scipy.cluster import hierarchy as hc
from clustrous._periodic_cluster import get_cluster_list

def cluster(r, r_max):
    """
    Group a set of points into distinct sets, based on their Euclidean
    distance.

    Uses the single-linkage criterion, meaning that if the distance between two
    points is less than the cut-off distance, they are in the same cluster.

    Parameters
    ----------
    r: np.ndarray[ndim=2, shape=(n, d)]
        The points to cluster. `n` is the
        number of points, `d` is the number of dimensions. r_max: float How
        distant points can be while still placed in the same cluster.

    Returns
    -------
    labels: np.ndarray[ndim=1, shape=(n,), dtype=np.int]
        For each point, an
        integer labelling its cluster. Points with the same integer belong to
        the same cluster.
    """
    linkage_matrix = hc.linkage(r, method='single', metric='sqeuclidean')
    return hc.fcluster(linkage_matrix, t=r_max ** 2, criterion='distance')

def cluster_periodic(r, r_max, L):
    """
    Group a set of points into distinct sets, based on their Euclidean
    distance, in a periodic space.

    Uses the single-linkage criterion, meaning that if the distance between two
    points is less than the cut-off distance, they are in the same cluster.

    Parameters
    ----------
    r: np.ndarray[ndim=2, shape=(n, d)]
        The points to cluster. `n` is the number of points,
        `d` is the number of dimensions.
    r_max: float
        How distant points can be while still placed in the same cluster.
    L: float
        The size of the system.

    Returns
    -------
    labels: np.ndarray[ndim=1, shape=(n,), dtype=np.int]
        For each point, an integer labelling its cluster.
        Points with the same integer belong to the same cluster.
    """
    # Get a linked list where a closed loop indicates a single cluster.
    linked_list = get_cluster_list(r, r_max, L)
    # Convert from Fortran 1-based to Python 0-based indexing.
    linked_list -= 1
    return _get_labels(linked_list)

def n_clusters(labels):
    """Get the number of clusters from a set of labels."""
    return len(set(labels))

def cluster_sizes(labels):
    """Get the number of points in each cluster, sorted by label."""
    if labels.min() == 0:
        return np.bincount(labels)
    elif labels.min() == 1:
        return np.bincount(labels - 1)
    else:
        raise Exception

def biggest_cluster_fraction(clust_sizes):
    """Calculate the fraction of points that lie in the biggest cluster.

    The measure to some extent indicates the degree to which points belong to
    a few clusters. However, it is a bad measure, because it gives results that
    are counter-intuitive. For example, these distributions all give the same
    result:

    - [n - 10, 10]
    - [n - 10, 5, 5]
    - [n - 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

    Parameters
    ----------
    clust_sizes: list[int]
        The number of points in each cluster.

    Returns
    -------
    m: float
        Cluster measure.
    """
    clust_sizes = np.array(clust_sizes)
    return clust_sizes.max() / float(clust_sizes.sum())

def _clumpiness(n_cluster, n_tot):
    frac = n_cluster / n_tot
    clumpiness = (n_cluster - 1.0) / (n_tot - 1.0)
    return frac * clumpiness

def clumpiness(clust_sizes):
    """Calculate how 'clumpy' a set of clustered points are.

    The measure indicates the degree to which points belong to a few clusters.
    This is calculated by finding the clumpiness of a point in each cluster,
    which is its contribution to the overall population. This is then
    weighted by the number of points with that clumpiness value, and the sum
    taken of this over all clusters.

    This is chosen to give intuitively sensible orderings to distributions of
    points. For example, these are examples of its values for some populations:

    - [6]: 1
    - [5, 1]: 0.67
    - [4, 2]: 0.47
    - [4, 1, 1]: 0.4
    - [3, 3]: 0.4
    - [2, 1, 1, 1, 1, 1]: 0.05
    - [1, 1, 1, 1, 1, 1]: 0

    Parameters
    ----------
    clust_sizes: list[int]
        The number of points in each cluster.

    Returns
    -------
    k: float
        Clumpiness measure.
    """
    return np.sum(_clumpiness(clust_sizes, float(clust_sizes.sum())))

def _get_labels(linked_list):
    """Convert clusters represented as a linked list into a labels array.

    For example, `[1, 0, 2, 3]` represents a system where the first two samples
    are in a single cluster, because the first points to the second, then the
    second points to the first. The last two point to themselves, and are thus
    in a cluster with a single sample.

    This function converts such a list into an array of integers, whose entries
    begin at zero and increase consecutively. Each integer identifies a sample
    as belonging to a particular cluster, labelled by that integer.

    Parameters
    ----------
    linked_list: list[int]
        List of integers whose minimum must be zero,
        and maximum must be `len(linked_list)`.

    Returns
    -------
    labels: np.ndarray[dtype=int, shape=(len(linked_list),)]
        Cluster labels, starting at zero.
    """
    # `-1` indicates a sample that has not been visited yet.
    labels = np.full([len(linked_list)], -1, dtype=np.int)

    # Initial label is zero.
    label = 0
    # Each unvisited index represents a new cluster.
    for i_base in range(len(linked_list)):
        if labels[i_base] == -1:
            i = i_base
            # Iterate through the linked samples setting their label.
            while True:
                labels[i] = label
                i_next = linked_list[i]
                # When we arrive back at the start,
                # we are finished with that cluster.
                if i_next == i_base:
                    break
                i = i_next
            label += 1
    return labels


text:
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models

class Migration(SchemaMigration):

    #depends_on = (
    #    ("players", "0001_initial"),
    #    ("comms", "0001_initial"),
    #)

    def forwards(self, orm):

        # Adding model 'Msg'
        db.create_table('comms_msg', (
            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
            ('db_sender', self.gf('django.db.models.fields.related.ForeignKey')(related_name='sender_set', to=orm['players.PlayerDB'])),
            ('db_receivers', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
            ('db_channels', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
            ('db_message', self.gf('django.db.models.fields.TextField')()),
            ('db_date_sent', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
            ('db_hide_from_sender', self.gf('django.db.models.fields.BooleanField')(default=False)),
            ('db_hide_from_receivers', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
            ('db_hide_from_channels', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
            ('db_lock_storage', self.gf('django.db.models.fields.TextField')(null=True)),
        ))
        db.send_create_signal('comms', ['Msg'])

        # Adding model 'Channel'
        db.create_table('comms_channel', (
            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
            ('db_key', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)),
            ('db_desc', self.gf('django.db.models.fields.CharField')(max_length=80, null=True, blank=True)),
            ('db_aliases', self.gf('django.db.models.fields.CharField')(max_length=255)),
            ('db_keep_log', self.gf('django.db.models.fields.BooleanField')(default=True)),
            ('db_lock_storage', self.gf('django.db.models.fields.TextField')(blank=True)),
        ))
        db.send_create_signal('comms', ['Channel'])

        # Adding model 'ChannelConnection'
        db.create_table('comms_channelconnection', (
            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
            ('db_player', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['players.PlayerDB'])),
            ('db_channel', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['comms.Channel'])),
        ))
        db.send_create_signal('comms', ['ChannelConnection'])

    def backwards(self, orm):

        # Deleting model 'Msg'
        db.delete_table('comms_msg')

        # Deleting model 'Channel'
        db.delete_table('comms_channel')

        # Deleting model 'ChannelConnection'
        db.delete_table('comms_channelconnection')

    models = {
        'auth.group': {
            'Meta': {'object_name': 'Group'},
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
        },
        'auth.permission': {
            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
        },
        'auth.user': {
            'Meta': {'object_name': 'User'},
            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
        },
        'comms.channel': {
            'Meta': {'object_name': 'Channel'},
            'db_aliases': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
            'db_desc': ('django.db.models.fields.CharField', [], {'max_length': '80', 'null': 'True', 'blank': 'True'}),
            'db_keep_log': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
            'db_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
            'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
        },
        'comms.channelconnection': {
            'Meta': {'object_name': 'ChannelConnection'},
            'db_channel': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['comms.Channel']"}),
            'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['players.PlayerDB']"}),
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
        },
        'comms.msg': {
            'Meta': {'object_name': 'Msg'},
            'db_channels': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
            'db_date_sent': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
            'db_hide_from_channels': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
            'db_hide_from_receivers': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
            'db_hide_from_sender': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
            'db_lock_storage': ('django.db.models.fields.TextField', [], {'null': 'True'}),
            'db_message': ('django.db.models.fields.TextField', [], {}),
            'db_receivers': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
            'db_sender': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sender_set'", 'to': "orm['players.PlayerDB']"}),
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
        },
        'contenttypes.contenttype': {
            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
        },
        'objects.objectdb': {
            'Meta': {'object_name': 'ObjectDB'},
            'db_cmdset_storage': ('django.db.models.fields.TextField', [], {'null': 'True'}),
            'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
            'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
            'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
            'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
            'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
            'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
            'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}),
            'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
        },
        'players.playerdb': {
            'Meta': {'object_name': 'PlayerDB'},
            'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
            'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
            'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
            'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']", 'null': 'True'}),
            'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
            'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
        }
    }

    complete_apps = ['comms']


text:
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.shortcuts import redirect
from django.template import Context, loader
from django.views.generic import UpdateView, DetailView
from django.views.generic.edit import FormView
from django.views.generic.list import ListView

from wye.base.constants import WorkshopStatus
from wye.base.emailer_html import send_email_to_list, send_email_to_id
from wye.organisations.models import Organisation
from wye.profiles.models import Profile
from wye.workshops.models import Workshop

from .forms import UserProfileForm, ContactUsForm

class ProfileView(DetailView):
    model = Profile
    template_name = 'profile/index.html'
    slug_field = 'user__username'

    def get_context_data(self, *args, **kwargs):
        slug = self.kwargs['slug']
        self.object = self.model.objects.get(user__username=slug)
        context = super(
            ProfileView, self).get_context_data(*args, **kwargs)
        return context

class UserDashboard(ListView):
    model = Profile
    template_name = 'profile/dashboard.html'

    def dispatch(self, request, *args, **kwargs):
        user_profile = Profile.objects.get(
            user__id=self.request.user.id)
        if not user_profile.get_user_type:
            return redirect('profiles:profile-edit', slug=request.user.username)
        return super(UserDashboard, self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(UserDashboard, self).get_context_data(**kwargs)
        user_profile = Profile.objects.get(user=self.request.user)
        workshop_all = Workshop.objects.all()
        accept_workshops = workshop_all.filter(
            status=WorkshopStatus.ACCEPTED)
        requested_workshops = workshop_all.filter(
            status=WorkshopStatus.REQUESTED)
        organisation_all = Organisation.objects.all()
        for each_type in user_profile.get_user_type:
            if each_type == 'tutor':
                context['is_tutor'] = True
                context['workshop_requested_tutor'] = accept_workshops.filter(
                    presenter=self.request.user)
                context['workshop_completed_tutor'] = requested_workshops.filter(
                    presenter=self.request.user)
            if each_type == 'lead':
                context['is_regional_lead'] = True
                context['workshops_accepted_under_rl'] = accept_workshops
                context['workshops_pending_under_rl'] = requested_workshops
                context['interested_tutors'] = Profile.objects.filter(
                    usertype__slug='tutor',
                    interested_locations__name__in=user_profile.get_interested_locations).exclude(
                    user=self.request.user).count()
                context['interested_locations'] = organisation_all.filter(
                    location__name__in=user_profile.get_interested_locations).count()

            if each_type == 'poc':
                context['is_college_poc'] = True
                context['users_organisation'] = organisation_all.filter(
                    user=self.request.user)
                context['workshop_requested_under_poc'] = workshop_all.filter(
                    requester__id__in=organisation_all.values_list(
                        'id', flat=True))
                context['workshops_accepted_under_poc'] = workshop_all.filter(
                    status=WorkshopStatus.ACCEPTED,
                    requester__id__in=organisation_all.values_list(
                        'id', flat=True))

            if each_type == 'admin':
                context['is_admin'] = True
                context['workshops_by_status'] = workshop_all.order_by(
                    'status')
                context['workshops_by_region'] = workshop_all.order_by(
                    'location')

        return context

class ProfileEditView(UpdateView):
    model = Profile
    template_name = 'profile/update.html'
    form_class = UserProfileForm
    slug_field = 'user__username'

    def form_valid(self, form):
        return super(ProfileEditView, self).form_valid(form)

    def get_success_url(self):
        return reverse('profiles:profile-page', kwargs={'slug': self.object.slug})

    def dispatch(self, *args, **kwargs):
        if self.request.user.pk == self.get_object().pk:
            return super(ProfileEditView, self).dispatch(*args, **kwargs)
        else:
            raise PermissionDenied

class ContactFormView(FormView):
    form_class = ContactUsForm
    template_name = 'contact.html'
    success_url = '/thankyou'

    def form_valid(self, form):

        email_context = Context({
            'contact_name': form.cleaned_data['name'],
            'contact_email': form.cleaned_data['email'],
            'comments': form.cleaned_data['comments'],
            'conatct_number': form.cleaned_data['contact_number'],
            'feedback_type': form.cleaned_data['feedback_type']
        })

        subject = "PythonExpress Feedback by %s" % (form.cleaned_data['name'])
        text_body = loader.get_template(
            'email_messages/contactus/message.txt').render(email_context)
        email_body = loader.get_template(
            'email_messages/contactus/message.html').render(email_context)
        user_subject = '[PythonExpress] Feedback Received'
        user_text_body = loader.get_template(
            'email_messages/contactus/message_user.txt').render(email_context)
        user_email_body = loader.get_template(
            'email_messages/contactus/message_user.html').render(email_context)

        try:
            regional_lead = Profile.objects.filter(
                usertype__slug__in=['lead', 'admin']).values_list(
                'user__email', flat=True)
            send_email_to_list(
                subject,
                users_list=regional_lead,
                body=email_body,
                text_body=text_body)

            send_email_to_id(
                user_subject,
                body=user_email_body,
                email_id=form.cleaned_data['email'],
                text_body=user_text_body)
        except Exception as e:
            print(e)

        return super(ContactFormView, self).form_valid(form)


text:
ef-soft-delete
==============
EF Soft Delete is an implementation of Entity Framework's DbContext specifically designed to perform  soft or logical deletes to entities by requiring to have a "Deleted" or "IsDeleted" column in every table.

The class also initiales the DbContext in such a way that only those columns which have their "Deleted" column set to false are returned in every DbSet.

Usage:
You must subclass DbContextBase and define your DBSets in that subclass either in Code First or Database First scenarios.
One caveat, the DbSets should be typed as IDbSet<>.

```C#
namespace MyApp.Data
{
        using Juppir.EfSoftDeleteDbContext;
        public class MyAppDbContext : DbContextbase
        {
                static MyAppDbContext()
                {
                    Database.SetInitializer<MyAppDbContext>(null);
                }
                public MyAppDbContext(string connectionStringName)
                    : base(connectionStringName)
                {
                    Customers = new FilteredDbSet<Customer>(this, c => c.Deleted == false, null);
                }

                public IDbSet<Customer> Customers { get; set; }

                protected override void OnModelCreating(DbModelBuilder modelBuilder)
                {
                  modelBuilder.Configurations.Add(new CustomerMap());
                }
        }
}
```

Also included in the solution are the modified EF Reverse Engineer Code First text templates to generate the same code above when using the EF Power Tools.


text:
from __future__ import division, print_function, unicode_literals
__doc__ = """
Converts old expert 8-bit encodings into Glyphs nice names.
"""

import vanilla, codecs
from AppKit import NSFont
AXtDefault = """
Syntax:
- Freely write comments and empty lines
- Rename: Lines containing a dash (-) followed by a greater sign (>) will trigger glyph renaming, with or without spaces between names
- Recipe: Lines containing glyph recipes with plus (+) and equals (=) will be treated like in Glyph > Add Glyphs... as long as the do not contain any space
- Recipes will overwrite existing glyphs. Renamings will create a number-suffixed glyph if a glyph with the same name already exists.

breve -> kashida-ar
grave -> kashida-ar.alt

A -> hamza-ar
D -> hamzaabove-ar
E -> hamzabelow-ar
C -> highhamza-ar
q -> shadda-ar
s -> shaddaFatha-ar
v -> shaddaFathatan-ar
t -> shaddaDamma-ar
w -> shaddaDammatan-ar
u -> shaddaKasra-ar
x -> shaddaKasratan-ar
p -> kasra-ar
m -> kasratan-ar
n -> fatha-ar
k -> fathatan-ar
o -> damma-ar
l -> dammatan-ar
r -> sukun-ar
y -> wasla-ar
B -> madda-ar

G -> alef-ar
Eacute -> alef-ar.fina

Udieresis -> beh-ar
H -> beh-ar.init
Ntilde -> beh-ar.medi
Odieresis -> beh-ar.fina

I -> tehMarbuta-ar
aacute -> tehMarbuta-ar.fina

adieresis -> teh-ar
J -> teh-ar.init
agrave -> teh-ar.medi
acircumflex -> teh-ar.fina

ccedilla -> theh-ar
K -> theh-ar.init
atilde -> theh-ar.medi
aring -> theh-ar.fina

ecircumflex -> jeem-ar
L -> jeem-ar.init
eacute -> jeem-ar.medi
egrave -> jeem-ar.fina

igrave -> hah-ar
M -> hah-ar.init
edieresis -> hah-ar.medi
iacute -> hah-ar.fina

ntilde -> khah-ar
N -> khah-ar.init
icircumflex -> khah-ar.medi
idieresis -> khah-ar.fina

O -> dal-ar
oacute -> dal-ar.fina

P -> thal-ar
ograve -> thal-ar.fina

Q -> reh-ar
ocircumflex -> reh-ar.fina

R -> zain-ar
otilde -> zain-ar.fina

(for seen, sheen, sad, dad, see further below)

bullet -> tah-ar
W -> tah-ar.init
sterling -> tah-ar.medi
section -> tah-ar.fina

registered -> zah-ar
X -> zah-ar.init
paragraph -> zah-ar.medi
germandbls -> zah-ar.fina

acute -> ain-ar
Y -> ain-ar.init
copyright -> ain-ar.medi
trademark -> ain-ar.fina

AE -> ghain-ar
Z -> ghain-ar.init
dieresis -> ghain-ar.medi
notequal -> ghain-ar.fina

plusminus -> feh-ar
a -> feh-ar.init
Oslash -> feh-ar.medi
infinity -> feh-ar.fina

yen -> qaf-ar
b -> qaf-ar.init
lessequal -> qaf-ar.medi
greaterequal -> qaf-ar.fina

summation -> kaf-ar
c -> kaf-ar.init
mu -> kaf-ar.medi
partialdiff -> kaf-ar.fina

integral -> lam-ar
d -> lam-ar.init
product -> lam-ar.medi
pi -> lam-ar.fina

Omega -> meem-ar
e -> meem-ar.init
ordfeminine -> meem-ar.medi
ordmasculine -> meem-ar.fina

questiondown -> noon-ar
f -> noon-ar.init
ae -> noon-ar.medi
oslash -> noon-ar.fina

radical -> heh-ar
g -> heh-ar.init
exclamdown -> heh-ar.medi
logicalnot -> heh-ar.fina

h -> waw-ar
florin -> waw-ar.fina

i -> alefMaksura-ar
approxequal -> alefMaksura-ar.fina

ellipsis -> yeh-ar
j -> yeh-ar.init
guillemetleft -> yeh-ar.medi
guillemetright -> yeh-ar.fina
guillemotleft -> yeh-ar.medi
guillemotright -> yeh-ar.fina

Ccedilla -> yehHamzaabove-ar
F -> yehHamzaabove-ar.init
Adieresis -> yehHamzaabove-ar.medi
Aring -> yehHamzaabove-ar.fina

ring -> peh-ar
greater -> peh-ar.init
DEL -> peh-ar.medi
dotaccent -> peh-ar.fina

caron -> tcheh-ar
cedilla -> tcheh-ar.init
hungarumlaut -> tcheh-ar.medi
ogonek -> tcheh-ar.fina

less -> veh-ar
quotedbl -> veh-ar.init
numbersign -> veh-ar.medi
ampersand -> veh-ar.fina

Numbers and Punctuation:
zero -> zero-ar
one -> one-ar
two -> two-ar
three -> three-ar
four -> four-ar
five -> five-ar
six -> six-ar
seven -> seven-ar
eight -> eight-ar
nine -> nine-ar

comma -> comma-ar
semicolon -> semicolon-ar
question -> question-ar
nonbreakingspace -> nbspace

Ligatures:
Edieresis -> yeh_meem-ar
Aacute -> yeh_meem-ar.init
Uacute -> yeh_noon-ar.feh
Ograve -> yeh_reh-ar.fina
quoteright -> lam_alef-ar
Oacute -> lam_alef-ar.fina
fraction -> lam_meem-ar
Ydieresis -> lam_meem-ar.init
Ugrave -> lam_meem_hah-ar.init
dotlessi -> lam_meem_khah-ar.init
Ucircumflex -> lam_meem_jeem-ar.init
ydieresis -> lam_khah-ar.init
guilsinglleft -> lam_yeh-ar
currency -> lam_alefMaksura-ar
divide -> lam_jeem-ar.init
lozenge -> lam_hah-ar.init
circumflex -> lam_lam_heh-ar
Otilde -> beh_meem-ar
Atilde -> beh_meem-ar.init
Iacute -> beh_noon-ar.fina
Egrave -> beh_reh-ar.fina
oe -> teh_jeem-ar
OE -> teh_jeem-ar.init
emdash -> teh_hah-ar
endash -> teh_hah-ar.init
Idieresis -> teh_noon-ar.fina
Icircumflex -> teh_reh-ar.fina
quotedblleft -> teh_meem-ar.init
quotedblright -> teh_meem-ar
Igrave -> theh_reh-ar.fina
f_i -> meem_hah-ar.init
f_l -> meem_khah-ar.init
guilsinglright -> meem_jeem-ar.init
periodcentered -> meem_meem-ar
daggerdbl -> meem_meem-ar.init
Ecircumflex -> noon_yeh-ar
quotedblbase -> noon_jeem-ar
quotesinglbase -> noon_jeem-ar.init
Acircumflex -> noon_meem-ar
perthousand -> noon_meem-ar.init
apple -> noon_noon-ar.fina
Ocircumflex -> noon_reh-ar.fina
quoteleft -> feh_yeh-ar

Not sure about these letters - can someone check please:
Some (?) of them need to be combined with half2 further below.
S -> _seen-ar.init.half1
ugrave -> _seen-ar.medi.half1
T -> _sheen-ar.init.half1
ucircumflex -> _sheen-ar.medi.half1
U -> _sad-ar.init.half1
udieresis -> _sad-ar.medi.half1
macron -> block
V -> _dad-ar.init.half1
dagger -> _dad-ar.medi.half1
tilde -> dad-ar.fina
! tilde is not always dad, sometimes it is a complete phrase.

These are supposed to be combined with the seen/sheen/sad/dad above:
cent -> noonghunna-ar
degree -> _seen-ar.medi.half2
odieresis -> _seen_reh-ar.fina.half2
uacute -> _seen_zain-ar.fina.half2

These must come last, and in this very order, otherwise they collide with a previous rename:
asciicircum -> comma
z -> guillemetleft
braceleft -> guillemetright
bar -> quotedblleft
braceright -> quotedblright

asterisk -> multiply
at -> asterisk

underscore -> divide
asciitilde -> underscore
percent -> percent-ar

bracketleft -> bracketright.xxx
bracketright -> bracketleft
bracketright.xxx -> bracketright

These seem to stay the same, not sure if true for all AXt fonts:
Delta -> Delta
backslash -> backslash
colon -> colon
exclam -> exclam
period -> period
quotesingle -> quotesingle
slash -> slash
parenleft -> parenleft
parenright -> parenright
hyphen -> hyphen
dollar -> dollar
equal -> equal
plus -> plus

fi -> meem_hah-ar.init
fl -> meem_khah-ar.init

RECIPES:

_seen-ar.init.half1+noonghunna-ar=seen-ar
_seen-ar.init.half1+_seen-ar.medi.half2=seen-ar.init
_seen-ar.medi.half1+_seen-ar.medi.half2=seen-ar.medi
_seen-ar.medi.half1+noonghunna-ar=seen-ar.fina
_sheen-ar.init.half1+noonghunna-ar=sheen-ar
_sheen-ar.init.half1+_seen-ar.medi.half2=sheen-ar.init
_sheen-ar.medi.half1+_seen-ar.medi.half2=sheen-ar.medi
_sheen-ar.medi.half1+noonghunna-ar=sheen-ar.fina
_sad-ar.init.half1+noonghunna-ar=sad-ar
_sad-ar.init.half1+_seen-ar.medi.half2=sad-ar.init
_sad-ar.medi.half1+_seen-ar.medi.half2=sad-ar.medi
_sad-ar.medi.half1+noonghunna-ar=sad-ar.fina
_dad-ar.init.half1+noonghunna-ar=dad-ar
_dad-ar.init.half1+_seen-ar.medi.half2=dad-ar.init
_dad-ar.medi.half1+_seen-ar.medi.half2=dad-ar.medi
_dad-ar.medi.half1+noonghunna-ar=dad-ar.fina

_seen-ar.init.half1+_seen_reh-ar.fina.half2=seen_reh-ar
_seen-ar.medi.half1+_seen_reh-ar.fina.half2=seen_reh-ar.fina
_seen-ar.init.half1+_seen_zain-ar.fina.half2=seen_zain-ar
_seen-ar.medi.half1+_seen_zain-ar.fina.half2=seen_zain-ar.fina
_sheen-ar.init.half1+_seen_reh-ar.fina.half2=sheen_reh-ar
_sheen-ar.medi.half1+_seen_reh-ar.fina.half2=sheen_reh-ar.fina
_sheen-ar.init.half1+_seen_zain-ar.fina.half2=sheen_zain-ar
_sheen-ar.medi.half1+_seen_zain-ar.fina.half2=sheen_zain-ar.fina
_sad-ar.init.half1+_seen_reh-ar.fina.half2=sad_reh-ar
_sad-ar.medi.half1+_seen_reh-ar.fina.half2=sad_reh-ar.fina
_sad-ar.init.half1+_seen_zain-ar.fina.half2=sad_zain-ar
_sad-ar.medi.half1+_seen_zain-ar.fina.half2=sad_zain-ar.fina
_dad-ar.init.half1+_seen_reh-ar.fina.half2=dad_reh-ar
_dad-ar.medi.half1+_seen_reh-ar.fina.half2=dad_reh-ar.fina
_dad-ar.init.half1+_seen_zain-ar.fina.half2=dad_zain-ar
_dad-ar.medi.half1+_seen_zain-ar.fina.half2=dad_zain-ar.fina
"""

def saveFileInLocation(content="", filePath="~/Desktop/test.txt"):
	with codecs.open(filePath, "w", "utf-8-sig") as thisFile:
		print("💾 Writing:", thisFile.name)
		thisFile.write(content)
		thisFile.close()
	return True

def readFileFromLocation(filePath="~/Desktop/test.txt"):
	content = ""
	with codecs.open(filePath, "r", "utf-8-sig") as thisFile:
		print("💾 Reading:", thisFile.name)
		content = thisFile.read()
		thisFile.close()
	return content

class EncodingConverter(object):

	def __init__(self):
		# Window 'self.w':
		windowWidth = 550
		windowHeight = 260
		windowWidthResize = 1000 # user can resize width by this value
		windowHeightResize = 1000 # user can resize height by this value
		self.w = vanilla.FloatingWindow(
			(windowWidth, windowHeight), # default window size
			"Encoding Converter", # window title
			minSize=(windowWidth, windowHeight), # minimum size (for resizing)
			maxSize=(windowWidth + windowWidthResize, windowHeight + windowHeightResize), # maximum size (for resizing)
			autosaveName="com.mekkablue.EncodingConverter.mainwindow" # stores last window position and size
			)

		# UI elements:
		linePos, inset, lineHeight = 8, 15, 22

		self.w.descriptionText = vanilla.TextBox((inset, linePos + 2, -inset, 14), "Enter conversion text (see tooltips):", sizeStyle='small', selectable=True)
		linePos += lineHeight

		self.w.recipe = vanilla.TextEditor((1, linePos, -1, -inset * 3), text="", callback=self.SavePreferences, checksSpelling=False)
		self.w.recipe.getNSTextView().setToolTip_(
			"- Freely write comments and empty lines\n- Rename: Lines containing a dash (-) followed by a greater sign (>) will trigger glyph renaming, with or without spaces between names\n- Recipe: Lines containing glyph recipes with plus (+) and equals (=) will be treated like in Glyph > Add Glyphs... as long as the do not contain any space\n- Recipes will overwrite existing glyphs. Renamings will create a number-suffixed glyph if a glyph with the same name already exists."
			)
		self.w.recipe.getNSScrollView().setHasVerticalScroller_(1)
		self.w.recipe.getNSScrollView().setHasHorizontalScroller_(1)
		self.w.recipe.getNSScrollView().setRulersVisible_(0)

		legibleFont = NSFont.legibileFontOfSize_(NSFont.systemFontSize())
		textView = self.w.recipe.getNSTextView()
		textView.setFont_(legibleFont)
		textView.setHorizontallyResizable_(1)
		textView.setVerticallyResizable_(1)
		textView.setAutomaticDataDetectionEnabled_(1)
		textView.setAutomaticLinkDetectionEnabled_(1)
		textView.setDisplaysLinkToolTips_(1)
		textSize = textView.minSize()
		textSize.width = 1000
		textView.setMinSize_(textSize)
		# textView.textContainer().setWidthTracksTextView_(0)
		# textView.textContainer().setContainerSize_(textSize)

		# Run Button:
		self.w.openButton = vanilla.Button((inset, -20 - inset, 110, -inset), "Open Text…", sizeStyle='regular', callback=self.importEncoding)
		self.w.saveButton = vanilla.Button((inset + 120, -20 - inset, 110, -inset), "Save Text…", sizeStyle='regular', callback=self.exportEncoding)
		self.w.resetButton = vanilla.Button((inset + 260, -20 - inset, 100, -inset), "Reset Text", sizeStyle='regular', callback=self.resetEncoding)
		self.w.runButton = vanilla.Button((-120 - inset, -20 - inset, -inset, -inset), "Convert Font", sizeStyle='regular', callback=self.EncodingConverterMain)
		self.w.setDefaultButton(self.w.runButton)

		# Load Settings:
		if not self.LoadPreferences():
			print("Note: 'Encoding Converter' could not load preferences. Will resort to defaults")

		# Open window and focus on it:
		self.w.open()
		self.w.makeKey()

	def SavePreferences(self, sender=None):
		try:
			# write current settings into prefs:
			Glyphs.defaults["com.mekkablue.EncodingConverter.recipe"] = self.w.recipe.get()
			return True
		except:
			import traceback
			print(traceback.format_exc())
			return False

	def LoadPreferences(self):
		try:
			# register defaults:
			Glyphs.registerDefault("com.mekkablue.EncodingConverter.recipe", AXtDefault.strip())

			# load previously written prefs:
			self.w.recipe.set(Glyphs.defaults["com.mekkablue.EncodingConverter.recipe"])
			return True
		except:
			import traceback
			print(traceback.format_exc())
			return False

	def exportEncoding(self, sender=None):
		self.SavePreferences()
		filePath = GetSaveFile(message="Save Renaming Scheme", ProposedFileName="glyph name conversion.txt", filetypes=("txt"))
		if filePath:
			fileContent = Glyphs.defaults["com.mekkablue.EncodingConverter.recipe"]
			saveFileInLocation(content=fileContent, filePath=filePath)

	def importEncoding(self, sender=None):
		filePath = GetOpenFile(message="Open Renaming Scheme", allowsMultipleSelection=False, filetypes=("txt"))
		if filePath:
			fileContent = readFileFromLocation(filePath=filePath)
			if fileContent:
				Glyphs.defaults["com.mekkablue.EncodingConverter.recipe"] = fileContent
				self.LoadPreferences()
			else:
				Message(title="File Error", message="File could not be read. Perhaps empty?", OKButton=None)

	def resetEncoding(self, sender=None):
		Glyphs.defaults["com.mekkablue.EncodingConverter.recipe"] = AXtDefault.strip()
		self.LoadPreferences()

	def freeGlyphName(self, glyphName, glyphNameList):
		"""
		Returns the first unused version of glyphName in glyphNameList.
		If necessary, adds a 3-digit extension to the name
		or increases the existing number extension by one.
		"""

		if glyphName in glyphNameList:
			try:
				# increase the .000 extension
				increasedGlyphName = glyphName[:-3] + ("%.3d" % int(glyphName[-3:]) + 1)
				return freeGlyphName(increasedGlyphName, glyphNameList)
			except:
				# has no .000 extension yet:
				increasedGlyphName = glyphName + ".001"
				return freeGlyphName(increasedGlyphName, glyphNameList)
		return glyphName

	def glyphRename(self, source, target, font):
		"""Renames source to target."""
		thisGlyph = font.glyphs[source]
		existingGlyphNames = [g.name for g in Font.glyphs]
		targetString = self.freeGlyphName(target, existingGlyphNames)

		try:
			thisGlyph.name = targetString
			thisGlyph.export = targetString[0] != "_"
			print("🙌 Renamed glyph: %s → %s" % (source, targetString))
			return 1
		except Exception as e:
			if "NoneType" in str(e):
				e = "No glyph with that name."
			print("❌ Failed to rename %s to %s. (%s)" % (source, targetString, e))
			return 0

	def isValidGlyphName(self, glyphName):
		validCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-."
		if len(glyphName) == 0 or glyphName[0] == "-":
			return False
		for letter in glyphName:
			if not letter in validCharacters:
				return False
		return True

	def EncodingConverterMain(self, sender=None):
		try:
			# clear macro window log:
			Glyphs.clearLog()

			# update settings to the latest user input:
			if not self.SavePreferences():
				print("⚠ 'Encoding Converter' could not write preferences.")

			thisFont = Glyphs.font # frontmost font
			if thisFont is None:
				Message(title="No Font Open", message="The script requires a font. Open a font and run the script again.", OKButton=None)
			else:
				print("Encoding Converter Report for %s" % thisFont.familyName)
				if thisFont.filepath:
					print(thisFont.filepath)
				else:
					print("⚠ The font file has not been saved yet.")
				print()

				thisFont.disableUpdateInterface()
				try:

					thisFont.setDisablesNiceNames_(1)
					nameChangeString = Glyphs.defaults["com.mekkablue.EncodingConverter.recipe"]
					countRenames = 0
					countRecipes = 0

					# parse lines of nameChangeString:
					for line in nameChangeString.splitlines():
						try:
							if line.strip(): # skip empty lines

								# RENAME LINE:
								if "->" in line:
									nameList = line.split("->")
									sourceName = nameList[0].strip()
									targetName = nameList[1].strip()
									if sourceName != targetName:
										countRenames += self.glyphRename(sourceName, targetName, thisFont)

								# GLYPH RECIPE:
								elif "=" in line and not " " in line:
									sourceRecipe, targetGlyph = line.strip().split("=")
									if self.isValidGlyphName(targetGlyph):
										sourceGlyphNames = sourceRecipe.split("+")
										if all([thisFont.glyphs[n] for n in sourceGlyphNames]):
											exportStatus = targetGlyph[0] != "_"
											glyph = thisFont.glyphs[targetGlyph]
											if glyph:
												print("🔠 overwritten: %s" % targetGlyph)
											else:
												glyph = GSGlyph()
												glyph.name = targetGlyph
												thisFont.glyphs.append(glyph)
												print("🔠 created: %s" % targetGlyph)
											for layer in glyph.layers:
												if layer.isMasterLayer or layer.isSpecialLayer:
													layer.clear()
													for compName in sourceGlyphNames:
														comp = GSComponent(compName)
														layer.components.append(comp)
											countRecipes += 1
										else:
											print("⚠ Could not create recipe for %s. Not all ingredients in font: %s." % (targetGlyph, ", ".join(sourceGlyphNames)))
									else:
										print("⚠ invalid glyph name: %s. Skipping." % targetGlyph)
						except:
							pass

				except Exception as e:
					Glyphs.showMacroWindow()
					print("\n⚠ Script Error:\n")
					import traceback
					print(traceback.format_exc())
					print()
					raise e

				finally:
					thisFont.enableUpdateInterface() # re-enables UI updates in Font View

				self.w.close() # delete if you want window to stay open

			# Final report:
			Glyphs.showNotification(
				"%s: Done" % (thisFont.familyName),
				"Renamed %i glyph%s, built %i glyph recipe%s. Details in Macro Window" % (
					countRenames,
					"" if countRenames == 1 else "s",
					countRecipes,
					"" if countRecipes == 1 else "s",
					),
				)
			print("\nDone.")

		except Exception as e:
			# brings macro window to front and reports error:
			Glyphs.showMacroWindow()
			print("Encoding Converter Error: %s" % e)
			import traceback
			print(traceback.format_exc())

EncodingConverter()


text:
package auth

import "fmt"

type SchemeInfo map[string]interface{}

type Scheme interface {
	AppLogin(appName string) (Token, error)
	Login(params map[string]string) (Token, error)
	Logout(token string) error
	Auth(token string) (Token, error)
	Info() (SchemeInfo, error)
	Name() string
	Create(user *User) (*User, error)
	Remove(user *User) error
}

type ManagedScheme interface {
	Scheme
	StartPasswordReset(user *User) error
	ResetPassword(user *User, resetToken string) error
	ChangePassword(token Token, oldPassword string, newPassword string) error
}

type AuthenticationFailure struct {
	Message string
}

func (a AuthenticationFailure) Error() string {
	if a.Message != "" {
		return a.Message
	}
	return "Authentication failed, wrong password."
}

var schemes = make(map[string]Scheme)

func RegisterScheme(name string, scheme Scheme) {
	schemes[name] = scheme
}

func UnregisterScheme(name string) {
	delete(schemes, name)
}

func GetScheme(name string) (Scheme, error) {
	scheme, ok := schemes[name]
	if !ok {
		return nil, fmt.Errorf("Unknown auth scheme: %q.", name)
	}
	return scheme, nil
}


text:
<?php

/**
 * Modified: 2020-05-26T22:07:25+00:00
 */
namespace Office365\OneDrive\ContentTypes;

use Office365\Runtime\ClientValue;
class ContentTypeOrder extends ClientValue
{
    /**
     * @var bool
     */
    public $Default;
    /**
     * @var integer
     */
    public $Position;
}


text:
package Manoc::Logger::CatalystRole;
use Moose::Role;

use Manoc::Logger;
use Log::Log4perl::Catalyst;

sub setup_log {
    my ( $class, $levels ) = @_;

    return if $class->log;

    $levels ||= '';
    $levels =~ s/^\s+//;
    $levels =~ s/\s+$//;
    my %levels = map { $_ => 1 } split /\s*,\s*/, $levels;

    my $env_debug = Catalyst::Utils::env_value( $class, 'DEBUG' );
    if ( defined $env_debug ) {
        $levels{debug} = 1 if $env_debug;    # Ugly!
        delete( $levels{debug} ) unless $env_debug;
    }

    Manoc::Logger->init(
        {
            class => $class,
            debug => $levels{debug}
        }
    );

    # start default screen logger
    $class->log( Log::Log4perl::Catalyst->new() );

    # ovverride debug method
    if ( $levels{debug} ) {
        Class::MOP::get_metaclass_by_name($class)->add_method( 'debug' => sub { 1 } );
        $class->log->debug('Debug messages enabled');
    }
}

1;

# Local Variables:
# mode: cperl
# indent-tabs-mode: nil
# cperl-indent-level: 4
# cperl-indent-parens-as-block: t
# End:


text:
1. Follow the [Bazel steps for the TF Demo App](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android#bazel).

2. Build the app with Bazel. The demo needs C++11. We configure the fat_apk_cpu flag to package support for 4 hardware variants. You may replace it with --config=android_arm64 on a 64-bit device and --config=android_arm for 32-bit device:

  ```shell
  bazel build -c opt --cxxopt='--std=c++11' --fat_apk_cpu=x86,x86_64,arm64-v8a,armeabi-v7a \
    //tensorflow/contrib/lite/examples/android:tflite_demo
  ```

3. Install the demo on a
   [debug-enabled device](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android#install):

  ```shell
  adb install bazel-bin/tensorflow/contrib/lite/examples/android/tflite_demo.apk
  ```


text:
using System;
using System.Collections.Generic;
using System.Linq;
using Bio.Algorithms.Kmer;
using Bio.Util;

namespace Bio.Algorithms.Assembly.Graph
{
    /// <summary>
    /// Implements a thread safe K-mer dictionary (12 < k < 31) for storing values associated with ulong k-mers.
    /// Backend is an array of binary search trees
    /// </summary>
    public class KmerDictionary
    {
        /// <summary>
        /// How many bits of the ulong to use to decide which bucket is inserted where?
        /// Also determines the number of buckets as 2^hashLength,
        /// </summary>
        private const int HashLength = 12;

        /// <summary>
        /// Each bucket stores a Tree that can be searched.
        /// </summary>
        private readonly BinaryTreeOfDebrujinNodes[] _buckets;

        /// <summary>
        /// Mask to hash off higher bits which can be used to get the bucket assignment of a k-mer
        /// </summary>
        private readonly ulong _hashingMask;

        /// <summary>
        /// Creates a new dictionary to store and search for deBruijin Nodes
        /// </summary>
        public KmerDictionary()
        {
            var maxSize = (ulong) Math.Pow(2, HashLength);

            // Create a list of buckets up to that size
            _buckets = new BinaryTreeOfDebrujinNodes[maxSize];

            // Create a new tree in each bucket position
            Enumerable.Range(0, (int) maxSize).ForEach(x => _buckets[x] = new BinaryTreeOfDebrujinNodes());

            // Make a mask for incoming bits
            _hashingMask = maxSize - 1; // This should be all bits up to the length of the buckets array.
        }

        /// <summary>
        /// Number of kmers in the dictionary
        /// </summary>
        public long NodeCount
        {
            get { return _buckets.Select(x => x.Count).Sum(); }
        }

        /// <summary>
        /// Either returns the DeBrujin node associated with the ulong, or
        /// sets it if an old one does not exist
        /// Parallel Note: Is thread safe
        /// </summary>
        /// <returns>The node representing this value</returns>
        public DeBruijnNode SetNewOrGetOld(KmerData32 value)
        {
            int bucket = AssignBucket(value);
            BinaryTreeOfDebrujinNodes curBucket = _buckets[bucket];

            //keep it thread safe for additions
            DeBruijnNode toReturn;
            lock (curBucket)
            {
                toReturn = curBucket.AddOrReturnCurrent(value);
            }
            return toReturn;
        }

        /// <summary>
        /// Enumerate through tree returning an array while removing references to left/right children
        /// so they can become available to GC if not otherwise referenced.
        /// </summary>
        /// <returns>Set of nodes</returns>
        private IEnumerable<DeBruijnNode> GetNodes()
        {
            return _buckets.SelectMany(tree => tree.GetNodes());
        }

        /// <summary>
        /// Returns a node for a given k-mer
        /// </summary>
        /// <param name="kmer">The kmer</param>
        /// <returns>true if the item has previously been assigned a serial number; otherwise, false.</returns>
        public DeBruijnNode TryGetOld(KmerData32 kmer)
        {
            int bucketIndex = AssignBucket(kmer);
            BinaryTreeOfDebrujinNodes tree = _buckets[bucketIndex];
            return tree.SearchTree(kmer);
        }

        /// <summary>
        /// Assign a k-mer encoded as a ulong to a bucket
        /// </summary>
        /// <param name="value">kmer value</param>
        /// <returns>bucket index</returns>
        private int AssignBucket(KmerData32 value)
        {
            return (int) (value.KmerData & _hashingMask);
        }

        /// <summary>
        /// Converts the nodes in the kmer manager into an array
        /// in order to improve performance and simultaneously destroys tree data structure.
        /// </summary>
        public IEnumerable<DeBruijnNode> GenerateNodeArray()
        {
            IEnumerable<DeBruijnNode> nodes;
            long maxSize = PlatformManager.Services.Is64BitProcessType ? int.MaxValue - 64 : int.MaxValue/4;

            if (NodeCount > maxSize)
            {
                nodes = new BigList<DeBruijnNode>(GetNodes(), NodeCount);
            }
            else
            {
                var tnodes = new List<DeBruijnNode>((int) NodeCount);
                tnodes.AddRange(GetNodes());
                nodes = tnodes;
            }
            return nodes;
        }
    }
}


text:
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
    </style>

    <style name="MainGradeHeaders">
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_alignParentTop">true</item>
        <item name="android:layout_alignParentLeft">true</item>
        <item name="android:textSize">32sp</item>
        <item name="android:textStyle">bold</item>
        <item name="android:layout_marginBottom">4dp</item>
    </style>

    <style name="MainGradeSubHeaders">
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">wrap_content</item>
        <item name="android:textSize">20sp</item>
        <item name="android:layout_marginLeft">4dp</item>
    </style>

    <style name="MainGradeText">
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">wrap_content</item>
        <item name="android:textSize">16sp</item>
    </style>

    <style name="MainGradeEditText">
        <item name="android:gravity">center</item>
        <item name="android:textSize">14sp</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">80dp</item>
        <item name="android:inputType">numberDecimal</item>
        <item name="android:singleLine">true</item>
        <item name="android:maxLength">6</item>
        <item name="android:minLines">1</item>
        <item name="android:maxLines">1</item>
    </style>

    <style name="LectureQuizMaxValStyle">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:textSize">16sp</item>
        <item name="android:layout_toRightOf">@+id/editTextLecQuiz1</item>
        <item name="android:layout_marginLeft">4dp</item>
    </style>

    <style name="LectureQuizGradeStyle" parent="MainGradeEditText">
        <item name="android:layout_width">50dp</item>
        <item name="android:inputType">number</item>
        <item name="android:maxLength">2</item>
    </style>

    <style name="MainGradeScaleText" parent="MainGradeText">
        <item name="android:layout_width">145dp</item>
        <item name="android:layout_marginLeft">4dp</item>
        <item name="android:layout_marginBottom">2dp</item>
        <item name="android:paddingLeft">4dp</item>
        <item name="android:layout_alignLeft">@+id/textViewLabelGradeScale</item>
    </style>

</resources>


text:
<!DOCTYPE html>

  <meta charset="utf-8">

  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>FunctionalX.tests.lists.cart2 package — FunctionalX.py 0.0.1 documentation</title>

    <link rel="stylesheet" href="../_static/css/theme.css" type="text/css" />

    <link rel="top" title="FunctionalX.py 0.0.1 documentation" href="../index.html"/>
        <link rel="up" title="FunctionalX.tests.lists package" href="FunctionalX.tests.lists.html"/>
        <link rel="prev" title="FunctionalX.tests.lists package" href="FunctionalX.tests.lists.html"/>

             FunctionalX.py

                0.0.1

  <form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>

lists

FunctionalX

FunctionalX package

Subpackages

FunctionalX.src package

FunctionalX.tests package

Module contents

        FunctionalX.py

Docs »

FunctionalX »

FunctionalX package »

FunctionalX.tests package »

FunctionalX.tests.lists package »

FunctionalX.tests.lists.cart2 package

             View page source

FunctionalX.tests.lists.cart2 package¶

Submodules¶

FunctionalX.tests.lists.cart2.test_1 module¶

FunctionalX.tests.lists.cart2.test_1.run()[source]¶

Module contents¶

FunctionalX.tests.lists.cart2.runtests()[source]¶

         Previous

        © Copyright 2016, Yuhang(Steven) Wang.

  Built with Sphinx using a theme provided by Read the Docs.


text:
#include <aws/elasticmapreduce/model/ExecutionEngineConfig.h>
#include <aws/core/utils/json/JsonSerializer.h>

#include <utility>

using namespace Aws::Utils::Json;
using namespace Aws::Utils;

namespace Aws
{
namespace EMR
{
namespace Model
{

ExecutionEngineConfig::ExecutionEngineConfig() :
    m_idHasBeenSet(false),
    m_type(ExecutionEngineType::NOT_SET),
    m_typeHasBeenSet(false),
    m_masterInstanceSecurityGroupIdHasBeenSet(false)
{
}

ExecutionEngineConfig::ExecutionEngineConfig(JsonView jsonValue) :
    m_idHasBeenSet(false),
    m_type(ExecutionEngineType::NOT_SET),
    m_typeHasBeenSet(false),
    m_masterInstanceSecurityGroupIdHasBeenSet(false)
{
  *this = jsonValue;
}

ExecutionEngineConfig& ExecutionEngineConfig::operator =(JsonView jsonValue)
{
  if(jsonValue.ValueExists("Id"))
  {
    m_id = jsonValue.GetString("Id");

    m_idHasBeenSet = true;
  }

  if(jsonValue.ValueExists("Type"))
  {
    m_type = ExecutionEngineTypeMapper::GetExecutionEngineTypeForName(jsonValue.GetString("Type"));

    m_typeHasBeenSet = true;
  }

  if(jsonValue.ValueExists("MasterInstanceSecurityGroupId"))
  {
    m_masterInstanceSecurityGroupId = jsonValue.GetString("MasterInstanceSecurityGroupId");

    m_masterInstanceSecurityGroupIdHasBeenSet = true;
  }

  return *this;
}

JsonValue ExecutionEngineConfig::Jsonize() const
{
  JsonValue payload;

  if(m_idHasBeenSet)
  {
   payload.WithString("Id", m_id);

  }

  if(m_typeHasBeenSet)
  {
   payload.WithString("Type", ExecutionEngineTypeMapper::GetNameForExecutionEngineType(m_type));
  }

  if(m_masterInstanceSecurityGroupIdHasBeenSet)
  {
   payload.WithString("MasterInstanceSecurityGroupId", m_masterInstanceSecurityGroupId);

  }

  return payload;
}

} // namespace Model
} // namespace EMR
} // namespace Aws