<commit_before>#!/usr/bin/env python2
# Copyright (c) 2014-2015 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.

"""
Run Regression Test Suite

This module calls down into individual test cases via subprocess. It will
forward all unrecognized arguments onto the individual test scripts, other
than:

    - `-extended`: run the "extended" test suite in addition to the basic one.
    - `-win`: signal that this is running in a Windows environment, and we
      should run the tests.
    - `--coverage`: this generates a basic coverage report for the RPC
      interface.

For a description of arguments recognized by test scripts, see
`qa/pull-tester/test_framework/test_framework.py:BitcoinTestFramework.main`.

"""

import os
import time
import shutil
import sys
import subprocess
import tempfile
import re

from tests_config import *

#If imported values are not defined then set to zero (or disabled)
if not vars().has_key('ENABLE_WALLET'):
    ENABLE_WALLET=0
if not vars().has_key('ENABLE_BITCOIND'):
    ENABLE_BITCOIND=0
if not vars().has_key('ENABLE_UTILS'):
    ENABLE_UTILS=0
if not vars().has_key('ENABLE_ZMQ'):
    ENABLE_ZMQ=0

ENABLE_COVERAGE=0

#Create a set to store arguments and create the passOn string
opts = set()
passOn = ""
p = re.compile("^--")

bold = ("","")
if (os.name == 'posix'):
    bold = ('\033[0m', '\033[1m')

for arg in sys.argv[1:]:
    if arg == '--coverage':
        ENABLE_COVERAGE = 1
    elif (p.match(arg) or arg == "-h"):
        passOn += " " + arg
    else:
        opts.add(arg)

#Set env vars
buildDir = BUILDDIR
if "BITCOIND" not in os.environ:
    os.environ["BITCOIND"] = buildDir + '/src/bitcoind' + EXEEXT
if "BITCOINCLI" not in os.environ:
    os.environ["BITCOINCLI"] = buildDir + '/src/bitcoin-cli' + EXEEXT

#Disable Windows tests by default
if EXEEXT == ".exe" and "-win" not in opts:
    print "Win tests currently disabled.  Use -win option to enable"
    sys.exit(0)

#Tests
testScripts1 = [
    'bip68-112-113-p2p.py',
    'wallet.py',
    'excessive.py',
    'listtransactions.py',
    'receivedby.py',
    'mempool_resurrect_test.py',
    'txn_doublespend.py --mineblock',
    'txn_clone.py',
    'getchaintips.py',
    'rawtransactions.py',
    'rest.py',
    'mempool_spendcoinbase.py',
    'mempool_reorg.py',
#    'mempool_limit.py',  # mempool priority changes causes create_lots_of_big_transactions to fail
    'httpbasics.py',
    'multi_rpc.py',
    'zapwallettxes.py',
    'proxy_test.py',
    'merkle_blocks.py',
    'fundrawtransaction.py',
    'signrawtransactions.py',
    'walletbackup.py',
    'nodehandling.py',
    'reindex.py',
    'decodescript.py',
#    'p2p-fullblocktest.py',
    'blockchain.py',
    'disablewallet.py',
#    'sendheaders.py',   # BU requests INVs not headers -- in the future we may add support for headers, at least by treating them like INVs
    'keypool.py',
#    'prioritise_transaction.py',
#    'invalidblockrequest.py',
    'invalidtxrequest.py',
    'abandonconflict.py',
    'p2p-versionbits-warning.py',
]
testScripts = []

testScriptsExt = [
    'bip9-softforks.py',
    'bip65-cltv.py',
    'bip65-cltv-p2p.py',
#    'bip68-sequence.py',
    'bipdersig-p2p.py',
    'bipdersig.py',
    'getblocktemplate_longpoll.py',
    'getblocktemplate_proposals.py',
    'txn_doublespend.py',
    'txn_clone.py --mineblock',
#    'pruning.py',  # too much disk
    'forknotify.py',
    'invalidateblock.py',
#    'rpcbind_test.py', #temporary, bug in libevent, see #6655
    'smartfees.py',
    'maxblocksinflight.py',
    'p2p-acceptblock.py',
    'mempool_packages.py',
    'maxuploadtarget.py',
    'replace-by-fee.py',
]

#Enable ZMQ tests
if ENABLE_ZMQ == 1:
    testScripts.append('zmq_test.py')

def runtests():
    coverage = None

    if ENABLE_COVERAGE:
        coverage = RPCCoverage()
        print("Initializing coverage directory at %s\n" % coverage.dir)

    if(ENABLE_WALLET == 1 and ENABLE_UTILS == 1 and ENABLE_BITCOIND == 1):
        rpcTestDir = buildDir + '/qa/rpc-tests/'
        run_extended = '-extended' in opts
        cov_flag = coverage.flag if coverage else ''
        flags = " --srcdir %s/src %s %s" % (buildDir, cov_flag, passOn)

        #Run Tests
        for i in range(len(testScripts)):
            if (len(opts) == 0
                    or (len(opts) == 1 and "-win" in opts )
                    or run_extended
                    or testScripts[i] in opts
                    or re.sub(".py$", "", testScripts[i]) in opts ):

                print("Running testscript %s%s%s ..." % (bold[1], testScripts[i], bold[0]))
                time0 = time.time()
                subprocess.check_call(
                    rpcTestDir + testScripts[i] + flags, shell=True)
                print("Duration: %s s\n" % (int(time.time() - time0)))

                # exit if help is called so we print just one set of
                # instructions
                p = re.compile(" -h| --help")
                if p.match(passOn):
                    sys.exit(0)

        # Run Extended Tests
        for i in range(len(testScriptsExt)):
            if (run_extended or testScriptsExt[i] in opts
                    or re.sub(".py$", "", testScriptsExt[i]) in opts):

                print(
                    "Running 2nd level testscript "
                    + "%s%s%s ..." % (bold[1], testScriptsExt[i], bold[0]))
                time0 = time.time()
                subprocess.check_call(
                    rpcTestDir + testScriptsExt[i] + flags, shell=True)
                print("Duration: %s s\n" % (int(time.time() - time0)))

        if coverage:
            coverage.report_rpc_coverage()

            print("Cleaning up coverage data")
            coverage.cleanup()

    else:
        print "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled"

class RPCCoverage(object):
    """
    Coverage reporting utilities for pull-tester.

    Coverage calculation works by having each test script subprocess write
    coverage files into a particular directory. These files contain the RPC
    commands invoked during testing, as well as a complete listing of RPC
    commands per `bitcoin-cli help` (`rpc_interface.txt`).

    After all tests complete, the commands run are combined and diff'd against
    the complete list to calculate uncovered RPC commands.

    See also: qa/rpc-tests/test_framework/coverage.py

    """
    def __init__(self):
        self.dir = tempfile.mkdtemp(prefix="coverage")
        self.flag = '--coveragedir %s' % self.dir

    def report_rpc_coverage(self):
        """
        Print out RPC commands that were unexercised by tests.

        """
        uncovered = self._get_uncovered_rpc_commands()

        if uncovered:
            print("Uncovered RPC commands:")
            print("".join(("  - %s\n" % i) for i in sorted(uncovered)))
        else:
            print("All RPC commands covered.")

    def cleanup(self):
        return shutil.rmtree(self.dir)

    def _get_uncovered_rpc_commands(self):
        """
        Return a set of currently untested RPC commands.

        """
        # This is shared from `qa/rpc-tests/test-framework/coverage.py`
        REFERENCE_FILENAME = 'rpc_interface.txt'
        COVERAGE_FILE_PREFIX = 'coverage.'

        coverage_ref_filename = os.path.join(self.dir, REFERENCE_FILENAME)
        coverage_filenames = set()
        all_cmds = set()
        covered_cmds = set()

        if not os.path.isfile(coverage_ref_filename):
            raise RuntimeError("No coverage reference found")

        with open(coverage_ref_filename, 'r') as f:
            all_cmds.update([i.strip() for i in f.readlines()])

        for root, dirs, files in os.walk(self.dir):
            for filename in files:
                if filename.startswith(COVERAGE_FILE_PREFIX):
                    coverage_filenames.add(os.path.join(root, filename))

        for filename in coverage_filenames:
            with open(filename, 'r') as f:
                covered_cmds.update([i.strip() for i in f.readlines()])

        return all_cmds - covered_cmds

if __name__ == '__main__':
    runtests()
<commit_msg>re-enable normal tests<commit_after>#!/usr/bin/env python2
# Copyright (c) 2014-2015 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.

"""
Run Regression Test Suite

This module calls down into individual test cases via subprocess. It will
forward all unrecognized arguments onto the individual test scripts, other
than:

    - `-extended`: run the "extended" test suite in addition to the basic one.
    - `-win`: signal that this is running in a Windows environment, and we
      should run the tests.
    - `--coverage`: this generates a basic coverage report for the RPC
      interface.

For a description of arguments recognized by test scripts, see
`qa/pull-tester/test_framework/test_framework.py:BitcoinTestFramework.main`.

"""

import os
import time
import shutil
import sys
import subprocess
import tempfile
import re

from tests_config import *

#If imported values are not defined then set to zero (or disabled)
if not vars().has_key('ENABLE_WALLET'):
    ENABLE_WALLET=0
if not vars().has_key('ENABLE_BITCOIND'):
    ENABLE_BITCOIND=0
if not vars().has_key('ENABLE_UTILS'):
    ENABLE_UTILS=0
if not vars().has_key('ENABLE_ZMQ'):
    ENABLE_ZMQ=0

ENABLE_COVERAGE=0

#Create a set to store arguments and create the passOn string
opts = set()
passOn = ""
p = re.compile("^--")

bold = ("","")
if (os.name == 'posix'):
    bold = ('\033[0m', '\033[1m')

for arg in sys.argv[1:]:
    if arg == '--coverage':
        ENABLE_COVERAGE = 1
    elif (p.match(arg) or arg == "-h"):
        passOn += " " + arg
    else:
        opts.add(arg)

#Set env vars
buildDir = BUILDDIR
if "BITCOIND" not in os.environ:
    os.environ["BITCOIND"] = buildDir + '/src/bitcoind' + EXEEXT
if "BITCOINCLI" not in os.environ:
    os.environ["BITCOINCLI"] = buildDir + '/src/bitcoin-cli' + EXEEXT

#Disable Windows tests by default
if EXEEXT == ".exe" and "-win" not in opts:
    print "Win tests currently disabled.  Use -win option to enable"
    sys.exit(0)

#Tests
testScripts = [
    'bip68-112-113-p2p.py',
    'wallet.py',
    'excessive.py',
    'listtransactions.py',
    'receivedby.py',
    'mempool_resurrect_test.py',
    'txn_doublespend.py --mineblock',
    'txn_clone.py',
    'getchaintips.py',
    'rawtransactions.py',
    'rest.py',
    'mempool_spendcoinbase.py',
    'mempool_reorg.py',
#    'mempool_limit.py',  # mempool priority changes causes create_lots_of_big_transactions to fail
    'httpbasics.py',
    'multi_rpc.py',
    'zapwallettxes.py',
    'proxy_test.py',
    'merkle_blocks.py',
    'fundrawtransaction.py',
    'signrawtransactions.py',
    'walletbackup.py',
    'nodehandling.py',
    'reindex.py',
    'decodescript.py',
#    'p2p-fullblocktest.py',
    'blockchain.py',
    'disablewallet.py',
#    'sendheaders.py',   # BU requests INVs not headers -- in the future we may add support for headers, at least by treating them like INVs
    'keypool.py',
#    'prioritise_transaction.py',
#    'invalidblockrequest.py',
    'invalidtxrequest.py',
    'abandonconflict.py',
    'p2p-versionbits-warning.py',
]

testScriptsExt = [
    'bip9-softforks.py',
    'bip65-cltv.py',
    'bip65-cltv-p2p.py',
#    'bip68-sequence.py',
    'bipdersig-p2p.py',
    'bipdersig.py',
    'getblocktemplate_longpoll.py',
    'getblocktemplate_proposals.py',
    'txn_doublespend.py',
    'txn_clone.py --mineblock',
#    'pruning.py',  # too much disk
    'forknotify.py',
    'invalidateblock.py',
#    'rpcbind_test.py', #temporary, bug in libevent, see #6655
    'smartfees.py',
    'maxblocksinflight.py',
    'p2p-acceptblock.py',
    'mempool_packages.py',
    'maxuploadtarget.py',
    'replace-by-fee.py',
]

#Enable ZMQ tests
if ENABLE_ZMQ == 1:
    testScripts.append('zmq_test.py')

def runtests():
    coverage = None

    if ENABLE_COVERAGE:
        coverage = RPCCoverage()
        print("Initializing coverage directory at %s\n" % coverage.dir)

    if(ENABLE_WALLET == 1 and ENABLE_UTILS == 1 and ENABLE_BITCOIND == 1):
        rpcTestDir = buildDir + '/qa/rpc-tests/'
        run_extended = '-extended' in opts
        cov_flag = coverage.flag if coverage else ''
        flags = " --srcdir %s/src %s %s" % (buildDir, cov_flag, passOn)

        #Run Tests
        for i in range(len(testScripts)):
            if (len(opts) == 0
                    or (len(opts) == 1 and "-win" in opts )
                    or run_extended
                    or testScripts[i] in opts
                    or re.sub(".py$", "", testScripts[i]) in opts ):

                print("Running testscript %s%s%s ..." % (bold[1], testScripts[i], bold[0]))
                time0 = time.time()
                subprocess.check_call(
                    rpcTestDir + testScripts[i] + flags, shell=True)
                print("Duration: %s s\n" % (int(time.time() - time0)))

                # exit if help is called so we print just one set of
                # instructions
                p = re.compile(" -h| --help")
                if p.match(passOn):
                    sys.exit(0)

        # Run Extended Tests
        for i in range(len(testScriptsExt)):
            if (run_extended or testScriptsExt[i] in opts
                    or re.sub(".py$", "", testScriptsExt[i]) in opts):

                print(
                    "Running 2nd level testscript "
                    + "%s%s%s ..." % (bold[1], testScriptsExt[i], bold[0]))
                time0 = time.time()
                subprocess.check_call(
                    rpcTestDir + testScriptsExt[i] + flags, shell=True)
                print("Duration: %s s\n" % (int(time.time() - time0)))

        if coverage:
            coverage.report_rpc_coverage()

            print("Cleaning up coverage data")
            coverage.cleanup()

    else:
        print "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled"

class RPCCoverage(object):
    """
    Coverage reporting utilities for pull-tester.

    Coverage calculation works by having each test script subprocess write
    coverage files into a particular directory. These files contain the RPC
    commands invoked during testing, as well as a complete listing of RPC
    commands per `bitcoin-cli help` (`rpc_interface.txt`).

    After all tests complete, the commands run are combined and diff'd against
    the complete list to calculate uncovered RPC commands.

    See also: qa/rpc-tests/test_framework/coverage.py

    """
    def __init__(self):
        self.dir = tempfile.mkdtemp(prefix="coverage")
        self.flag = '--coveragedir %s' % self.dir

    def report_rpc_coverage(self):
        """
        Print out RPC commands that were unexercised by tests.

        """
        uncovered = self._get_uncovered_rpc_commands()

        if uncovered:
            print("Uncovered RPC commands:")
            print("".join(("  - %s\n" % i) for i in sorted(uncovered)))
        else:
            print("All RPC commands covered.")

    def cleanup(self):
        return shutil.rmtree(self.dir)

    def _get_uncovered_rpc_commands(self):
        """
        Return a set of currently untested RPC commands.

        """
        # This is shared from `qa/rpc-tests/test-framework/coverage.py`
        REFERENCE_FILENAME = 'rpc_interface.txt'
        COVERAGE_FILE_PREFIX = 'coverage.'

        coverage_ref_filename = os.path.join(self.dir, REFERENCE_FILENAME)
        coverage_filenames = set()
        all_cmds = set()
        covered_cmds = set()

        if not os.path.isfile(coverage_ref_filename):
            raise RuntimeError("No coverage reference found")

        with open(coverage_ref_filename, 'r') as f:
            all_cmds.update([i.strip() for i in f.readlines()])

        for root, dirs, files in os.walk(self.dir):
            for filename in files:
                if filename.startswith(COVERAGE_FILE_PREFIX):
                    coverage_filenames.add(os.path.join(root, filename))

        for filename in coverage_filenames:
            with open(filename, 'r') as f:
                covered_cmds.update([i.strip() for i in f.readlines()])

        return all_cmds - covered_cmds

if __name__ == '__main__':
    runtests()
<|endoftext|>


<commit_before>from __future__ import division

from datetime import datetime
from random import choice

from tornado.web import authenticated, HTTPError, asynchronous
from tornado.gen import coroutine, Task

from qiita_ware import r_server
from qiita_db.sql_connection import SQLConnectionHandler
from qiita_db.util import get_count
from qiita_db.study import Study
from .base_handlers import BaseHandler

class StatsHandler(BaseHandler):
    def _get_stats(self, callback):
        # check if the key exists in redis
        lats = r_server.lrange('stats:sample_lats', 0, -1)
        longs = r_server.lrange('stats:sample_longs', 0, -1)
        if not (lats or longs):
            # if we don't have them, then fetch from disk and add to the
            # redis server with a 1-hour expiration
            conn = SQLConnectionHandler()
            sql = """select latitude, longitude
                     from qiita.required_sample_info"""
            lat_longs = conn.execute_fetchall(sql)
            with r_server.pipeline() as pipe:
                for latitude, longitude in lat_longs:
                    # storing as a simple data structure, hopefully this doesn't
                    # burn us later
                    pipe.rpush('stats:sample_lats', latitude)
                    pipe.rpush('stats:sample_longs', longitude)

                # set the key to expire in an hour, so that we limit the number of
                # times we have to go to the database to a reasonable amount
                r_server.expire('stats:sample_lats', 3600)
                r_server.expire('stats:sample_longs', 3600)

                pipe.execute()
        else:
            # If we do have them, put the redis results into the same structure
            # that would come back from the database
            longs = [float(x) for x in longs]
            lats = [float(x) for x in lats]
            lat_longs = zip(lats, longs)

        # Get the number of studies
        num_studies = get_count('qiita.study')

        # Get the number of samples
        num_samples = len(lats)

        # Get the number of users
        num_users = get_count('qiita.qiita_user')

        callback([num_studies, num_samples, num_users, lat_longs])

    @coroutine
    def get(self):
        num_studies, num_samples, num_users, lat_longs = \
            yield Task(self._get_stats)

        # Pull a random public study from the database
        study = Study(choice(Study.get_public()))

        self.render('stats.html', user=self.current_user,
                    num_studies=num_studies, num_samples=num_samples,
                    num_users=num_users, lat_longs=lat_longs,
                    random_study_info=study.info,
                    random_study_title=study.title, random_study_id=study.id)
<commit_msg>flake8 fixes<commit_after>from __future__ import division

from random import choice

from tornado.gen import coroutine, Task

from qiita_ware import r_server
from qiita_db.sql_connection import SQLConnectionHandler
from qiita_db.util import get_count
from qiita_db.study import Study
from .base_handlers import BaseHandler

class StatsHandler(BaseHandler):
    def _get_stats(self, callback):
        # check if the key exists in redis
        lats = r_server.lrange('stats:sample_lats', 0, -1)
        longs = r_server.lrange('stats:sample_longs', 0, -1)
        if not (lats or longs):
            # if we don't have them, then fetch from disk and add to the
            # redis server with a 1-hour expiration
            conn = SQLConnectionHandler()
            sql = """select latitude, longitude
                     from qiita.required_sample_info"""
            lat_longs = conn.execute_fetchall(sql)
            with r_server.pipeline() as pipe:
                for latitude, longitude in lat_longs:
                    # storing as a simple data structure, hopefully this
                    # doesn't burn us later
                    pipe.rpush('stats:sample_lats', latitude)
                    pipe.rpush('stats:sample_longs', longitude)

                # set the key to expire in an hour, so that we limit the number
                # of times we have to go to the database to a reasonable amount
                r_server.expire('stats:sample_lats', 3600)
                r_server.expire('stats:sample_longs', 3600)

                pipe.execute()
        else:
            # If we do have them, put the redis results into the same structure
            # that would come back from the database
            longs = [float(x) for x in longs]
            lats = [float(x) for x in lats]
            lat_longs = zip(lats, longs)

        # Get the number of studies
        num_studies = get_count('qiita.study')

        # Get the number of samples
        num_samples = len(lats)

        # Get the number of users
        num_users = get_count('qiita.qiita_user')

        callback([num_studies, num_samples, num_users, lat_longs])

    @coroutine
    def get(self):
        num_studies, num_samples, num_users, lat_longs = \
            yield Task(self._get_stats)

        # Pull a random public study from the database
        study = Study(choice(Study.get_public()))

        self.render('stats.html', user=self.current_user,
                    num_studies=num_studies, num_samples=num_samples,
                    num_users=num_users, lat_longs=lat_longs,
                    random_study_info=study.info,
                    random_study_title=study.title, random_study_id=study.id)
<|endoftext|>


<commit_before>import numpy
import sympy

from ..helpers import article
from ..helpers import fs_array as fs
from ..helpers import fsd, untangle, z
from ._helpers import S2Scheme, expand_symmetries
from ._peirce_1956 import peirce_1956_1, peirce_1956_3
from ._radon import radon

_source = article(
    authors=["Preston C. Hammer", "Arthur H. Stroud"],
    title="Numerical Evaluation of Multiple Integrals II",
    journal="Math. Comp.",
    volume="12",
    year="1958",
    pages="272-280",
    url="https://doi.org/10.1090/S0025-5718-1958-0102176-6",
)

frac = sympy.Rational
pi = sympy.pi
sqrt = numpy.vectorize(sympy.sqrt)
pm_ = numpy.array([+1, -1])
cos = numpy.vectorize(sympy.cos)
sin = numpy.vectorize(sympy.sin)

def hammer_stroud_11_2():
    # ERR Incorrectly stated in Stroud with 0.5 instead of sqrt(0.5)
    d = {"s40": [[frac(1, 4)], [sqrt(frac(1, 2))]]}
    points, weights = expand_symmetries(d)
    return S2Scheme("Hammer-Stroud 11-2", weights, points, 3, _source)

def hammer_stroud_12_2():
    d = {
        "zero": [[frac(1, 6)]],
        "s40": [[frac(1, 6)], [sqrt(frac(1, 2))]],
        "pm": [[frac(1, 24)], [sqrt(frac(1, 2))], [sqrt(frac(1, 2))]],
    }
    points, weights = expand_symmetries(d)
    return S2Scheme("Hammer-Stroud 12-2", weights, points, 5, _source)

def hammer_stroud_13_2():
    return peirce_1956_1()

def hammer_stroud_17():
    # DUP ENH This is Radon's formula.
    return radon(0)

def hammer_stroud_18():
    # ENH The article only gives floats, but really this is the spherical-product gauss
    # formula as described in Strouds book, S2 7-2.
    #
    # data = [
    #     (frac(1, 16), fs([0.4247082002778669, 0.1759198966061612])),
    #     (frac(1, 16), fs([0.8204732385702833, 0.3398511429799874])),
    # ]
    r1, r2 = sqrt((3 - pm_ * sqrt(3)) / 6)

    a = (2 * numpy.arange(8) + 1) * pi / 8
    x = numpy.array([cos(a), sin(a)]).T

    data = [(frac(1, 16), r1 * x), (frac(1, 16), r2 * x)]
    points, weights = untangle(data)
    return S2Scheme("Hammer-Stroud 18", weights, points, 7, _source)

def hammer_stroud_19():
    sqrt6 = sqrt(6)
    alpha1 = (16 + sqrt6) / 288
    alpha2 = (137 - 32 * sqrt6) / 1818
    alpha3 = (520 + 155 * sqrt6) / 3636 / 8

    a = sqrt((6 + sqrt6) / 10)

    data = [
        (frac(1, 9), z(2)),
        (alpha1, fs([0.5505043204538557, 0.2280263556769715])),
        (alpha2, fsd(2, (a, 1))),
        (alpha3, fs([0.7932084745126058, 0.4645097310495256])),
    ]
    points, weights = untangle(data)
    return S2Scheme("Hammer-Stroud 19", weights, points, 9, _source)

def hammer_stroud_20():
    # ENH Also Peirce's formula, even given symbolically.
    return peirce_1956_3()

def hammer_stroud_21():
    alpha0 = 0.0341505695624825 / numpy.pi
    alpha1 = 0.0640242008621985 / numpy.pi
    alpha2 = 0.0341505695624825 / numpy.pi

    data = [
        (alpha0, fs([0.2584361661674054, 0.0514061496288813])),
        (alpha1, fs([0.5634263397544869, 0.1120724670846205])),
        (alpha1, fs([0.4776497869993547, 0.3191553840796721])),
        (alpha1, fs([0.8028016728473508, 0.1596871812824163])),
        (alpha1, fs([0.6805823955716280, 0.4547506180649039])),
        (alpha2, fs([0.2190916025980981, 0.1463923286035535])),
        (alpha2, fs([0.9461239423417719, 0.1881957532057769])),
        (alpha2, fs([0.8020851487551318, 0.5359361621905023])),
    ]

    points, weights = untangle(data)
    return S2Scheme("Hammer-Stroud 21", weights, points, 15, _source)
<commit_msg>s2: hammer-stroud: some modernization<commit_after>import numpy
import sympy

from ..helpers import article
from ._helpers import S2Scheme, expand_symmetries
from ._peirce_1956 import peirce_1956_1, peirce_1956_3
from ._radon import radon

_source = article(
    authors=["Preston C. Hammer", "Arthur H. Stroud"],
    title="Numerical Evaluation of Multiple Integrals II",
    journal="Math. Comp.",
    volume="12",
    year="1958",
    pages="272-280",
    url="https://doi.org/10.1090/S0025-5718-1958-0102176-6",
)

frac = sympy.Rational
pi = sympy.pi
sqrt = numpy.vectorize(sympy.sqrt)
pm_ = numpy.array([+1, -1])
cos = numpy.vectorize(sympy.cos)
sin = numpy.vectorize(sympy.sin)

def hammer_stroud_11_2():
    # ERR Incorrectly stated in Stroud with 0.5 instead of sqrt(0.5)
    d = {"s40": [[frac(1, 4)], [sqrt(frac(1, 2))]]}
    points, weights = expand_symmetries(d)
    return S2Scheme("Hammer-Stroud 11-2", weights, points, 3, _source)

def hammer_stroud_12_2():
    d = {
        "zero": [[frac(1, 6)]],
        "s40": [[frac(1, 6)], [sqrt(frac(1, 2))]],
        "pm": [[frac(1, 24)], [sqrt(frac(1, 2))], [sqrt(frac(1, 2))]],
    }
    points, weights = expand_symmetries(d)
    return S2Scheme("Hammer-Stroud 12-2", weights, points, 5, _source)

def hammer_stroud_13_2():
    return peirce_1956_1()

def hammer_stroud_17():
    # DUP ENH This is Radon's formula.
    return radon(0)

def hammer_stroud_18():
    # ENH The article only gives floats, but really this is the spherical-product gauss
    # formula as described in Strouds book, S2 7-2.
    #
    # data = [
    #     (frac(1, 16), fs([0.4247082002778669, 0.1759198966061612])),
    #     (frac(1, 16), fs([0.8204732385702833, 0.3398511429799874])),
    # ]
    r1, r2 = sqrt((3 - pm_ * sqrt(3)) / 6)

    a = (2 * numpy.arange(8) + 1) * pi / 8
    x = numpy.array([cos(a), sin(a)]).T

    points = numpy.vstack([r1 * x, r2 * x])
    weights = numpy.full(points.shape[0], frac(1, 16))
    return S2Scheme("Hammer-Stroud 18", weights, points, 7, _source)

def hammer_stroud_19():
    sqrt6 = sqrt(6)
    alpha1 = (16 + sqrt6) / 288
    alpha2 = (137 - 32 * sqrt6) / 1818
    alpha3 = (520 + 155 * sqrt6) / 3636 / 8

    a = sqrt((6 + sqrt6) / 10)

    d = {
        "zero": [[frac(1, 9)]],
        "fsd": [
            [alpha1, alpha3],
            [0.5505043204538557, 0.7932084745126058],
            [0.2280263556769715, 0.4645097310495256],
        ],
        "s40": [[alpha2], [a]],
    }
    points, weights = expand_symmetries(d)
    return S2Scheme("Hammer-Stroud 19", weights, points, 9, _source)

def hammer_stroud_20():
    # ENH Also Peirce's formula, even given symbolically.
    return peirce_1956_3()

def hammer_stroud_21():
    alpha0 = 0.0341505695624825 / numpy.pi
    alpha1 = 0.0640242008621985 / numpy.pi
    alpha2 = 0.0341505695624825 / numpy.pi

    d = {
        "fsd": [
            [alpha0, alpha1, alpha1, alpha1, alpha1, alpha2, alpha2, alpha2],
            [
                0.2584361661674054,
                0.5634263397544869,
                0.4776497869993547,
                0.8028016728473508,
                0.6805823955716280,
                0.2190916025980981,
                0.9461239423417719,
                0.8020851487551318,
            ],
            [
                0.0514061496288813,
                0.1120724670846205,
                0.3191553840796721,
                0.1596871812824163,
                0.4547506180649039,
                0.1463923286035535,
                0.1881957532057769,
                0.5359361621905023,
            ],
        ],
    }
    points, weights = expand_symmetries(d)
    return S2Scheme("Hammer-Stroud 21", weights, points, 15, _source)
<|endoftext|>


<commit_before>alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
encryptions = []
class var:
        def __init__(self, obj): self.obj = obj;
        def get(self):    return self.obj
        def set(self, obj):      self.obj = obj
class reverse:
    name = "reverse"
    def start(self, encrypt, sentance):
        done = False;
        if encrypt == False:
            self.decrypt(sentance)
        else:
            self.encrypt(sentance)
    def encrypt(sentence):
        final = ""
        i = len(sentence) -1
        while(i != -1):
            final+= sentence[i];
            i -= 1
        return  final;
    def decrypt(sentence):
        final = ""
        i = len(sentence) -1
        while(i != -1):
            final+= sentence[i];
            i -= 1
        return  final;

class caesar:
    name = "caesar"
    def start(self, encrypt, sentance):
        done = False;
        while (not done):
            try:
                key = int(input("Whats the key? "))
                done=True
            except TypeError:
                print("ERROR, NON-INT INPUTED")
                done = False
        if encrypt == False:
            self.decrypt(key, sentance)
        else:
            self.encrypt(key, sentance)

    def encrypt(key, sentance):
        returnMessage = ""
        for char in sentance:
            pos = alphabet.find(char)
            if char not in alphabet:
                returnMessage += char
            else:
                if pos + key > 25:
                    returnMessage+= alphabet[pos + key - 26]
                else:
                    returnMessage += alphabet[pos + key]
        return returnMessage
    def decrypt(key, sentance):
        returnMessage = ""
        for char in sentance:
            pos = alphabet.find(char)
            if char not in alphabet:
                returnMessage += char
            else:
                if pos - key < 0:
                    returnMessage+= alphabet[pos - key + 26]
                else:
                    returnMessage += alphabet[pos - key]
        return returnMessage

encryptions.append(var(caesar()))
encryptions.append(var(reverse()))

encryptionType = input("What cipher do you want to use? Reverse/Caesar: ").lower()
sentance = input("What sentance do yo want to encrypt/decrypt? " ).upper()
done = False;

while (not done):
    endy = input("Encrypt or decrypt? ").upper()
    if endy == "ENCRYPT" or "DECRYPT":
        done = True;
    else:
        print("ANSWER NOT ENCRYPT OR DECRYPT")

for encryption in encryptions:
    if encryption.get().name == encryptionType:
        if endy == "ENCRYPT":
            print("Encrypting")
            print(encryption.get().start(True, sentance))
        else:
            print(encryption.get().start(False, sentance))
            print("Decrypting")
    else:
        print("FATAL ERROR, NON ENCRYPTION TYPE INPUTED")<commit_msg>Bug fixes<commit_after>alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
encryptions = []
class var:
        def __init__(self, obj): self.obj = obj;
        def get(self):    return self.obj
        def set(self, obj):      self.obj = obj
class reverse:
    name = "reverse"
    def start(self, encrypt, sentance):
        done = False;
        if encrypt == False:
            self.decrypt(sentance)
        else:
            self.encrypt(sentance)
    def encrypt(sentence):
        final = ""
        i = len(sentence) -1
        while(i != -1):
            final+= sentence[i];
            i -= 1
        return  final;
    def decrypt(sentence):
        final = ""
        i = len(sentence) -1
        while(i != -1):
            final+= sentence[i];
            i -= 1
        return  final;

class caesar:
    name = "caesar"
    def start(self, encrypt, sentance):
        done = False;
        while (not done):
            try:
                key = int(input("Whats the key? "))
                done=True
            except TypeError:
                print("ERROR, NON-INT INPUTED")
                done = False
        if encrypt == False:
            self.decrypt(key, sentance)
        else:
            self.encrypt(key, sentance)

    def encrypt(self, key, sentance):
        returnMessage = ""
        for char in sentance:
            pos = alphabet.find(char)
            if char not in alphabet:
                returnMessage += char
            else:
                if pos + key > 25:
                    returnMessage+= alphabet[pos + key - 26]
                else:
                    returnMessage += alphabet[pos + key]
        return returnMessage
    def decrypt(self, key, sentance):
        returnMessage = ""
        for char in sentance:
            pos = alphabet.find(char)
            if char not in alphabet:
                returnMessage += char
            else:
                if pos - key < 0:
                    returnMessage+= alphabet[pos - key + 26]
                else:
                    returnMessage += alphabet[pos - key]
        return returnMessage

encryptions.append(var(caesar()))
encryptions.append(var(reverse()))

encryptionType = input("What cipher do you want to use? Reverse/Caesar: ").lower()
sentance = input("What sentance do yo want to encrypt/decrypt? " ).upper()
done = False;

while (not done):
    endy = input("Encrypt or decrypt? ").upper()
    if endy == "ENCRYPT" or "DECRYPT":
        done = True;
    else:
        print("ANSWER NOT ENCRYPT OR DECRYPT")

for encryption in encryptions:
    if encryption.get().name == encryptionType:
        if endy == "ENCRYPT":
            print("Encrypting")
            print(encryption.get().start(True, sentance))
        else:
            print(encryption.get().start(False, sentance))
            print("Decrypting")
    else:
        print("FATAL ERROR, NON ENCRYPTION TYPE INPUTED")<|endoftext|>


<commit_before>import os
import unittest

from test_spglib import dirnames
from vasp import read_vasp

from spglib import get_hall_number_from_symmetry, get_symmetry_dataset

data_dir = os.path.dirname(os.path.abspath(__file__))

class TestGetHallNumberFromSymmetry(unittest.TestCase):
    def setUp(self):
        self._filenames = []
        for d in dirnames:
            dirname = os.path.join(data_dir, "data", d)
            filenames = os.listdir(dirname)
            self._filenames += [os.path.join(dirname, fname) for fname in filenames]

    def tearDown(self):
        pass

    def test_get_hall_number_from_symmetry(self):
        for fname in self._filenames:
            cell = read_vasp(fname)
            if "distorted" in fname:
                dataset = get_symmetry_dataset(cell, symprec=1e-1)
                hall_number = get_hall_number_from_symmetry(
                    dataset["rotations"], dataset["translations"], symprec=1e-1
                )
                if hall_number != dataset["hall_number"]:
                    print(
                        "%d != %d in %s" % (hall_number, dataset["hall_number"], fname)
                    )
                    ref_cell = (
                        dataset["std_lattice"],
                        dataset["std_positions"],
                        dataset["std_types"],
                    )
                    dataset = get_symmetry_dataset(ref_cell, symprec=1e-5)
                    hall_number = get_hall_number_from_symmetry(
                        dataset["rotations"], dataset["translations"], symprec=1e-5
                    )
                    print(
                        "Using refined cell: %d, %d in %s"
                        % (hall_number, dataset["hall_number"], fname)
                    )
            else:
                dataset = get_symmetry_dataset(cell, symprec=1e-5)
                hall_number = get_hall_number_from_symmetry(
                    dataset["rotations"], dataset["translations"], symprec=1e-5
                )
            self.assertEqual(
                hall_number,
                dataset["hall_number"],
                msg=("%d != %d in %s" % (hall_number, dataset["hall_number"], fname)),
            )

if __name__ == "__main__":
    suite = unittest.TestLoader().loadTestsFromTestCase(TestGetHallNumberFromSymmetry)
    unittest.TextTestRunner(verbosity=2).run(suite)
    # unittest.main()
<commit_msg>Migrate test_hall_number_from_symmetry.py to pytest and ignore::DeprecationWarning<commit_after>"""Test of get_hall_number_from_symmetry."""
from __future__ import annotations

import os
from pathlib import Path
from typing import Callable

import pytest

from spglib import get_hall_number_from_symmetry, get_symmetry_dataset

data_dir = os.path.dirname(os.path.abspath(__file__))

@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_get_hall_number_from_symmetry(all_filenames: list[Path], read_vasp: Callable):
    """Test get_hall_number_from_symmetry."""
    for fname in all_filenames:
        cell = read_vasp(fname)
        if "distorted" in str(fname):
            dataset = get_symmetry_dataset(cell, symprec=1e-1)
            hall_number = get_hall_number_from_symmetry(
                dataset["rotations"], dataset["translations"], symprec=1e-1
            )
            if hall_number != dataset["hall_number"]:
                print("%d != %d in %s" % (hall_number, dataset["hall_number"], fname))
                ref_cell = (
                    dataset["std_lattice"],
                    dataset["std_positions"],
                    dataset["std_types"],
                )
                dataset = get_symmetry_dataset(ref_cell, symprec=1e-5)
                hall_number = get_hall_number_from_symmetry(
                    dataset["rotations"], dataset["translations"], symprec=1e-5
                )
                print(
                    "Using refined cell: %d, %d in %s"
                    % (hall_number, dataset["hall_number"], fname)
                )
        else:
            dataset = get_symmetry_dataset(cell, symprec=1e-5)
            hall_number = get_hall_number_from_symmetry(
                dataset["rotations"], dataset["translations"], symprec=1e-5
            )
        assert hall_number == dataset["hall_number"], "%d != %d in %s" % (
            hall_number,
            dataset["hall_number"],
            fname,
        )
<|endoftext|>


<commit_before># This file is part of LiSE, a framework for life simulation games.
# Copyright (C) Zachary Spector, ZacharySpector@gmail.com
"""Object to configure, start, and stop ELiDE."""

import json

from kivy.logger import Logger
from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.resources import resource_add_path

from kivy.uix.screenmanager import ScreenManager

from kivy.properties import (
    AliasProperty,
    ObjectProperty,
    NumericProperty,
    StringProperty
)
import LiSE
from LiSE.proxy import EngineProcessManager
import ELiDE
import ELiDE.screen
import ELiDE.stores
import ELiDE.statcfg
import ELiDE.spritebuilder
import ELiDE.rulesview
import ELiDE.charsview
from ELiDE.board.board import Board
from ELiDE.board.arrow import ArrowWidget
from ELiDE.board.spot import Spot
from ELiDE.board.pawn import Pawn
from .util import trigger

resource_add_path(ELiDE.__path__[0] + "/assets")
resource_add_path(ELiDE.__path__[0] + "/assets/rltiles")

class ELiDEApp(App):
    """Extensible LiSE Development Environment.

    """
    title = 'ELiDE'
    icon = 'icon.png'

    engine = ObjectProperty()
    branch = StringProperty('trunk')
    tick = NumericProperty(0)
    character = ObjectProperty()
    selection = ObjectProperty(None, allownone=True)
    selected_remote = ObjectProperty()

    def _get_character_name(self, *args):
        if self.character is None:
            return
        return self.character.name

    def _set_character_name(self, name):
        if self.character.name != name:
            self.character = self.engine.character[name]

    character_name = AliasProperty(
        _get_character_name,
        _set_character_name,
        bind=('character',)
    )

    def _pull_time(self, *args):
        if not self.engine:
            Clock.schedule_once(self._pull_time, 0)
            return
        (self.branch, self.tick) = self.engine.time
    pull_time = trigger(_pull_time)

    @trigger
    def _push_time(self, *args):
        if self.engine.time != (self.branch, self.tick):
            self.engine.time_travel(
                self.branch, self.tick,
                chars=[self.character.name],
                cb=self.mainscreen._update_from_chardiff
            )

    def set_tick(self, t):
        """Set my tick to the given value, cast to an integer."""
        self.tick = int(t)

    def set_time(self, b, t=None):
        if t is None:
            (b, t) = b
        t = int(t)
        (self.branch, self.tick) = (b, t)

    def select_character(self, char):
        """Change my ``character`` to the selected character object if they
        aren't the same.

        """
        if char == self.character:
            return
        self.character = char

    def build_config(self, config):
        """Set config defaults"""
        for sec in 'LiSE', 'ELiDE':
            config.adddefaultsection(sec)
        config.setdefaults(
            'LiSE',
            {
                'world': 'sqlite:///LiSEworld.db',
                'code': 'LiSEcode.db',
                'language': 'eng',
                'logfile': '',
                'loglevel': 'info'
            }
        )
        config.setdefaults(
            'ELiDE',
            {
                'boardchar': 'physical',
                'debugger': 'no',
                'inspector': 'no',
                'user_kv': 'yes',
                'play_speed': '1',
                'thing_graphics': json.dumps([
                    ("Marsh Davies' Island", 'marsh_davies_island_fg.atlas'),
                    ('RLTiles: Body', 'base.atlas'),
                    ('RLTiles: Basic clothes', 'body.atlas'),
                    ('RLTiles: Armwear', 'arm.atlas'),
                    ('RLTiles: Legwear', 'leg.atlas'),
                    ('RLTiles: Right hand', 'hand1.atlas'),
                    ('RLTiles: Left hand', 'hand2.atlas'),
                    ('RLTiles: Boots', 'boot.atlas'),
                    ('RLTiles: Hair', 'hair.atlas'),
                    ('RLTiles: Beard', 'beard.atlas'),
                    ('RLTiles: Headwear', 'head.atlas')
                ]),
                'place_graphics': json.dumps([
                    ("Marsh Davies' Island", 'marsh_davies_island_bg.atlas'),
                    ("Marsh Davies' Crypt", 'marsh_davies_crypt.atlas'),
                    ('RLTiles: Dungeon', 'dungeon.atlas')
                ])
            }
        )
        config.write()

    def build(self):
        """Make sure I can use the database, create the tables as needed, and
        return the root widget.

        """
        config = self.config
        Logger.debug(
            "ELiDEApp: starting with world {}, code {}, path {}".format(
                config['LiSE']['world'],
                config['LiSE']['code'],
                LiSE.__path__[-1]
            )
        )

        if config['ELiDE']['debugger'] == 'yes':
            import pdb
            pdb.set_trace()

        self.manager = ScreenManager()
        if config['ELiDE']['inspector'] == 'yes':
            from kivy.core.window import Window
            from kivy.modules import inspector
            inspector.create_inspector(Window, self.manager)

        Clock.schedule_once(self._start_subprocess, 0.1)
        Clock.schedule_once(self._add_screens, 0.2)
        return self.manager

    def _start_subprocess(self, *args):
        config = self.config
        self.procman = EngineProcessManager()
        enkw = {'logger': Logger}
        if config['LiSE'].get('logfile'):
            enkw['logfile'] = config['LiSE']['logfile']
        if config['LiSE'].get('loglevel'):
            enkw['loglevel'] = config['LiSE']['loglevel']
        self.engine = self.procman.start(
            config['LiSE']['world'],
            config['LiSE']['code'],
            **enkw
        )
        self.pull_time()

        @self.engine.time.connect
        def pull_time(inst, **kwargs):
            self.branch = inst.branch
            self.tick = inst.tick

        @self.engine.string.language.connect
        def pull_lang(inst, **kwargs):
            self.strings.language = kwargs['language']

        @self.engine.character.connect
        def pull_chars(*args):
            self.chars.names = list(self.engine.character)

        self.bind(
            branch=self._push_time,
            tick=self._push_time
        )

        char = config['ELiDE']['boardchar']
        if char not in self.engine.character:
            self.engine.add_character(char)

    def _add_screens(self, *args):
        def toggler(screenname):
            def tog(*args):
                if self.manager.current == screenname:
                    self.manager.current = 'main'
                else:
                    self.manager.current = screenname
            return tog
        config = self.config

        self.pawncfg = ELiDE.spritebuilder.PawnConfigScreen(
            toggle=toggler('pawncfg'),
            data=json.loads(config['ELiDE']['thing_graphics'])
        )

        self.spotcfg = ELiDE.spritebuilder.SpotConfigScreen(
            toggle=toggler('spotcfg'),
            data=json.loads(config['ELiDE']['place_graphics'])
        )

        self.rules = ELiDE.rulesview.RulesScreen(
            engine=self.engine,
            toggle=toggler('rules')
        )

        self.chars = ELiDE.charsview.CharactersScreen(
            engine=self.engine,
            toggle=toggler('chars'),
            names=list(self.engine.character),
            new_board=self.new_board
        )
        self.bind(character_name=self.chars.setter('character_name'))

        def chars_push_character_name(*args):
            self.unbind(character_name=self.chars.setter('character_name'))
            self.character_name = self.chars.character_name
            self.bind(character_name=self.chars.setter('character_name'))

        self.chars.push_character_name = chars_push_character_name

        self.strings = ELiDE.stores.StringsEdScreen(
            language=self.engine.string.language,
            language_setter=self._set_language,
            toggle=toggler('strings')
        )

        self.funcs = ELiDE.stores.FuncsEdScreen(
            name='funcs',
            toggle=toggler('funcs')
        )

        self.select_character(
            self.engine.character[
                config['ELiDE']['boardchar']
            ]
        )

        self.statcfg = ELiDE.statcfg.StatScreen(
            toggle=toggler('statcfg'),
            branch=self.branch,
            tick=self.tick,
            engine=self.engine
        )
        self.bind(
            selected_remote=self.statcfg.setter('remote'),
            branch=self.statcfg.setter('branch'),
            tick=self.statcfg.setter('tick')
        )

        self.mainscreen = ELiDE.screen.MainScreen(
            use_kv=config['ELiDE']['user_kv'] == 'yes',
            play_speed=int(config['ELiDE']['play_speed']),
            boards={
                name: Board(
                    character=char
                ) for name, char in self.engine.character.items()
            }
        )
        if self.mainscreen.statlist:
            self.statcfg.statlist = self.mainscreen.statlist
        self.mainscreen.bind(statlist=self.statcfg.setter('statlist'))
        self.bind(
            selection=self.reremote,
            character=self.reremote
        )
        self.selected_remote = self._get_selected_remote()
        for wid in (
                self.mainscreen,
                self.pawncfg,
                self.spotcfg,
                self.statcfg,
                self.rules,
                self.chars,
                self.strings,
                self.funcs
        ):
            self.manager.add_widget(wid)

    def _set_language(self, lang):
        self.engine.string.language = lang

    def _get_selected_remote(self):
        if self.selection is None:
            return self.character.stat
        elif hasattr(self.selection, 'remote'):
            return self.selection.remote
        elif (
                hasattr(self.selection, 'portal') and
                self.selection.portal is not None
        ):
            return self.selection.portal
        else:
            raise ValueError("Invalid selection: {}".format(self.selection))

    def reremote(self, *args):
        self.selected_remote = self._get_selected_remote()

    def on_character_name(self, *args):
        if self.config['ELiDE']['boardchar'] != self.character_name:
            self.config['ELiDE']['boardchar'] = self.character_name

    def on_character(self, *args):
        self.selection = None

    def on_pause(self):
        """Sync the database with the current state of the game."""
        self.engine.commit()
        self.config.write()

    def on_stop(self, *largs):
        """Sync the database, wrap up the game, and halt."""
        self.procman.shutdown()
        self.config.write()

    def on_selection(self, *args):
        Logger.debug("ELiDEApp: selection {}".format(self.selection))

    def delete_selection(self):
        """Delete both the selected widget and whatever it represents."""
        selection = self.selection
        if selection is None:
            return
        if isinstance(selection, ArrowWidget):
            self.selection = None
            self.mainscreen.boardview.board.rm_arrow(
                selection.origin.name,
                selection.destination.name
            )
            selection.portal.delete()
        elif isinstance(selection, Spot):
            self.selection = None
            self.mainscreen.boardview.board.rm_spot(selection.name)
            selection.remote.delete()
        else:
            assert isinstance(selection, Pawn)
            self.selection = None
            self.mainscreen.boardview.board.rm_pawn(selection.name)
            selection.remote.delete()

    def new_board(self, name):
        """Make a board for a character name, and switch to it."""
        char = self.engine.character[name]
        board = Board(character=char)
        self.mainscreen.boards[name] = board
        self.character = char

kv = """
<App>:
    time: [root.branch, root.tick]
    selected_remote: root.selection.remote if root.selection else None
<SymbolLabel@Label>:
    font_name: "Symbola.ttf"
    font_size: 50
<SymbolButton@Button>:
    font_name: "Symbola.ttf"
    font_size: 50
"""
Builder.load_string(kv)
<commit_msg>Don't pass code databae to engine proxy<commit_after># This file is part of LiSE, a framework for life simulation games.
# Copyright (C) Zachary Spector, ZacharySpector@gmail.com
"""Object to configure, start, and stop ELiDE."""

import json

from kivy.logger import Logger
from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.resources import resource_add_path

from kivy.uix.screenmanager import ScreenManager

from kivy.properties import (
    AliasProperty,
    ObjectProperty,
    NumericProperty,
    StringProperty
)
import LiSE
from LiSE.proxy import EngineProcessManager
import ELiDE
import ELiDE.screen
import ELiDE.stores
import ELiDE.statcfg
import ELiDE.spritebuilder
import ELiDE.rulesview
import ELiDE.charsview
from ELiDE.board.board import Board
from ELiDE.board.arrow import ArrowWidget
from ELiDE.board.spot import Spot
from ELiDE.board.pawn import Pawn
from .util import trigger

resource_add_path(ELiDE.__path__[0] + "/assets")
resource_add_path(ELiDE.__path__[0] + "/assets/rltiles")

class ELiDEApp(App):
    """Extensible LiSE Development Environment.

    """
    title = 'ELiDE'
    icon = 'icon.png'

    engine = ObjectProperty()
    branch = StringProperty('trunk')
    tick = NumericProperty(0)
    character = ObjectProperty()
    selection = ObjectProperty(None, allownone=True)
    selected_remote = ObjectProperty()

    def _get_character_name(self, *args):
        if self.character is None:
            return
        return self.character.name

    def _set_character_name(self, name):
        if self.character.name != name:
            self.character = self.engine.character[name]

    character_name = AliasProperty(
        _get_character_name,
        _set_character_name,
        bind=('character',)
    )

    def _pull_time(self, *args):
        if not self.engine:
            Clock.schedule_once(self._pull_time, 0)
            return
        (self.branch, self.tick) = self.engine.time
    pull_time = trigger(_pull_time)

    @trigger
    def _push_time(self, *args):
        if self.engine.time != (self.branch, self.tick):
            self.engine.time_travel(
                self.branch, self.tick,
                chars=[self.character.name],
                cb=self.mainscreen._update_from_chardiff
            )

    def set_tick(self, t):
        """Set my tick to the given value, cast to an integer."""
        self.tick = int(t)

    def set_time(self, b, t=None):
        if t is None:
            (b, t) = b
        t = int(t)
        (self.branch, self.tick) = (b, t)

    def select_character(self, char):
        """Change my ``character`` to the selected character object if they
        aren't the same.

        """
        if char == self.character:
            return
        self.character = char

    def build_config(self, config):
        """Set config defaults"""
        for sec in 'LiSE', 'ELiDE':
            config.adddefaultsection(sec)
        config.setdefaults(
            'LiSE',
            {
                'world': 'sqlite:///LiSEworld.db',
                'language': 'eng',
                'logfile': '',
                'loglevel': 'info'
            }
        )
        config.setdefaults(
            'ELiDE',
            {
                'boardchar': 'physical',
                'debugger': 'no',
                'inspector': 'no',
                'user_kv': 'yes',
                'play_speed': '1',
                'thing_graphics': json.dumps([
                    ("Marsh Davies' Island", 'marsh_davies_island_fg.atlas'),
                    ('RLTiles: Body', 'base.atlas'),
                    ('RLTiles: Basic clothes', 'body.atlas'),
                    ('RLTiles: Armwear', 'arm.atlas'),
                    ('RLTiles: Legwear', 'leg.atlas'),
                    ('RLTiles: Right hand', 'hand1.atlas'),
                    ('RLTiles: Left hand', 'hand2.atlas'),
                    ('RLTiles: Boots', 'boot.atlas'),
                    ('RLTiles: Hair', 'hair.atlas'),
                    ('RLTiles: Beard', 'beard.atlas'),
                    ('RLTiles: Headwear', 'head.atlas')
                ]),
                'place_graphics': json.dumps([
                    ("Marsh Davies' Island", 'marsh_davies_island_bg.atlas'),
                    ("Marsh Davies' Crypt", 'marsh_davies_crypt.atlas'),
                    ('RLTiles: Dungeon', 'dungeon.atlas')
                ])
            }
        )
        config.write()

    def build(self):
        """Make sure I can use the database, create the tables as needed, and
        return the root widget.

        """
        config = self.config
        Logger.debug(
            "ELiDEApp: starting with world {}, code {}, path {}".format(
                config['LiSE']['world'],
                config['LiSE']['code'],
                LiSE.__path__[-1]
            )
        )

        if config['ELiDE']['debugger'] == 'yes':
            import pdb
            pdb.set_trace()

        self.manager = ScreenManager()
        if config['ELiDE']['inspector'] == 'yes':
            from kivy.core.window import Window
            from kivy.modules import inspector
            inspector.create_inspector(Window, self.manager)

        Clock.schedule_once(self._start_subprocess, 0.1)
        Clock.schedule_once(self._add_screens, 0.2)
        return self.manager

    def _start_subprocess(self, *args):
        config = self.config
        self.procman = EngineProcessManager()
        enkw = {'logger': Logger}
        if config['LiSE'].get('logfile'):
            enkw['logfile'] = config['LiSE']['logfile']
        if config['LiSE'].get('loglevel'):
            enkw['loglevel'] = config['LiSE']['loglevel']
        self.engine = self.procman.start(
            config['LiSE']['world'],
            **enkw
        )
        self.pull_time()

        @self.engine.time.connect
        def pull_time(inst, **kwargs):
            self.branch = inst.branch
            self.tick = inst.tick

        @self.engine.string.language.connect
        def pull_lang(inst, **kwargs):
            self.strings.language = kwargs['language']

        @self.engine.character.connect
        def pull_chars(*args):
            self.chars.names = list(self.engine.character)

        self.bind(
            branch=self._push_time,
            tick=self._push_time
        )

        char = config['ELiDE']['boardchar']
        if char not in self.engine.character:
            self.engine.add_character(char)

    def _add_screens(self, *args):
        def toggler(screenname):
            def tog(*args):
                if self.manager.current == screenname:
                    self.manager.current = 'main'
                else:
                    self.manager.current = screenname
            return tog
        config = self.config

        self.pawncfg = ELiDE.spritebuilder.PawnConfigScreen(
            toggle=toggler('pawncfg'),
            data=json.loads(config['ELiDE']['thing_graphics'])
        )

        self.spotcfg = ELiDE.spritebuilder.SpotConfigScreen(
            toggle=toggler('spotcfg'),
            data=json.loads(config['ELiDE']['place_graphics'])
        )

        self.rules = ELiDE.rulesview.RulesScreen(
            engine=self.engine,
            toggle=toggler('rules')
        )

        self.chars = ELiDE.charsview.CharactersScreen(
            engine=self.engine,
            toggle=toggler('chars'),
            names=list(self.engine.character),
            new_board=self.new_board
        )
        self.bind(character_name=self.chars.setter('character_name'))

        def chars_push_character_name(*args):
            self.unbind(character_name=self.chars.setter('character_name'))
            self.character_name = self.chars.character_name
            self.bind(character_name=self.chars.setter('character_name'))

        self.chars.push_character_name = chars_push_character_name

        self.strings = ELiDE.stores.StringsEdScreen(
            language=self.engine.string.language,
            language_setter=self._set_language,
            toggle=toggler('strings')
        )

        self.funcs = ELiDE.stores.FuncsEdScreen(
            name='funcs',
            toggle=toggler('funcs')
        )

        self.select_character(
            self.engine.character[
                config['ELiDE']['boardchar']
            ]
        )

        self.statcfg = ELiDE.statcfg.StatScreen(
            toggle=toggler('statcfg'),
            branch=self.branch,
            tick=self.tick,
            engine=self.engine
        )
        self.bind(
            selected_remote=self.statcfg.setter('remote'),
            branch=self.statcfg.setter('branch'),
            tick=self.statcfg.setter('tick')
        )

        self.mainscreen = ELiDE.screen.MainScreen(
            use_kv=config['ELiDE']['user_kv'] == 'yes',
            play_speed=int(config['ELiDE']['play_speed']),
            boards={
                name: Board(
                    character=char
                ) for name, char in self.engine.character.items()
            }
        )
        if self.mainscreen.statlist:
            self.statcfg.statlist = self.mainscreen.statlist
        self.mainscreen.bind(statlist=self.statcfg.setter('statlist'))
        self.bind(
            selection=self.reremote,
            character=self.reremote
        )
        self.selected_remote = self._get_selected_remote()
        for wid in (
                self.mainscreen,
                self.pawncfg,
                self.spotcfg,
                self.statcfg,
                self.rules,
                self.chars,
                self.strings,
                self.funcs
        ):
            self.manager.add_widget(wid)

    def _set_language(self, lang):
        self.engine.string.language = lang

    def _get_selected_remote(self):
        if self.selection is None:
            return self.character.stat
        elif hasattr(self.selection, 'remote'):
            return self.selection.remote
        elif (
                hasattr(self.selection, 'portal') and
                self.selection.portal is not None
        ):
            return self.selection.portal
        else:
            raise ValueError("Invalid selection: {}".format(self.selection))

    def reremote(self, *args):
        self.selected_remote = self._get_selected_remote()

    def on_character_name(self, *args):
        if self.config['ELiDE']['boardchar'] != self.character_name:
            self.config['ELiDE']['boardchar'] = self.character_name

    def on_character(self, *args):
        self.selection = None

    def on_pause(self):
        """Sync the database with the current state of the game."""
        self.engine.commit()
        self.config.write()

    def on_stop(self, *largs):
        """Sync the database, wrap up the game, and halt."""
        self.procman.shutdown()
        self.config.write()

    def on_selection(self, *args):
        Logger.debug("ELiDEApp: selection {}".format(self.selection))

    def delete_selection(self):
        """Delete both the selected widget and whatever it represents."""
        selection = self.selection
        if selection is None:
            return
        if isinstance(selection, ArrowWidget):
            self.selection = None
            self.mainscreen.boardview.board.rm_arrow(
                selection.origin.name,
                selection.destination.name
            )
            selection.portal.delete()
        elif isinstance(selection, Spot):
            self.selection = None
            self.mainscreen.boardview.board.rm_spot(selection.name)
            selection.remote.delete()
        else:
            assert isinstance(selection, Pawn)
            self.selection = None
            self.mainscreen.boardview.board.rm_pawn(selection.name)
            selection.remote.delete()

    def new_board(self, name):
        """Make a board for a character name, and switch to it."""
        char = self.engine.character[name]
        board = Board(character=char)
        self.mainscreen.boards[name] = board
        self.character = char

kv = """
<App>:
    time: [root.branch, root.tick]
    selected_remote: root.selection.remote if root.selection else None
<SymbolLabel@Label>:
    font_name: "Symbola.ttf"
    font_size: 50
<SymbolButton@Button>:
    font_name: "Symbola.ttf"
    font_size: 50
"""
Builder.load_string(kv)
<|endoftext|>


<commit_before>import sublime, sublime_plugin, re, shutil, functools, os
from subprocess import Popen, call

class ExternReplUp(sublime_plugin.TextCommand):
    "sends up arrow"
    def run(self, edit):
        self.view.run_command("save")
        if sublime.platform() == 'windows':
            Popen('ConEmuC -GuiMacro:0 Keys("Up");Paste(0,"\\n")')
        else:
            command= 'tmux send-keys -t repl Up C-m'
            print("Command = " + command)
            return Popen(command,shell=True)

class ExternReplOps(sublime_plugin.TextCommand):
    def run(self, edit, what):
        if self.view.is_dirty():
            self.view.run_command("save")
        init_er(self)
        self.er.command(self.er.ops_get(what)())

class ExternReplHistory(sublime_plugin.TextCommand):
    "runs the command from the history"
    def run(self, edit):
        init_er(self)
        self.view.window().show_quick_panel(self.er.history.entries, self.select )
    def select(self, x):
        if (x != -1):
            self.er.command(self.er.history.entries[x])

class ExternReplFile(sublime_plugin.TextCommand):
    "opens the file or webgage in curretn line"
    def run(self, edit):
        init_er(self)
        file = self.er.line
        if (re.match("^http",file)):
            print("browse to file")
            Popen("chrome "+file)
        else:
            print("opening "+file)
            self.view.window().open_file(file)

class ExternReplRefresh(sublime_plugin.TextCommand):
    "invoked be F5, new version of run"
    def run(self, edit):
        if self.view.is_dirty():
            self.view.run_command("save")
        init_er(self)
        self.manual_refresh() or self.test() or self.runn()

    def manual_refresh(self):
        # dictionary of {file: command ,... }
        manual = {
          os.environ["scripts2"] + "\\libwba\\functions.md":"ruby \\Dropbox\\sublime\\data\\packages\\ExternalREPL\\ruby\\psdoc.rb > %scripts2%\\libwba\\functions.md"
        }
        if (self.er.file_name in manual):
            command = manual[self.er.file_name]
            return_code = call(command, shell=True)
            print ("manual refresh with: " + command + "(" + str(return_code) + ")")
            return True

    def test(self):
        if (self.er.ops_get('test?')()):
            print("run tests")
            self.er.command(self.er.ops_get('test')())
            return True

    def runn(self):
        print("runn")
        self.er.command(self.er.ops_get('run')())

class ExternReplAlternate(sublime_plugin.TextCommand):
    "switches from file to test and reverse"
    def run(self, edit):
        init_er(self)
        other = self.er.alternate(self.view.file_name())
        print("switch to: "+ other)
        self.view.window().open_file(other)

class ExternReplDublicateFile(sublime_plugin.TextCommand):
    "copies current file and opens it"
    def run(self, edit):
        if self.view.is_dirty():
            self.view.run_command("save")
        file = self.view.file_name()
        v = self.view.window().show_input_panel("Copy File to:", file, functools.partial(self.on_done,file), None, None)
        name, ext = os.path.splitext(file)
        v.sel().clear()
        v.sel().add(sublime.Region(0, len(name)))

    def on_done(self,src, dst):
        shutil.copyfile(src, dst)
        self.view.window().open_file(dst)

class ExternReplMarkdownToc(sublime_plugin.TextCommand):
    "copies current file and opens it"
    def run(self, edit):
        if self.view.is_dirty():
            self.view.run_command("save")
        file = self.view.file_name()
        if re.compile( r'\.md$',re.I).search(file):
            #c:\project\file.tests.ps1
            toc = re.sub(r'\.md$',".md.toc",file)
            command = "ruby "+sublime.packages_path()+"\\ExternalREPL\\ruby\\toc.rb "+file+" > "+toc
            return_code = call(command, shell=True)
            self.view.window().open_file(toc)
        elif re.compile( r'\.md.toc$',re.I).search(file):
            md = re.sub(r'\.md\.toc$',".md",file)
            command = "ruby "+sublime.packages_path()+"\\ExternalREPL\\ruby\\retoc.rb "+file+" "+md #+" > "+md
            return_code = call(command, shell=True)
            self.view.window().open_file(md)

class ExternReplShowOutput(sublime_plugin.WindowCommand):
    "pipes textbuffer into command"
    def run(self):
        self.output_view = self.window.create_output_panel("exec")
        self.output_view.run_command('append', {'characters': 'Hallo output view', 'force': True, 'scroll_to_end': True})
        self.window.run_command("show_panel", {"panel": "output.exec"})

class ExternReplMoveFile(sublime_plugin.TextCommand):
    "renames current file and opens it"
    def run(self, edit):
        if self.view.is_dirty():
            self.view.run_command("save")
        file = self.view.file_name()
        v = self.view.window().show_input_panel("Copy File to:", file, functools.partial(self.on_done,file), None, None)
        name, ext = os.path.splitext(file)
        v.sel().clear()
        v.sel().add(sublime.Region(0, len(name)))

    def on_done(self,src, dst):
        try:
            os.rename(src, dst)
            self.view.retarget(dst)
        except:
            sublime.status_message("Unable to rename")

class History:
    def __init__(self,project):
        self.project = project
        self.settings = sublime.load_settings("ExternalRepl.last-run")
        self.all_entries = self.settings.get("historys") or {}
        self.entries = self.all_entries.get( self.project) or []

    def append(self,text):
        self.entries.insert(0,text) # prepend
        self.remove_dublicates()
        self.all_entries[self.project] = self.entries
        self.settings.set("historys", self.all_entries)
        sublime.save_settings("ExternalRepl.last-run")

    def remove_dublicates(self):
        "while retaining order"
        seen = set()
        seen_add = seen.add
        self.entries = [ x for x in self.entries if x not in seen and not seen_add(x)]

class Er:
    def __init__(self,stc):
        self.error = None # can be set
        self.stc  = stc
        self.view = stc.view
        self.file_name = self.view.file_name()
        folders = [f for f in sublime.active_window().folders() if self.file_name.lower().startswith(f.lower())] # project directory
        if not folders:
         #   self.error ="Project Folder needs to be incuded in Side Bar (can't find project folder)"
            self.path = ""
            self.file = self.file_name
        else:
            self.path = folders[0]
            self.file = self.file_name[len(self.path)+1:]
        self.history = History(self.path)
        scopes = self.view.scope_name(self.view.sel()[0].begin()) # source.python meta.structure.list.python punctuation.definition.list.begin.python
        langs = ["python","powershell","ruby","clojure","markdown"]
        match = [l for l in langs if l in scopes]

        self.lang = "unknown"
        if match:    self.lang = match[0]

        self.ops_lang = {
            "powershell": {
                "test?":             lambda: re.match(".*\.tests\.ps1$",self.file_name), # is this a test file ?
                "load":              lambda: '. ' + self.file_name,
                "run":               lambda: self.file_name,
                "test":              lambda: 'invoke-pester ' + self.file,
                "test_one_pattern":  """^\s*(?:d|D)escribe\s+(?:'|")(.*)(?:'|")\s*\{\s*$""",
                "test_one":          lambda: 'invoke-pester ' + self.file + ' -testname ' + ' '.join(['"'+i+'"' for i in self.selected_testnames]),
            },
            "clojure": {
                "load":              lambda: '(load-file "' + self.file.replace("\\","/") + '")',
                "line":              lambda: self.clojure_current_form,
                "cd":                lambda: self.clojure_cd,
            },
            "ruby": {
                "test_one_pattern": """^\s*it\s+(?:'|")(.*)(?:'|")\s+do\s*$""",
                "test":              lambda: 'ruby  -I test'+os.pathsep+'lib ' + self.file.replace("\\","/") ,
                "load":              lambda: 'load "' + self.file_name.replace("\\","/") + '"',
                "run":               lambda: 'ruby -I lib ' + self.file,
                "test_one":          lambda: 'ruby -I lib' + os.pathsep +'test ' + self.file + ' --name "/' + '|'.join([ '^test_\d{4}_'+i+'$' for i in self.selected_testnames]) +'/"',
                                     # ruby -I lib;test test\couch_test.rb --name /^test_\d{4}_describe1$|^test_\d{4}_describe2$/"
            },
            "python": {
                "run":               lambda: 'python ' + self.file,
            },
            "markdown": {
                "load": lambda: "pandoc -r markdown_github+footnotes+grid_tables -o \"" + re.sub("\..+$",".docx",self.file) + "\" \"" + self.file +"\"",
                "run":  lambda: self.ops_lang.get("markdown").get("load")() + " && \"" + re.sub("\..+$",".docx",self.file) + "\"",
            },
        }
        self.ops_platform = {
            "windows": {
                "cd":       lambda: 'cd "' + self.path + '"',
                "explorer": lambda: "explorer " + self.path,
            }
        }
        self.ops = {
                "line":     lambda: self.line,
                "last":     lambda: self.history.entries[0],
                "test?":    lambda: False,
        }

    def ops_get(self,operation):
        return self.ops_lang.get(self.lang,{}).get(operation) \
            or self.ops_platform.get(sublime.platform(),{}).get(operation) \
            or self.ops.get(operation) \
            or (lambda: "Cannot find operation '"+operation+"' for lang="+self.lang + ", Platform="+sublime.platform())

    @property
    def line(self):
        for region in self.view.sel():
            if region.empty():
                line = self.view.line(region)
                line_contents = self.view.substr(line)
                line_below = sublime.Region(line.b+1)
                self.view.sel().clear()
                self.view.sel().add(line_below)
                return line_contents
            else:
                return self.view.substr(region)

    @property
    def clojure_current_form(self):
        opening = []
        regions = self.view.find_all("^\(",fmt="$1",extractions=opening)
        for i,region in enumerate(regions[:-1]):
            region.b = regions[i+1].a-1
        regions[-1].b = self.view.size()
        forms = []
        for region in regions:
            for s in self.view.sel():
                if s.intersects(region):
                    forms.append( self.view.substr(region) )
        return "".join(forms)

    @property
    def clojure_cd(self):
        ns = self.view.find(r"\(\s*ns [\w\.]+", 0)
        return self.view.substr(ns) + ")"

    @property
    def testnames(self):
        "( (region, 'name'),... )"
        testnames = []
        regions = self.view.find_all(self.ops_get("test_one_pattern"),fmt="$1",extractions=testnames)
        regions[0].a  = 0
        regions[-1].b = self.view.size()
        for i,region in enumerate(regions[:-1]):
            region.b = regions[i+1].a
        return [ (region, testnames.pop(0)) for region in regions]

    @property
    def selected_testnames(self):
        "list of testnames"
        acc = []
        for region, testname in self.testnames:
            for s in self.view.sel():
                if s.intersects(region):
                    acc.append( testname )
        return acc

    def command(self,command):
        self.history.append(command)
        # \ => \\ | " => \" | remove \n
        quoted = command.replace('\\','\\\\')\
                        .replace('"','\\"')
        if sublime.platform() == 'windows':
            command = 'ConEmuC -GuiMacro:0 Paste(0,"' + quoted + '\\n")'
            Popen(command)
        else:
            # Multiline with tmux needs multiple commands
            for line in quoted.split('\n'):
                command = 'tmux send-keys -t repl "' + line + '" C-m'
                Popen(command,shell=True)

    # test switching
    def alternate(self,file):
        return getattr(self, "alternate_"+ self.lang)(file)

    # converters for alternate file witching named altenate_syntax
    def alternate_powershell(self,file):
        if re.compile( r'\.tests\.',re.I).search(file):
            # c:\project\file.tests.ps1
            return re.sub(r'\.tests\.',".",file)
        else:
            # c:\project\file.ps1
            return re.sub(r'\.ps1$',".tests.ps1",file)

    def alternate_ruby(self,file):
        if re.compile( r'\\test_',re.I).search(file):
            # c:\project\test\bar\test_foo.ps1
            a = re.sub(r'\\test\\',"\\\\lib\\\\",file)
            return re.sub(r'\\test_',"\\\\",a)
        else:
            # c:\project\lib\bar\foo.ps1
            a = re.sub(r'\\lib\\',"\\\\test\\\\",file)
            return re.sub(r'\\([^\\]+)$',"\\\\test_\g<1>", a)

# returns false if there is an error happening
def init_er(self):
    self.er = Er(self)
    if self.er.error:
        print(self.er.error)
        return False
    else:
        return True

<commit_msg>uncomment single Line<commit_after>import sublime, sublime_plugin, re, shutil, functools, os
from subprocess import Popen, call

class ExternReplUp(sublime_plugin.TextCommand):
    "sends up arrow"
    def run(self, edit):
        self.view.run_command("save")
        if sublime.platform() == 'windows':
            Popen('ConEmuC -GuiMacro:0 Keys("Up");Paste(0,"\\n")')
        else:
            command= 'tmux send-keys -t repl Up C-m'
            print("Command = " + command)
            return Popen(command,shell=True)

class ExternReplOps(sublime_plugin.TextCommand):
    def run(self, edit, what):
        if self.view.is_dirty():
            self.view.run_command("save")
        init_er(self)
        self.er.command(self.er.ops_get(what)())

class ExternReplHistory(sublime_plugin.TextCommand):
    "runs the command from the history"
    def run(self, edit):
        init_er(self)
        self.view.window().show_quick_panel(self.er.history.entries, self.select )
    def select(self, x):
        if (x != -1):
            self.er.command(self.er.history.entries[x])

class ExternReplFile(sublime_plugin.TextCommand):
    "opens the file or webgage in curretn line"
    def run(self, edit):
        init_er(self)
        file = self.er.line
        if (re.match("^http",file)):
            print("browse to file")
            Popen("chrome "+file)
        else:
            print("opening "+file)
            self.view.window().open_file(file)

class ExternReplRefresh(sublime_plugin.TextCommand):
    "invoked be F5, new version of run"
    def run(self, edit):
        if self.view.is_dirty():
            self.view.run_command("save")
        init_er(self)
        self.manual_refresh() or self.test() or self.runn()

    def manual_refresh(self):
        # dictionary of {file: command ,... }
        manual = {
          os.environ["scripts2"] + "\\libwba\\functions.md":"ruby \\Dropbox\\sublime\\data\\packages\\ExternalREPL\\ruby\\psdoc.rb > %scripts2%\\libwba\\functions.md"
        }
        if (self.er.file_name in manual):
            command = manual[self.er.file_name]
            return_code = call(command, shell=True)
            print ("manual refresh with: " + command + "(" + str(return_code) + ")")
            return True

    def test(self):
        if (self.er.ops_get('test?')()):
            print("run tests")
            self.er.command(self.er.ops_get('test')())
            return True

    def runn(self):
        print("runn")
        self.er.command(self.er.ops_get('run')())

class ExternReplAlternate(sublime_plugin.TextCommand):
    "switches from file to test and reverse"
    def run(self, edit):
        init_er(self)
        other = self.er.alternate(self.view.file_name())
        print("switch to: "+ other)
        self.view.window().open_file(other)

class ExternReplDublicateFile(sublime_plugin.TextCommand):
    "copies current file and opens it"
    def run(self, edit):
        if self.view.is_dirty():
            self.view.run_command("save")
        file = self.view.file_name()
        v = self.view.window().show_input_panel("Copy File to:", file, functools.partial(self.on_done,file), None, None)
        name, ext = os.path.splitext(file)
        v.sel().clear()
        v.sel().add(sublime.Region(0, len(name)))

    def on_done(self,src, dst):
        shutil.copyfile(src, dst)
        self.view.window().open_file(dst)

class ExternReplMarkdownToc(sublime_plugin.TextCommand):
    "copies current file and opens it"
    def run(self, edit):
        if self.view.is_dirty():
            self.view.run_command("save")
        file = self.view.file_name()
        if re.compile( r'\.md$',re.I).search(file):
            #c:\project\file.tests.ps1
            toc = re.sub(r'\.md$',".md.toc",file)
            command = "ruby "+sublime.packages_path()+"\\ExternalREPL\\ruby\\toc.rb "+file+" > "+toc
            return_code = call(command, shell=True)
            self.view.window().open_file(toc)
        elif re.compile( r'\.md.toc$',re.I).search(file):
            md = re.sub(r'\.md\.toc$',".md",file)
            command = "ruby "+sublime.packages_path()+"\\ExternalREPL\\ruby\\retoc.rb "+file+" "+md #+" > "+md
            return_code = call(command, shell=True)
            self.view.window().open_file(md)

class ExternReplShowOutput(sublime_plugin.WindowCommand):
    "pipes textbuffer into command"
    def run(self):
        self.output_view = self.window.create_output_panel("exec")
        self.output_view.run_command('append', {'characters': 'Hallo output view', 'force': True, 'scroll_to_end': True})
        self.window.run_command("show_panel", {"panel": "output.exec"})

class ExternReplMoveFile(sublime_plugin.TextCommand):
    "renames current file and opens it"
    def run(self, edit):
        if self.view.is_dirty():
            self.view.run_command("save")
        file = self.view.file_name()
        v = self.view.window().show_input_panel("Copy File to:", file, functools.partial(self.on_done,file), None, None)
        name, ext = os.path.splitext(file)
        v.sel().clear()
        v.sel().add(sublime.Region(0, len(name)))

    def on_done(self,src, dst):
        try:
            os.rename(src, dst)
            self.view.retarget(dst)
        except:
            sublime.status_message("Unable to rename")

class History:
    def __init__(self,project):
        self.project = project
        self.settings = sublime.load_settings("ExternalRepl.last-run")
        self.all_entries = self.settings.get("historys") or {}
        self.entries = self.all_entries.get( self.project) or []

    def append(self,text):
        self.entries.insert(0,text) # prepend
        self.remove_dublicates()
        self.all_entries[self.project] = self.entries
        self.settings.set("historys", self.all_entries)
        sublime.save_settings("ExternalRepl.last-run")

    def remove_dublicates(self):
        "while retaining order"
        seen = set()
        seen_add = seen.add
        self.entries = [ x for x in self.entries if x not in seen and not seen_add(x)]

class Er:
    def __init__(self,stc):
        self.error = None # can be set
        self.stc  = stc
        self.view = stc.view
        self.file_name = self.view.file_name()
        folders = [f for f in sublime.active_window().folders() if self.file_name.lower().startswith(f.lower())] # project directory
        if not folders:
         #   self.error ="Project Folder needs to be incuded in Side Bar (can't find project folder)"
            self.path = ""
            self.file = self.file_name
        else:
            self.path = folders[0]
            self.file = self.file_name[len(self.path)+1:]
        self.history = History(self.path)
        scopes = self.view.scope_name(self.view.sel()[0].begin()) # source.python meta.structure.list.python punctuation.definition.list.begin.python
        langs = ["python","powershell","ruby","clojure","markdown"]
        match = [l for l in langs if l in scopes]

        self.lang = "unknown"
        if match:    self.lang = match[0]

        self.ops_lang = {
            "powershell": {
                "test?":             lambda: re.match(".*\.tests\.ps1$",self.file_name), # is this a test file ?
                "load":              lambda: '. ' + self.file_name,
                "run":               lambda: self.file_name,
                "test":              lambda: 'invoke-pester ' + self.file,
                "test_one_pattern":  """^\s*(?:d|D)escribe\s+(?:'|")(.*)(?:'|")\s*\{\s*$""",
                "test_one":          lambda: 'invoke-pester ' + self.file + ' -testname ' + ' '.join(['"'+i+'"' for i in self.selected_testnames]),
            },
            "clojure": {
                "load":              lambda: '(load-file "' + self.file.replace("\\","/") + '")',
                "line":              lambda: self.clojure_current_form,
                "cd":                lambda: self.clojure_cd,
            },
            "ruby": {
                "test_one_pattern": """^\s*it\s+(?:'|")(.*)(?:'|")\s+do\s*$""",
                "test":              lambda: 'ruby  -I test'+os.pathsep+'lib ' + self.file.replace("\\","/") ,
                "load":              lambda: 'load "' + self.file_name.replace("\\","/") + '"',
                "run":               lambda: 'ruby -I lib ' + self.file,
                "test_one":          lambda: 'ruby -I lib' + os.pathsep +'test ' + self.file + ' --name "/' + '|'.join([ '^test_\d{4}_'+i+'$' for i in self.selected_testnames]) +'/"',
                                     # ruby -I lib;test test\couch_test.rb --name /^test_\d{4}_describe1$|^test_\d{4}_describe2$/"
            },
            "python": {
                "run":               lambda: 'python ' + self.file,
            },
            "markdown": {
                "load": lambda: "pandoc -r markdown_github+footnotes+grid_tables -o \"" + re.sub("\..+$",".docx",self.file) + "\" \"" + self.file +"\"",
                "run":  lambda: self.ops_lang.get("markdown").get("load")() + " && \"" + re.sub("\..+$",".docx",self.file) + "\"",
            },
        }
        self.ops_platform = {
            "windows": {
                "cd":       lambda: 'cd "' + self.path + '"',
                "explorer": lambda: "explorer " + self.path,
            }
        }
        self.ops = {
                "line":     lambda: self.line,
                "lineuncomment": lambda s: re.sub(r"^\s*#\s*","",s),
                "last":     lambda: self.history.entries[0],
                "test?":    lambda: False,
        }

    def ops_get(self,operation):
        return self.ops_lang.get(self.lang,{}).get(operation) \
            or self.ops_platform.get(sublime.platform(),{}).get(operation) \
            or self.ops.get(operation) \
            or (lambda: "Cannot find operation '"+operation+"' for lang="+self.lang + ", Platform="+sublime.platform())

    @property
    def line(self):
        for region in self.view.sel():
            if region.empty():
                line = self.view.line(region)
                line_contents = self.view.substr(line)
                line_below = sublime.Region(line.b+1)
                self.view.sel().clear()
                self.view.sel().add(line_below)
                return self.ops_get("lineuncomment")(line_contents)
            else:
                return self.view.substr(region)

    @property
    def clojure_current_form(self):
        opening = []
        regions = self.view.find_all("^\(",fmt="$1",extractions=opening)
        for i,region in enumerate(regions[:-1]):
            region.b = regions[i+1].a-1
        regions[-1].b = self.view.size()
        forms = []
        for region in regions:
            for s in self.view.sel():
                if s.intersects(region):
                    forms.append( self.view.substr(region) )
        return "".join(forms)

    @property
    def clojure_cd(self):
        ns = self.view.find(r"\(\s*ns [\w\.]+", 0)
        return self.view.substr(ns) + ")"

    @property
    def testnames(self):
        "( (region, 'name'),... )"
        testnames = []
        regions = self.view.find_all(self.ops_get("test_one_pattern"),fmt="$1",extractions=testnames)
        regions[0].a  = 0
        regions[-1].b = self.view.size()
        for i,region in enumerate(regions[:-1]):
            region.b = regions[i+1].a
        return [ (region, testnames.pop(0)) for region in regions]

    @property
    def selected_testnames(self):
        "list of testnames"
        acc = []
        for region, testname in self.testnames:
            for s in self.view.sel():
                if s.intersects(region):
                    acc.append( testname )
        return acc

    def command(self,command):
        self.history.append(command)
        # \ => \\ | " => \" | remove \n
        quoted = command.replace('\\','\\\\')\
                        .replace('"','\\"')
        if sublime.platform() == 'windows':
            command = 'ConEmuC -GuiMacro:0 Paste(0,"' + quoted + '\\n")'
            Popen(command)
        else:
            # Multiline with tmux needs multiple commands
            for line in quoted.split('\n'):
                command = 'tmux send-keys -t repl "' + line + '" C-m'
                Popen(command,shell=True)

    # test switching
    def alternate(self,file):
        return getattr(self, "alternate_"+ self.lang)(file)

    # converters for alternate file witching named altenate_syntax
    def alternate_powershell(self,file):
        if re.compile( r'\.tests\.',re.I).search(file):
            # c:\project\file.tests.ps1
            return re.sub(r'\.tests\.',".",file)
        else:
            # c:\project\file.ps1
            return re.sub(r'\.ps1$',".tests.ps1",file)

    def alternate_ruby(self,file):
        if re.compile( r'\\test_',re.I).search(file):
            # c:\project\test\bar\test_foo.ps1
            a = re.sub(r'\\test\\',"\\\\lib\\\\",file)
            return re.sub(r'\\test_',"\\\\",a)
        else:
            # c:\project\lib\bar\foo.ps1
            a = re.sub(r'\\lib\\',"\\\\test\\\\",file)
            return re.sub(r'\\([^\\]+)$',"\\\\test_\g<1>", a)

# returns false if there is an error happening
def init_er(self):
    self.er = Er(self)
    if self.er.error:
        print(self.er.error)
        return False
    else:
        return True

<|endoftext|>