<commit_before>import RPi.GPIO as GPIO
import spi as SPI
import signal
import time

class RFID:
    pin_rst = 22
    pin_ce = 0

    mode_idle = 0x00
    mode_auth = 0x0E
    mode_receive = 0x08
    mode_transmit = 0x04
    mode_transrec = 0x0C
    mode_reset = 0x0F
    mode_crc = 0x03

    auth_a = 0x60
    auth_b = 0x61

    act_read = 0x30
    act_write = 0xA0
    act_increment = 0xC1
    act_decrement = 0xC0
    act_restore = 0xC2
    act_transfer = 0xB0

    act_reqidl = 0x26
    act_reqall = 0x52
    act_anticl = 0x93
    act_select = 0x93
    act_end = 0x50

    reg_tx_control = 0x14
    length = 16

    authed = False

    def __init__(self, dev='/dev/spidev0.0', speed=1000000, pin_rst=22, pin_ce=0):
        self.pin_rst = pin_rst
        self.pin_ce = pin_ce

        SPI.openSPI(device=dev, speed=speed)
        GPIO.setmode(GPIO.BOARD)
        GPIO.setup(pin_rst, GPIO.OUT)
        GPIO.output(pin_rst, 1)
        if pin_ce != 0:
	        GPIO.setup(pin_ce, GPIO.OUT)
	        GPIO.output(pin_ce, 1)
        self.reset()
        self.dev_write(0x2A, 0x8D)
        self.dev_write(0x2B, 0x3E)
        self.dev_write(0x2D, 30)
        self.dev_write(0x2C, 0)
        self.dev_write(0x15, 0x40)
        self.dev_write(0x11, 0x3D)
        self.set_antenna(True)

    def spi_transfer(self, data):
        if self.pin_ce != 0:
	        GPIO.output(pin_ce, 0)
        SPI.transfer(data)
        if self.pin_ce != 0:
	        GPIO.output(pin_ce, 1)

    def dev_write(self, address, value):
        self.spi_transfer(((address << 1) & 0x7E, value))

    def dev_read(self, address):
        return self.spi_transfer((((address << 1) & 0x7E) | 0x80, 0))[1]

    def set_bitmask(self, address, mask):
        current = self.dev_read(address)
        self.dev_write(address, current | mask)

    def clear_bitmask(self, address, mask):
        current = self.dev_read(address)
        self.dev_write(address, current & (~mask))

    def set_antenna(self, state):
        if state == True:
            current = self.dev_read(self.reg_tx_control)
            if ~(current & 0x03):
                self.set_bitmask(self.reg_tx_control, 0x03)
        else:
            self.clear_bitmask(self.reg_tx_control, 0x03)

    def card_write(self, command, data):
        back_data = []
        back_length = 0
        error = False
        irq = 0x00
        irq_wait = 0x00
        last_bits = None
        n = 0

        if command == self.mode_auth:
            irq = 0x12
            irq_wait = 0x10
        if command == self.mode_transrec:
            irq = 0x77
            irq_wait = 0x30

        self.dev_write(0x02, irq | 0x80)
        self.clear_bitmask(0x04, 0x80)
        self.set_bitmask(0x0A, 0x80)
        self.dev_write(0x01, self.mode_idle)

        for i in range(len(data)):
            self.dev_write(0x09, data[i])

        self.dev_write(0x01, command)

        if command == self.mode_transrec:
            self.set_bitmask(0x0D, 0x80)

        i = 2000
        while True:
            n = self.dev_read(0x04)
            i -= 1
            if ~((i != 0) and ~(n & 0x01) and ~(n & irq_wait)):
                break

        self.clear_bitmask(0x0D, 0x80)

        if i != 0:
            if (self.dev_read(0x06) & 0x1B) == 0x00:
                error = False

                if n & irq & 0x01:
                    print("E1")
                    error = True

                if command == self.mode_transrec:
                    n = self.dev_read(0x0A)
                    last_bits = self.dev_read(0x0C) & 0x07
                    if last_bits != 0:
                        back_length = (n - 1) * 8 + last_bits
                    else:
                        back_length = n * 8

                    if n == 0:
                        n = 1

                    if n > self.length:
                        n = self.length

                    for i in range(n):
                        back_data.append(self.dev_read(0x09))
            else:
                print("E2")
                error = True

        return (error, back_data, back_length)

    def request(self, req_mode=0x26):
        """
        Requests for tag.
        Returns (False, None) if no tag is present, otherwise returns (True, tag type)
        """
        error = True
        back_bits = 0

        self.dev_write(0x0D, 0x07)
        (error, back_data, back_bits) = self.card_write(self.mode_transrec, [req_mode, ])

        if error or (back_bits != 0x10):
            return (True, None)

        return (False, back_bits)

    def anticoll(self):
        """
        Anti-collision detection.
        Returns tuple of (error state, tag ID).
        """
        back_data = []
        serial_number = []

        serial_number_check = 0

        self.dev_write(0x0D, 0x00)
        serial_number.append(self.act_anticl)
        serial_number.append(0x20)

        (error, back_data, back_bits) = self.card_write(self.mode_transrec, serial_number)
        if not error:
            if len(back_data) == 5:
                for i in range(4):
                    serial_number_check = serial_number_check ^ back_data[i]

                if serial_number_check != back_data[4]:
                    error = True
            else:
                error = True

        return (error, back_data)

    def calculate_crc(self, data):
        self.clear_bitmask(0x05, 0x04)
        self.set_bitmask(0x0A, 0x80)

        for i in range(len(data)):
            self.dev_write(0x09, data[i])
        self.dev_write(0x01, self.mode_crc)

        i = 255
        while True:
            n = self.dev_read(0x05)
            i -= 1
            if not ((i != 0) and not (n & 0x04)):
                break

        ret_data = []
        ret_data.append(self.dev_read(0x22))
        ret_data.append(self.dev_read(0x21))

        return ret_data

    def select_tag(self, uid):
        """
        Selects tag for further usage.
        uid -- list or tuple with four bytes tag ID
        Returns error state.
        """
        back_data = []
        buf = []

        buf.append(self.act_select)
        buf.append(0x70)

        for i in range(5):
            buf.append(uid[i])

        crc = self.calculate_crc(buf)
        buf.append(crc[0])
        buf.append(crc[1])

        (error, back_data, back_length) = self.card_write(self.mode_transrec, buf)

        if (not error) and (back_length == 0x18):
            return False
        else:
            return True

    def card_auth(self, auth_mode, block_address, key, uid):
        """
        Authenticates to use specified block address. Tag must be selected using select_tag(uid) before auth.
        auth_mode -- RFID.auth_a or RFID.auth_b
        key -- list or tuple with six bytes key
        uid -- list or tuple with four bytes tag ID
        Returns error state.
        """
        buf = []
        buf.append(auth_mode)
        buf.append(block_address)

        for i in range(len(key)):
            buf.append(key[i])

        for i in range(4):
            buf.append(uid[i])

        (error, back_data, back_length) = self.card_write(self.mode_auth, buf)
        if not (self.dev_read(0x08) & 0x08) != 0:
            error = True

        if not error:
            self.authed = True

        return error

    def stop_crypto(self):
        """Ends operations with Crypto1 usage."""
        self.clear_bitmask(0x08, 0x08)
        self.authed = False

    def read(self, block_address):
        """
        Reads data from block. You should be authenticated before calling read.
        Returns tuple of (error state, read data).
        """
        buf = []
        buf.append(self.act_read)
        buf.append(block_address)
        crc = self.calculate_crc(buf)
        buf.append(crc[0])
        buf.append(crc[1])
        (error, back_data, back_length) = self.card_write(self.mode_transrec, buf)

        if len(back_data) != 16:
            error = True

        return (error, back_data)

    def write(self, block_address, data):
        """
        Writes data to block. You should be authenticated before calling write.
        Returns error state.
        """
        buf = []
        buf.append(self.act_write)
        buf.append(block_address)
        crc = self.calculate_crc(buf)
        buf.append(crc[0])
        buf.append(crc[1])
        (error, back_data, back_length) = self.card_write(self.mode_transrec, buf)
        if not(back_length == 4) or not((back_data[0] & 0x0F) == 0x0A):
            error = True

        if not error:
            buf_w = []
            for i in range(16):
                buf_w.append(data[i])

            crc = self.calculate_crc(buf_w)
            buf_w.append(crc[0])
            buf_w.append(crc[1])
            (error, back_data, back_length) = self.card_write(self.mode_transrec, buf_w)
            if not(back_length == 4) or not((back_data[0] & 0x0F) == 0x0A):
                error = True

        return error

    def reset(self):
        self.dev_write(0x01, self.mode_reset)

    def cleanup(self):
        """
        Calls stop_crypto() if needed and cleanups GPIO.
        """
        if self.authed:
            self.stop_crypto()
        GPIO.cleanup()

    def util(self):
        """
        Creates and returns RFIDUtil object for this RFID instance.
        If module is not present, returns None.
        """
        try:
            import RFIDUtil
            return RFIDUtil.RFIDUtil(self)
        except ImportError:
            return None<commit_msg>Added self to pin_ce<commit_after>import RPi.GPIO as GPIO
import spi as SPI
import signal
import time

class RFID:
    pin_rst = 22
    pin_ce = 0

    mode_idle = 0x00
    mode_auth = 0x0E
    mode_receive = 0x08
    mode_transmit = 0x04
    mode_transrec = 0x0C
    mode_reset = 0x0F
    mode_crc = 0x03

    auth_a = 0x60
    auth_b = 0x61

    act_read = 0x30
    act_write = 0xA0
    act_increment = 0xC1
    act_decrement = 0xC0
    act_restore = 0xC2
    act_transfer = 0xB0

    act_reqidl = 0x26
    act_reqall = 0x52
    act_anticl = 0x93
    act_select = 0x93
    act_end = 0x50

    reg_tx_control = 0x14
    length = 16

    authed = False

    def __init__(self, dev='/dev/spidev0.0', speed=1000000, pin_rst=22, pin_ce=0):
        self.pin_rst = pin_rst
        self.pin_ce = pin_ce

        SPI.openSPI(device=dev, speed=speed)
        GPIO.setmode(GPIO.BOARD)
        GPIO.setup(pin_rst, GPIO.OUT)
        GPIO.output(pin_rst, 1)
        if pin_ce != 0:
	        GPIO.setup(pin_ce, GPIO.OUT)
	        GPIO.output(pin_ce, 1)
        self.reset()
        self.dev_write(0x2A, 0x8D)
        self.dev_write(0x2B, 0x3E)
        self.dev_write(0x2D, 30)
        self.dev_write(0x2C, 0)
        self.dev_write(0x15, 0x40)
        self.dev_write(0x11, 0x3D)
        self.set_antenna(True)

    def spi_transfer(self, data):
        if self.pin_ce != 0:
	        GPIO.output(self.pin_ce, 0)
        SPI.transfer(data)
        if self.pin_ce != 0:
	        GPIO.output(self.pin_ce, 1)

    def dev_write(self, address, value):
        self.spi_transfer(((address << 1) & 0x7E, value))

    def dev_read(self, address):
        return self.spi_transfer((((address << 1) & 0x7E) | 0x80, 0))[1]

    def set_bitmask(self, address, mask):
        current = self.dev_read(address)
        self.dev_write(address, current | mask)

    def clear_bitmask(self, address, mask):
        current = self.dev_read(address)
        self.dev_write(address, current & (~mask))

    def set_antenna(self, state):
        if state == True:
            current = self.dev_read(self.reg_tx_control)
            if ~(current & 0x03):
                self.set_bitmask(self.reg_tx_control, 0x03)
        else:
            self.clear_bitmask(self.reg_tx_control, 0x03)

    def card_write(self, command, data):
        back_data = []
        back_length = 0
        error = False
        irq = 0x00
        irq_wait = 0x00
        last_bits = None
        n = 0

        if command == self.mode_auth:
            irq = 0x12
            irq_wait = 0x10
        if command == self.mode_transrec:
            irq = 0x77
            irq_wait = 0x30

        self.dev_write(0x02, irq | 0x80)
        self.clear_bitmask(0x04, 0x80)
        self.set_bitmask(0x0A, 0x80)
        self.dev_write(0x01, self.mode_idle)

        for i in range(len(data)):
            self.dev_write(0x09, data[i])

        self.dev_write(0x01, command)

        if command == self.mode_transrec:
            self.set_bitmask(0x0D, 0x80)

        i = 2000
        while True:
            n = self.dev_read(0x04)
            i -= 1
            if ~((i != 0) and ~(n & 0x01) and ~(n & irq_wait)):
                break

        self.clear_bitmask(0x0D, 0x80)

        if i != 0:
            if (self.dev_read(0x06) & 0x1B) == 0x00:
                error = False

                if n & irq & 0x01:
                    print("E1")
                    error = True

                if command == self.mode_transrec:
                    n = self.dev_read(0x0A)
                    last_bits = self.dev_read(0x0C) & 0x07
                    if last_bits != 0:
                        back_length = (n - 1) * 8 + last_bits
                    else:
                        back_length = n * 8

                    if n == 0:
                        n = 1

                    if n > self.length:
                        n = self.length

                    for i in range(n):
                        back_data.append(self.dev_read(0x09))
            else:
                print("E2")
                error = True

        return (error, back_data, back_length)

    def request(self, req_mode=0x26):
        """
        Requests for tag.
        Returns (False, None) if no tag is present, otherwise returns (True, tag type)
        """
        error = True
        back_bits = 0

        self.dev_write(0x0D, 0x07)
        (error, back_data, back_bits) = self.card_write(self.mode_transrec, [req_mode, ])

        if error or (back_bits != 0x10):
            return (True, None)

        return (False, back_bits)

    def anticoll(self):
        """
        Anti-collision detection.
        Returns tuple of (error state, tag ID).
        """
        back_data = []
        serial_number = []

        serial_number_check = 0

        self.dev_write(0x0D, 0x00)
        serial_number.append(self.act_anticl)
        serial_number.append(0x20)

        (error, back_data, back_bits) = self.card_write(self.mode_transrec, serial_number)
        if not error:
            if len(back_data) == 5:
                for i in range(4):
                    serial_number_check = serial_number_check ^ back_data[i]

                if serial_number_check != back_data[4]:
                    error = True
            else:
                error = True

        return (error, back_data)

    def calculate_crc(self, data):
        self.clear_bitmask(0x05, 0x04)
        self.set_bitmask(0x0A, 0x80)

        for i in range(len(data)):
            self.dev_write(0x09, data[i])
        self.dev_write(0x01, self.mode_crc)

        i = 255
        while True:
            n = self.dev_read(0x05)
            i -= 1
            if not ((i != 0) and not (n & 0x04)):
                break

        ret_data = []
        ret_data.append(self.dev_read(0x22))
        ret_data.append(self.dev_read(0x21))

        return ret_data

    def select_tag(self, uid):
        """
        Selects tag for further usage.
        uid -- list or tuple with four bytes tag ID
        Returns error state.
        """
        back_data = []
        buf = []

        buf.append(self.act_select)
        buf.append(0x70)

        for i in range(5):
            buf.append(uid[i])

        crc = self.calculate_crc(buf)
        buf.append(crc[0])
        buf.append(crc[1])

        (error, back_data, back_length) = self.card_write(self.mode_transrec, buf)

        if (not error) and (back_length == 0x18):
            return False
        else:
            return True

    def card_auth(self, auth_mode, block_address, key, uid):
        """
        Authenticates to use specified block address. Tag must be selected using select_tag(uid) before auth.
        auth_mode -- RFID.auth_a or RFID.auth_b
        key -- list or tuple with six bytes key
        uid -- list or tuple with four bytes tag ID
        Returns error state.
        """
        buf = []
        buf.append(auth_mode)
        buf.append(block_address)

        for i in range(len(key)):
            buf.append(key[i])

        for i in range(4):
            buf.append(uid[i])

        (error, back_data, back_length) = self.card_write(self.mode_auth, buf)
        if not (self.dev_read(0x08) & 0x08) != 0:
            error = True

        if not error:
            self.authed = True

        return error

    def stop_crypto(self):
        """Ends operations with Crypto1 usage."""
        self.clear_bitmask(0x08, 0x08)
        self.authed = False

    def read(self, block_address):
        """
        Reads data from block. You should be authenticated before calling read.
        Returns tuple of (error state, read data).
        """
        buf = []
        buf.append(self.act_read)
        buf.append(block_address)
        crc = self.calculate_crc(buf)
        buf.append(crc[0])
        buf.append(crc[1])
        (error, back_data, back_length) = self.card_write(self.mode_transrec, buf)

        if len(back_data) != 16:
            error = True

        return (error, back_data)

    def write(self, block_address, data):
        """
        Writes data to block. You should be authenticated before calling write.
        Returns error state.
        """
        buf = []
        buf.append(self.act_write)
        buf.append(block_address)
        crc = self.calculate_crc(buf)
        buf.append(crc[0])
        buf.append(crc[1])
        (error, back_data, back_length) = self.card_write(self.mode_transrec, buf)
        if not(back_length == 4) or not((back_data[0] & 0x0F) == 0x0A):
            error = True

        if not error:
            buf_w = []
            for i in range(16):
                buf_w.append(data[i])

            crc = self.calculate_crc(buf_w)
            buf_w.append(crc[0])
            buf_w.append(crc[1])
            (error, back_data, back_length) = self.card_write(self.mode_transrec, buf_w)
            if not(back_length == 4) or not((back_data[0] & 0x0F) == 0x0A):
                error = True

        return error

    def reset(self):
        self.dev_write(0x01, self.mode_reset)

    def cleanup(self):
        """
        Calls stop_crypto() if needed and cleanups GPIO.
        """
        if self.authed:
            self.stop_crypto()
        GPIO.cleanup()

    def util(self):
        """
        Creates and returns RFIDUtil object for this RFID instance.
        If module is not present, returns None.
        """
        try:
            import RFIDUtil
            return RFIDUtil.RFIDUtil(self)
        except ImportError:
            return None<|endoftext|>


<commit_before># Copyright 2011 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
#    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.

"""Unit tests for `nova.wsgi`."""

import os.path
import tempfile
import urllib2

import eventlet
import eventlet.wsgi
import mock
from oslo.config import cfg
import requests
import testtools
import webob

import nova.exception
from nova import test
from nova.tests.unit import utils
import nova.wsgi

SSL_CERT_DIR = os.path.normpath(os.path.join(
                                os.path.dirname(os.path.abspath(__file__)),
                                'ssl_cert'))
CONF = cfg.CONF

class TestLoaderNothingExists(test.NoDBTestCase):
    """Loader tests where os.path.exists always returns False."""

    def setUp(self):
        super(TestLoaderNothingExists, self).setUp()
        self.stubs.Set(os.path, 'exists', lambda _: False)

    def test_relpath_config_not_found(self):
        self.flags(api_paste_config='api-paste.ini')
        self.assertRaises(
            nova.exception.ConfigNotFound,
            nova.wsgi.Loader,
        )

    def test_asbpath_config_not_found(self):
        self.flags(api_paste_config='/etc/nova/api-paste.ini')
        self.assertRaises(
            nova.exception.ConfigNotFound,
            nova.wsgi.Loader,
        )

class TestLoaderNormalFilesystem(test.NoDBTestCase):
    """Loader tests with normal filesystem (unmodified os.path module)."""

    _paste_config = """
[app:test_app]
use = egg:Paste#static
document_root = /tmp
    """

    def setUp(self):
        super(TestLoaderNormalFilesystem, self).setUp()
        self.config = tempfile.NamedTemporaryFile(mode="w+t")
        self.config.write(self._paste_config.lstrip())
        self.config.seek(0)
        self.config.flush()
        self.loader = nova.wsgi.Loader(self.config.name)

    def test_config_found(self):
        self.assertEqual(self.config.name, self.loader.config_path)

    def test_app_not_found(self):
        self.assertRaises(
            nova.exception.PasteAppNotFound,
            self.loader.load_app,
            "nonexistent app",
        )

    def test_app_found(self):
        url_parser = self.loader.load_app("test_app")
        self.assertEqual("/tmp", url_parser.directory)

    def tearDown(self):
        self.config.close()
        super(TestLoaderNormalFilesystem, self).tearDown()

class TestWSGIServer(test.NoDBTestCase):
    """WSGI server tests."""

    def test_no_app(self):
        server = nova.wsgi.Server("test_app", None)
        self.assertEqual("test_app", server.name)

    def test_custom_max_header_line(self):
        self.flags(max_header_line=4096)  # Default value is 16384.
        nova.wsgi.Server("test_custom_max_header_line", None)
        self.assertEqual(CONF.max_header_line, eventlet.wsgi.MAX_HEADER_LINE)

    def test_start_random_port(self):
        server = nova.wsgi.Server("test_random_port", None,
                                  host="127.0.0.1", port=0)
        server.start()
        self.assertNotEqual(0, server.port)
        server.stop()
        server.wait()

    @testtools.skipIf(not utils.is_ipv6_supported(), "no ipv6 support")
    def test_start_random_port_with_ipv6(self):
        server = nova.wsgi.Server("test_random_port", None,
            host="::1", port=0)
        server.start()
        self.assertEqual("::1", server.host)
        self.assertNotEqual(0, server.port)
        server.stop()
        server.wait()

    def test_server_pool_waitall(self):
        # test pools waitall method gets called while stopping server
        server = nova.wsgi.Server("test_server", None,
            host="127.0.0.1", port=4444)
        server.start()
        with mock.patch.object(server._pool,
                              'waitall') as mock_waitall:
            server.stop()
            server.wait()
            mock_waitall.assert_called_once_with()

    def test_uri_length_limit(self):
        server = nova.wsgi.Server("test_uri_length_limit", None,
            host="127.0.0.1", max_url_len=16384)
        server.start()

        uri = "http://127.0.0.1:%d/%s" % (server.port, 10000 * 'x')
        resp = requests.get(uri, proxies={"http": ""})
        eventlet.sleep(0)
        self.assertNotEqual(resp.status_code,
                            requests.codes.REQUEST_URI_TOO_LARGE)

        uri = "http://127.0.0.1:%d/%s" % (server.port, 20000 * 'x')
        resp = requests.get(uri, proxies={"http": ""})
        eventlet.sleep(0)
        self.assertEqual(resp.status_code,
                         requests.codes.REQUEST_URI_TOO_LARGE)
        server.stop()
        server.wait()

    def test_reset_pool_size_to_default(self):
        server = nova.wsgi.Server("test_resize", None,
            host="127.0.0.1", max_url_len=16384)
        server.start()

        # Stopping the server, which in turn sets pool size to 0
        server.stop()
        self.assertEqual(server._pool.size, 0)

        # Resetting pool size to default
        server.reset()
        server.start()
        self.assertEqual(server._pool.size, CONF.wsgi_default_pool_size)

    def test_client_socket_timeout(self):
        self.flags(client_socket_timeout=5)

        # mocking eventlet spawn method to check it is called with
        # configured 'client_socket_timeout' value.
        with mock.patch.object(eventlet,
                               'spawn') as mock_spawn:
            server = nova.wsgi.Server("test_app", None,
                                      host="127.0.0.1", port=0)
            server.start()
            _, kwargs = mock_spawn.call_args
            self.assertEqual(CONF.client_socket_timeout,
                             kwargs['socket_timeout'])
            server.stop()

    def test_wsgi_keep_alive(self):
        self.flags(wsgi_keep_alive=False)

        # mocking eventlet spawn method to check it is called with
        # configured 'wsgi_keep_alive' value.
        with mock.patch.object(eventlet,
                               'spawn') as mock_spawn:
            server = nova.wsgi.Server("test_app", None,
                                      host="127.0.0.1", port=0)
            server.start()
            _, kwargs = mock_spawn.call_args
            self.assertEqual(CONF.wsgi_keep_alive,
                             kwargs['keepalive'])
            server.stop()

class TestWSGIServerWithSSL(test.NoDBTestCase):
    """WSGI server with SSL tests."""

    def setUp(self):
        super(TestWSGIServerWithSSL, self).setUp()
        self.flags(enabled_ssl_apis=['fake_ssl'],
                ssl_cert_file=os.path.join(SSL_CERT_DIR, 'certificate.crt'),
                ssl_key_file=os.path.join(SSL_CERT_DIR, 'privatekey.key'))

    def test_ssl_server(self):

        def test_app(env, start_response):
            start_response('200 OK', {})
            return ['PONG']

        fake_ssl_server = nova.wsgi.Server("fake_ssl", test_app,
                                           host="127.0.0.1", port=0,
                                           use_ssl=True)
        fake_ssl_server.start()
        self.assertNotEqual(0, fake_ssl_server.port)

        cli = eventlet.connect(("localhost", fake_ssl_server.port))
        cli = eventlet.wrap_ssl(cli,
                                ca_certs=os.path.join(SSL_CERT_DIR, 'ca.crt'))

        cli.write('POST / HTTP/1.1\r\nHost: localhost\r\n'
                  'Connection: close\r\nContent-length:4\r\n\r\nPING')
        response = cli.read(8192)
        self.assertEqual(response[-4:], "PONG")

        fake_ssl_server.stop()
        fake_ssl_server.wait()

    def test_two_servers(self):

        def test_app(env, start_response):
            start_response('200 OK', {})
            return ['PONG']

        fake_ssl_server = nova.wsgi.Server("fake_ssl", test_app,
            host="127.0.0.1", port=0, use_ssl=True)
        fake_ssl_server.start()
        self.assertNotEqual(0, fake_ssl_server.port)

        fake_server = nova.wsgi.Server("fake", test_app,
            host="127.0.0.1", port=0)
        fake_server.start()
        self.assertNotEqual(0, fake_server.port)

        cli = eventlet.connect(("localhost", fake_ssl_server.port))
        cli = eventlet.wrap_ssl(cli,
                                ca_certs=os.path.join(SSL_CERT_DIR, 'ca.crt'))

        cli.write('POST / HTTP/1.1\r\nHost: localhost\r\n'
                  'Connection: close\r\nContent-length:4\r\n\r\nPING')
        response = cli.read(8192)
        self.assertEqual(response[-4:], "PONG")

        cli = eventlet.connect(("localhost", fake_server.port))

        cli.sendall('POST / HTTP/1.1\r\nHost: localhost\r\n'
                  'Connection: close\r\nContent-length:4\r\n\r\nPING')
        response = cli.recv(8192)
        self.assertEqual(response[-4:], "PONG")

        fake_ssl_server.stop()
        fake_ssl_server.wait()

    @testtools.skipIf(not utils.is_ipv6_supported(), "no ipv6 support")
    def test_app_using_ipv6_and_ssl(self):
        greetings = 'Hello, World!!!'

        @webob.dec.wsgify
        def hello_world(req):
            return greetings

        server = nova.wsgi.Server("fake_ssl",
                                  hello_world,
                                  host="::1",
                                  port=0,
                                  use_ssl=True)

        server.start()

        response = urllib2.urlopen('https://[::1]:%d/' % server.port)
        self.assertEqual(greetings, response.read())

        server.stop()
        server.wait()
<commit_msg>Tests: Don't require binding to port 4444<commit_after># Copyright 2011 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
#    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.

"""Unit tests for `nova.wsgi`."""

import os.path
import tempfile
import urllib2

import eventlet
import eventlet.wsgi
import mock
from oslo.config import cfg
import requests
import testtools
import webob

import nova.exception
from nova import test
from nova.tests.unit import utils
import nova.wsgi

SSL_CERT_DIR = os.path.normpath(os.path.join(
                                os.path.dirname(os.path.abspath(__file__)),
                                'ssl_cert'))
CONF = cfg.CONF

class TestLoaderNothingExists(test.NoDBTestCase):
    """Loader tests where os.path.exists always returns False."""

    def setUp(self):
        super(TestLoaderNothingExists, self).setUp()
        self.stubs.Set(os.path, 'exists', lambda _: False)

    def test_relpath_config_not_found(self):
        self.flags(api_paste_config='api-paste.ini')
        self.assertRaises(
            nova.exception.ConfigNotFound,
            nova.wsgi.Loader,
        )

    def test_asbpath_config_not_found(self):
        self.flags(api_paste_config='/etc/nova/api-paste.ini')
        self.assertRaises(
            nova.exception.ConfigNotFound,
            nova.wsgi.Loader,
        )

class TestLoaderNormalFilesystem(test.NoDBTestCase):
    """Loader tests with normal filesystem (unmodified os.path module)."""

    _paste_config = """
[app:test_app]
use = egg:Paste#static
document_root = /tmp
    """

    def setUp(self):
        super(TestLoaderNormalFilesystem, self).setUp()
        self.config = tempfile.NamedTemporaryFile(mode="w+t")
        self.config.write(self._paste_config.lstrip())
        self.config.seek(0)
        self.config.flush()
        self.loader = nova.wsgi.Loader(self.config.name)

    def test_config_found(self):
        self.assertEqual(self.config.name, self.loader.config_path)

    def test_app_not_found(self):
        self.assertRaises(
            nova.exception.PasteAppNotFound,
            self.loader.load_app,
            "nonexistent app",
        )

    def test_app_found(self):
        url_parser = self.loader.load_app("test_app")
        self.assertEqual("/tmp", url_parser.directory)

    def tearDown(self):
        self.config.close()
        super(TestLoaderNormalFilesystem, self).tearDown()

class TestWSGIServer(test.NoDBTestCase):
    """WSGI server tests."""

    def test_no_app(self):
        server = nova.wsgi.Server("test_app", None)
        self.assertEqual("test_app", server.name)

    def test_custom_max_header_line(self):
        self.flags(max_header_line=4096)  # Default value is 16384.
        nova.wsgi.Server("test_custom_max_header_line", None)
        self.assertEqual(CONF.max_header_line, eventlet.wsgi.MAX_HEADER_LINE)

    def test_start_random_port(self):
        server = nova.wsgi.Server("test_random_port", None,
                                  host="127.0.0.1", port=0)
        server.start()
        self.assertNotEqual(0, server.port)
        server.stop()
        server.wait()

    @testtools.skipIf(not utils.is_ipv6_supported(), "no ipv6 support")
    def test_start_random_port_with_ipv6(self):
        server = nova.wsgi.Server("test_random_port", None,
            host="::1", port=0)
        server.start()
        self.assertEqual("::1", server.host)
        self.assertNotEqual(0, server.port)
        server.stop()
        server.wait()

    def test_server_pool_waitall(self):
        # test pools waitall method gets called while stopping server
        server = nova.wsgi.Server("test_server", None,
            host="127.0.0.1")
        server.start()
        with mock.patch.object(server._pool,
                              'waitall') as mock_waitall:
            server.stop()
            server.wait()
            mock_waitall.assert_called_once_with()

    def test_uri_length_limit(self):
        server = nova.wsgi.Server("test_uri_length_limit", None,
            host="127.0.0.1", max_url_len=16384)
        server.start()

        uri = "http://127.0.0.1:%d/%s" % (server.port, 10000 * 'x')
        resp = requests.get(uri, proxies={"http": ""})
        eventlet.sleep(0)
        self.assertNotEqual(resp.status_code,
                            requests.codes.REQUEST_URI_TOO_LARGE)

        uri = "http://127.0.0.1:%d/%s" % (server.port, 20000 * 'x')
        resp = requests.get(uri, proxies={"http": ""})
        eventlet.sleep(0)
        self.assertEqual(resp.status_code,
                         requests.codes.REQUEST_URI_TOO_LARGE)
        server.stop()
        server.wait()

    def test_reset_pool_size_to_default(self):
        server = nova.wsgi.Server("test_resize", None,
            host="127.0.0.1", max_url_len=16384)
        server.start()

        # Stopping the server, which in turn sets pool size to 0
        server.stop()
        self.assertEqual(server._pool.size, 0)

        # Resetting pool size to default
        server.reset()
        server.start()
        self.assertEqual(server._pool.size, CONF.wsgi_default_pool_size)

    def test_client_socket_timeout(self):
        self.flags(client_socket_timeout=5)

        # mocking eventlet spawn method to check it is called with
        # configured 'client_socket_timeout' value.
        with mock.patch.object(eventlet,
                               'spawn') as mock_spawn:
            server = nova.wsgi.Server("test_app", None,
                                      host="127.0.0.1", port=0)
            server.start()
            _, kwargs = mock_spawn.call_args
            self.assertEqual(CONF.client_socket_timeout,
                             kwargs['socket_timeout'])
            server.stop()

    def test_wsgi_keep_alive(self):
        self.flags(wsgi_keep_alive=False)

        # mocking eventlet spawn method to check it is called with
        # configured 'wsgi_keep_alive' value.
        with mock.patch.object(eventlet,
                               'spawn') as mock_spawn:
            server = nova.wsgi.Server("test_app", None,
                                      host="127.0.0.1", port=0)
            server.start()
            _, kwargs = mock_spawn.call_args
            self.assertEqual(CONF.wsgi_keep_alive,
                             kwargs['keepalive'])
            server.stop()

class TestWSGIServerWithSSL(test.NoDBTestCase):
    """WSGI server with SSL tests."""

    def setUp(self):
        super(TestWSGIServerWithSSL, self).setUp()
        self.flags(enabled_ssl_apis=['fake_ssl'],
                ssl_cert_file=os.path.join(SSL_CERT_DIR, 'certificate.crt'),
                ssl_key_file=os.path.join(SSL_CERT_DIR, 'privatekey.key'))

    def test_ssl_server(self):

        def test_app(env, start_response):
            start_response('200 OK', {})
            return ['PONG']

        fake_ssl_server = nova.wsgi.Server("fake_ssl", test_app,
                                           host="127.0.0.1", port=0,
                                           use_ssl=True)
        fake_ssl_server.start()
        self.assertNotEqual(0, fake_ssl_server.port)

        cli = eventlet.connect(("localhost", fake_ssl_server.port))
        cli = eventlet.wrap_ssl(cli,
                                ca_certs=os.path.join(SSL_CERT_DIR, 'ca.crt'))

        cli.write('POST / HTTP/1.1\r\nHost: localhost\r\n'
                  'Connection: close\r\nContent-length:4\r\n\r\nPING')
        response = cli.read(8192)
        self.assertEqual(response[-4:], "PONG")

        fake_ssl_server.stop()
        fake_ssl_server.wait()

    def test_two_servers(self):

        def test_app(env, start_response):
            start_response('200 OK', {})
            return ['PONG']

        fake_ssl_server = nova.wsgi.Server("fake_ssl", test_app,
            host="127.0.0.1", port=0, use_ssl=True)
        fake_ssl_server.start()
        self.assertNotEqual(0, fake_ssl_server.port)

        fake_server = nova.wsgi.Server("fake", test_app,
            host="127.0.0.1", port=0)
        fake_server.start()
        self.assertNotEqual(0, fake_server.port)

        cli = eventlet.connect(("localhost", fake_ssl_server.port))
        cli = eventlet.wrap_ssl(cli,
                                ca_certs=os.path.join(SSL_CERT_DIR, 'ca.crt'))

        cli.write('POST / HTTP/1.1\r\nHost: localhost\r\n'
                  'Connection: close\r\nContent-length:4\r\n\r\nPING')
        response = cli.read(8192)
        self.assertEqual(response[-4:], "PONG")

        cli = eventlet.connect(("localhost", fake_server.port))

        cli.sendall('POST / HTTP/1.1\r\nHost: localhost\r\n'
                  'Connection: close\r\nContent-length:4\r\n\r\nPING')
        response = cli.recv(8192)
        self.assertEqual(response[-4:], "PONG")

        fake_ssl_server.stop()
        fake_ssl_server.wait()

    @testtools.skipIf(not utils.is_ipv6_supported(), "no ipv6 support")
    def test_app_using_ipv6_and_ssl(self):
        greetings = 'Hello, World!!!'

        @webob.dec.wsgify
        def hello_world(req):
            return greetings

        server = nova.wsgi.Server("fake_ssl",
                                  hello_world,
                                  host="::1",
                                  port=0,
                                  use_ssl=True)

        server.start()

        response = urllib2.urlopen('https://[::1]:%d/' % server.port)
        self.assertEqual(greetings, response.read())

        server.stop()
        server.wait()
<|endoftext|>


<commit_before>"""
    Horizontal Split Panel: Left and Right layouts with a movable splitter.

/*
 * Copyright 2008 Google Inc.
 * Copyright 2009 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
 *
 * 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.
 */
"""

from __pyjamas__ import JS
from pyjamas import Factory
from splitpanel import SplitPanel
from pyjamas import DOM
from pyjamas import DeferredCommand

class ImplHorizontalSplitPanel:
    """ The standard implementation for horizontal split panels.
    """
    def __init__(self, panel):
        self.panel = panel

        DOM.setStyleAttribute(panel.getElement(), "position", "relative")

        self.expandToFitParentHorizontally(panel.getWidgetElement(0))
        self.expandToFitParentHorizontally(panel.getWidgetElement(1))
        self.expandToFitParentHorizontally(panel.getSplitElement())

        self.panel.expandToFitParentUsingCssOffsets(panel.container)

        # Right now, both panes are stacked on top of each other
        # on either the left side or the right side of the containing
        # panel. This happens because both panes have position:absolute
        # and no left/top values. The panes will be on the left side
        # if the directionality is LTR, and on the right side if the
        # directionality is RTL. In the LTR case, we need to snap the
        # right pane to the right of the container, and in the RTL case,
        # we need to snap the left pane to the left of the container.

        if True: # TODO: (LocaleInfo.getCurrentLocale().isRTL()):
            self.panel.setLeft(self.panel.getWidgetElement(0), "0px")
        else:
            self.panel.setRight(self.panel.getWidgetElement(1), "0px")

    def expandToFitParentHorizontally(self, elem):
      self.panel.addAbsolutePositoning(elem)
      zeroSize = "0px"
      self.panel.setTop(elem, zeroSize)
      self.panel.setBottom(elem, zeroSize)

    def onAttach(self):
        pass
    def onDetach(self):
        pass

    def onTimer(self, sender):
        pass
    def execute(self):
        pass
    def addResizeListener(self, container):
        pass
    def onResize(self):
        pass

    def onSplitterResize(self, px):
        self.setSplitPositionUsingPixels(px)

    def setSplitPosition(self, pos):
        leftElem = self.panel.getWidgetElement(0)
        self.panel.setElemWidth(leftElem, pos)
        self.setSplitPositionUsingPixels(self.panel.getOffsetWidth(leftElem))

    def setSplitPositionUsingPixels(self, px):
        self._setSplitPositionUsingPixels(px)

    def _setSplitPositionUsingPixels(self, px):
        """ Set the splitter's position in units of pixels.

              px represents the splitter's position as a distance
              of px pixels from the left edge of the container. This is
              true even in a bidi environment. Callers of this method
              must be aware of this constraint.
        """
        splitElem = self.panel.getSplitElement()

        rootElemWidth = self.panel.getOffsetWidth(self.panel.container)
        splitElemWidth = self.panel.getOffsetWidth(splitElem)

        # This represents an invalid state where layout is incomplete. This
        # typically happens before DOM attachment, but I leave it here as a
        # precaution because negative width/height style attributes produce
        # errors on IE.
        if (rootElemWidth < splitElemWidth):
            return

        # Compute the new right side width.
        newRightWidth = rootElemWidth - px - splitElemWidth

        # Constrain the dragging to the physical size of the panel.
        if (px < 0):
            px = 0
            newRightWidth = rootElemWidth - splitElemWidth
        elif (newRightWidth < 0):
            px = rootElemWidth - splitElemWidth
            newRightWidth = 0

        rightElem = self.panel.getWidgetElement(1)

        # Set the width of the left side.
        self.panel.setElemWidth(self.panel.getWidgetElement(0), "%dpx" % px)

        # Move the splitter to the right edge of the left element.
        self.panel.setLeft(splitElem, "%dpx" % px)

        # Move the right element to the right of the splitter.
        self.panel.setLeft(rightElem, "%dpx" % (px + splitElemWidth))

        self.updateRightWidth(rightElem, newRightWidth)

    def updateRightWidth(self, rightElem, newRightWidth):
        # No need to update the width of the right side this will be
        # recomputed automatically by CSS. This is helpful, as we do not
        # have to worry about watching for resize events and adjusting the
        # right-side width.
        pass

class HorizontalSplitPanel(SplitPanel):
    """  A panel that arranges two widgets in a single horizontal row
         and allows the user to interactively change the proportion
         of the width dedicated to each of the two widgets. Widgets
         contained within a HorizontalSplitPanel will
         be automatically decorated with scrollbars when necessary.

         Default layout behaviour of HorizontalSplitPanels is to 100% fill
         its parent vertically and horizontally [this is NOT normal!]
    """

    def __init__(self, **kwargs):
        """ Creates an empty horizontal split panel.
        """

        if not kwargs.has_key('StyleName'): kwargs['StyleName']="gwt-HorizontalSplitPanel"

        if kwargs.has_key('Element'):
            element = kwargs.pop('Element')
        else:
            element = DOM.createDiv()
        SplitPanel.__init__(self, element,
                            DOM.createDiv(),
                            self.preventBoxStyles(DOM.createDiv()),
                            self.preventBoxStyles(DOM.createDiv()),
                            **kwargs)

        self.container = self.preventBoxStyles(DOM.createDiv())

        self.buildDOM()

        self.impl = ImplHorizontalSplitPanel(self)

        # By default the panel will fill its parent vertically and horizontally.
        # The horizontal case is covered by the fact that the top level div is
        # block display.
        self.setHeight("100%")

        self.lastSplitPosition = "50%"
        self.initialLeftWidth = 0
        self.initialThumbPos = 0

    def add(self, w):
        """
           * Adds a widget to a pane in the HorizontalSplitPanel. The method
           * will first attempt to add the widget to the left pane. If a
           * widget is already in that position, it will attempt to add the
           * widget to the right pane. If a widget is already in that position,
           * an exception will be thrown, as a HorizontalSplitPanel can
           * contain at most two widgets.
           *
           * Note that this method is bidi-sensitive. In an RTL environment,
           * this method will first attempt to add the widget to the right pane,
           * and if a widget is already in that position, it will attempt to add
           * the widget to the left pane.
           *
           * @param w the widget to be added
           * @throws IllegalStateException
        """
        if self.getStartOfLineWidget() is None:
            self.setStartOfLineWidget(w)
        elif self.getEndOfLineWidget() is None:
            self.setEndOfLineWidget(w)
        else:
            return
          # TODO throw new IllegalStateException(
          #    "A Splitter can only contain two Widgets.")

    def getEndOfLineWidget(self):
        """
           * Gets the widget in the pane that is at the end of the line
           * direction for the layout. That is, in an RTL layout, gets
           * the widget in the left pane, and in an LTR layout, gets
           * the widget in the right pane.
           *
           * @return the widget, null if there is not one.
        """
        return self.getWidget(self.getEndOfLinePos())

    def getLeftWidget(self):
        """
           * Gets the widget in the left side of the panel.
           *
           * @return the widget, null if there is not one.
        """
        return self.getWidget(0)

    def getRightWidget(self):
        """
           * Gets the widget in the right side of the panel.
           *
           * @return the widget, null if there is not one.
        """
        return self.getWidget(1)

    def getStartOfLineWidget(self):
        """
        * Gets the widget in the pane that is at the start of the line
        * direction for the layout. That is, in an RTL environment, gets
        * the widget in the right pane, and in an LTR environment, gets
        * the widget in the left pane.
        *
        * @return the widget, null if there is not one.
        """
        return self.getWidget(self.getStartOfLinePos())

    def setEndOfLineWidget(self, w):
        """
       * Sets the widget in the pane that is at the end of the line direction
       * for the layout. That is, in an RTL layout, sets the widget in
       * the left pane, and in and RTL layout, sets the widget in the
       * right pane.
       *
       * @param w the widget
        """
        self.setWidget(self.getEndOfLinePos(), w)

    def setLeftWidget(self, w):
        """
           * Sets the widget in the left side of the panel.
           *
           * @param w the widget
        """
        self.setWidget(0, w)

    def setRightWidget(self, w):
        """
           * Sets the widget in the right side of the panel.
           *
           * @param w the widget
        """
        self.setWidget(1, w)

    def setSplitPosition(self, pos):
        """
       * Moves the position of the splitter.
       *
       * This method is not bidi-sensitive. The size specified is always
       * the size of the left region, regardless of directionality.
       *
       * @param pos the new size of the left region in CSS units (e.g. "10px",
       *             "1em")
        """
        self.lastSplitPosition = pos
        self.impl.setSplitPosition(pos)

    def setStartOfLineWidget(self, w):
        """
       * Sets the widget in the pane that is at the start of the line direction
       * for the layout. That is, in an RTL layout, sets the widget in
       * the right pane, and in and RTL layout, sets the widget in the
       * left pane.
       *
       * @param w the widget
        """
        self.setWidget(self.getStartOfLinePos(), w)

    def onLoad(self):
        self.impl.onAttach()
        # Set the position realizing it might not work until
        # after layout runs.  This first call is simply to try
        # to avoid a jitter effect if possible.
        self.setSplitPosition(self.lastSplitPosition)
        DeferredCommand.add(self)

    def execute(self):
        self.setSplitPosition(self.lastSplitPosition)

    def onUnload(self):
        self.impl.onDetach()

    def onSplitterResize(self, x, y):
        self.impl.onSplitterResize(self.initialLeftWidth + x -
                                   self.initialThumbPos)

    def onSplitterResizeStarted(self, x, y):
        self.initialThumbPos = x
        self.initialLeftWidth = self.getOffsetWidth(self.getWidgetElement(0))

    def buildDOM(self):

        leftDiv = self.getWidgetElement(0)
        rightDiv = self.getWidgetElement(1)
        splitDiv = self.getSplitElement()

        DOM.appendChild(self.getElement(), self.container)

        DOM.appendChild(self.container, leftDiv)
        DOM.appendChild(self.container, splitDiv)
        DOM.appendChild(self.container, rightDiv)

        # Sadly, this is the only way I've found to get vertical
        # centering in this case. The usually CSS hacks (display:
        # table-cell, vertical-align: middle) don't work in an
        # absolute positioned DIV.
        DOM.setInnerHTML(splitDiv,
            "

" +
                self.getThumbImageHTML() +
                "

")

        self.addScrolling(leftDiv)
        self.addScrolling(rightDiv)

    def getEndOfLinePos(self):
        return 0
        # TODO: return (LocaleInfo.getCurrentLocale().isRTL() ? 0 : 1)

    def getStartOfLinePos(self):
        return 1
        # TODO: return (LocaleInfo.getCurrentLocale().isRTL() ? 1 : 0)

Factory.registerClass('pyjamas.ui.HorizontalSplitPanel', HorizontalSplitPanel)

<commit_msg> #333 fix HorizontalSplitPanel.onSplitterResize()<commit_after>"""
    Horizontal Split Panel: Left and Right layouts with a movable splitter.

/*
 * Copyright 2008 Google Inc.
 * Copyright 2009 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
 *
 * 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.
 */
"""

from __pyjamas__ import JS
from pyjamas import Factory
from splitpanel import SplitPanel
from pyjamas import DOM
from pyjamas import DeferredCommand

class ImplHorizontalSplitPanel:
    """ The standard implementation for horizontal split panels.
    """
    def __init__(self, panel):
        self.panel = panel

        DOM.setStyleAttribute(panel.getElement(), "position", "relative")

        self.expandToFitParentHorizontally(panel.getWidgetElement(0))
        self.expandToFitParentHorizontally(panel.getWidgetElement(1))
        self.expandToFitParentHorizontally(panel.getSplitElement())

        self.panel.expandToFitParentUsingCssOffsets(panel.container)

        # Right now, both panes are stacked on top of each other
        # on either the left side or the right side of the containing
        # panel. This happens because both panes have position:absolute
        # and no left/top values. The panes will be on the left side
        # if the directionality is LTR, and on the right side if the
        # directionality is RTL. In the LTR case, we need to snap the
        # right pane to the right of the container, and in the RTL case,
        # we need to snap the left pane to the left of the container.

        if True: # TODO: (LocaleInfo.getCurrentLocale().isRTL()):
            self.panel.setLeft(self.panel.getWidgetElement(0), "0px")
        else:
            self.panel.setRight(self.panel.getWidgetElement(1), "0px")

    def expandToFitParentHorizontally(self, elem):
      self.panel.addAbsolutePositoning(elem)
      zeroSize = "0px"
      self.panel.setTop(elem, zeroSize)
      self.panel.setBottom(elem, zeroSize)

    def onAttach(self):
        pass
    def onDetach(self):
        pass

    def onTimer(self, sender):
        pass
    def execute(self):
        pass
    def addResizeListener(self, container):
        pass
    def onResize(self):
        pass

    def onSplitterResize(self, px):
        self.setSplitPositionUsingPixels(px)

    def setSplitPosition(self, pos):
        leftElem = self.panel.getWidgetElement(0)
        self.panel.setElemWidth(leftElem, pos)
        self.setSplitPositionUsingPixels(self.panel.getOffsetWidth(leftElem))

    def setSplitPositionUsingPixels(self, px):
        self._setSplitPositionUsingPixels(px)

    def _setSplitPositionUsingPixels(self, px):
        """ Set the splitter's position in units of pixels.

              px represents the splitter's position as a distance
              of px pixels from the left edge of the container. This is
              true even in a bidi environment. Callers of this method
              must be aware of this constraint.
        """
        splitElem = self.panel.getSplitElement()

        rootElemWidth = self.panel.getOffsetWidth(self.panel.container)
        splitElemWidth = self.panel.getOffsetWidth(splitElem)

        # This represents an invalid state where layout is incomplete. This
        # typically happens before DOM attachment, but I leave it here as a
        # precaution because negative width/height style attributes produce
        # errors on IE.
        if (rootElemWidth < splitElemWidth):
            return

        # Compute the new right side width.
        newRightWidth = rootElemWidth - px - splitElemWidth

        # Constrain the dragging to the physical size of the panel.
        if (px < 0):
            px = 0
            newRightWidth = rootElemWidth - splitElemWidth
        elif (newRightWidth < 0):
            px = rootElemWidth - splitElemWidth
            newRightWidth = 0

        rightElem = self.panel.getWidgetElement(1)

        # Set the width of the left side.
        self.panel.setElemWidth(self.panel.getWidgetElement(0), "%dpx" % px)

        # Move the splitter to the right edge of the left element.
        self.panel.setLeft(splitElem, "%dpx" % px)

        # Move the right element to the right of the splitter.
        self.panel.setLeft(rightElem, "%dpx" % (px + splitElemWidth))

        self.updateRightWidth(rightElem, newRightWidth)

    def updateRightWidth(self, rightElem, newRightWidth):
        # No need to update the width of the right side this will be
        # recomputed automatically by CSS. This is helpful, as we do not
        # have to worry about watching for resize events and adjusting the
        # right-side width.
        pass

class HorizontalSplitPanel(SplitPanel):
    """  A panel that arranges two widgets in a single horizontal row
         and allows the user to interactively change the proportion
         of the width dedicated to each of the two widgets. Widgets
         contained within a HorizontalSplitPanel will
         be automatically decorated with scrollbars when necessary.

         Default layout behaviour of HorizontalSplitPanels is to 100% fill
         its parent vertically and horizontally [this is NOT normal!]
    """

    def __init__(self, **kwargs):
        """ Creates an empty horizontal split panel.
        """

        if not kwargs.has_key('StyleName'): kwargs['StyleName']="gwt-HorizontalSplitPanel"

        if kwargs.has_key('Element'):
            element = kwargs.pop('Element')
        else:
            element = DOM.createDiv()
        SplitPanel.__init__(self, element,
                            DOM.createDiv(),
                            self.preventBoxStyles(DOM.createDiv()),
                            self.preventBoxStyles(DOM.createDiv()),
                            **kwargs)

        self.container = self.preventBoxStyles(DOM.createDiv())

        self.buildDOM()

        self.impl = ImplHorizontalSplitPanel(self)

        # By default the panel will fill its parent vertically and horizontally.
        # The horizontal case is covered by the fact that the top level div is
        # block display.
        self.setHeight("100%")

        self.lastSplitPosition = "50%"
        self.initialLeftWidth = 0
        self.initialThumbPos = 0

    def add(self, w):
        """
           * Adds a widget to a pane in the HorizontalSplitPanel. The method
           * will first attempt to add the widget to the left pane. If a
           * widget is already in that position, it will attempt to add the
           * widget to the right pane. If a widget is already in that position,
           * an exception will be thrown, as a HorizontalSplitPanel can
           * contain at most two widgets.
           *
           * Note that this method is bidi-sensitive. In an RTL environment,
           * this method will first attempt to add the widget to the right pane,
           * and if a widget is already in that position, it will attempt to add
           * the widget to the left pane.
           *
           * @param w the widget to be added
           * @throws IllegalStateException
        """
        if self.getStartOfLineWidget() is None:
            self.setStartOfLineWidget(w)
        elif self.getEndOfLineWidget() is None:
            self.setEndOfLineWidget(w)
        else:
            return
          # TODO throw new IllegalStateException(
          #    "A Splitter can only contain two Widgets.")

    def getEndOfLineWidget(self):
        """
           * Gets the widget in the pane that is at the end of the line
           * direction for the layout. That is, in an RTL layout, gets
           * the widget in the left pane, and in an LTR layout, gets
           * the widget in the right pane.
           *
           * @return the widget, null if there is not one.
        """
        return self.getWidget(self.getEndOfLinePos())

    def getLeftWidget(self):
        """
           * Gets the widget in the left side of the panel.
           *
           * @return the widget, null if there is not one.
        """
        return self.getWidget(0)

    def getRightWidget(self):
        """
           * Gets the widget in the right side of the panel.
           *
           * @return the widget, null if there is not one.
        """
        return self.getWidget(1)

    def getStartOfLineWidget(self):
        """
        * Gets the widget in the pane that is at the start of the line
        * direction for the layout. That is, in an RTL environment, gets
        * the widget in the right pane, and in an LTR environment, gets
        * the widget in the left pane.
        *
        * @return the widget, null if there is not one.
        """
        return self.getWidget(self.getStartOfLinePos())

    def setEndOfLineWidget(self, w):
        """
       * Sets the widget in the pane that is at the end of the line direction
       * for the layout. That is, in an RTL layout, sets the widget in
       * the left pane, and in and RTL layout, sets the widget in the
       * right pane.
       *
       * @param w the widget
        """
        self.setWidget(self.getEndOfLinePos(), w)

    def setLeftWidget(self, w):
        """
           * Sets the widget in the left side of the panel.
           *
           * @param w the widget
        """
        self.setWidget(0, w)

    def setRightWidget(self, w):
        """
           * Sets the widget in the right side of the panel.
           *
           * @param w the widget
        """
        self.setWidget(1, w)

    def setSplitPosition(self, pos):
        """
       * Moves the position of the splitter.
       *
       * This method is not bidi-sensitive. The size specified is always
       * the size of the left region, regardless of directionality.
       *
       * @param pos the new size of the left region in CSS units (e.g. "10px",
       *             "1em")
        """
        self.lastSplitPosition = pos
        self.impl.setSplitPosition(pos)

    def setStartOfLineWidget(self, w):
        """
       * Sets the widget in the pane that is at the start of the line direction
       * for the layout. That is, in an RTL layout, sets the widget in
       * the right pane, and in and RTL layout, sets the widget in the
       * left pane.
       *
       * @param w the widget
        """
        self.setWidget(self.getStartOfLinePos(), w)

    def onLoad(self):
        self.impl.onAttach()
        # Set the position realizing it might not work until
        # after layout runs.  This first call is simply to try
        # to avoid a jitter effect if possible.
        self.setSplitPosition(self.lastSplitPosition)
        DeferredCommand.add(self)

    def execute(self):
        self.setSplitPosition(self.lastSplitPosition)

    def onUnload(self):
        self.impl.onDetach()

    def onSplitterResize(self, x, y):
        self.lastSplitPosition = x
        self.impl.onSplitterResize(self.initialLeftWidth + x -
                                   self.initialThumbPos)

    def onSplitterResizeStarted(self, x, y):
        self.initialThumbPos = x
        self.initialLeftWidth = self.getOffsetWidth(self.getWidgetElement(0))

    def buildDOM(self):

        leftDiv = self.getWidgetElement(0)
        rightDiv = self.getWidgetElement(1)
        splitDiv = self.getSplitElement()

        DOM.appendChild(self.getElement(), self.container)

        DOM.appendChild(self.container, leftDiv)
        DOM.appendChild(self.container, splitDiv)
        DOM.appendChild(self.container, rightDiv)

        # Sadly, this is the only way I've found to get vertical
        # centering in this case. The usually CSS hacks (display:
        # table-cell, vertical-align: middle) don't work in an
        # absolute positioned DIV.
        DOM.setInnerHTML(splitDiv,
            "

" +
                self.getThumbImageHTML() +
                "

")

        self.addScrolling(leftDiv)
        self.addScrolling(rightDiv)

    def getEndOfLinePos(self):
        return 0
        # TODO: return (LocaleInfo.getCurrentLocale().isRTL() ? 0 : 1)

    def getStartOfLinePos(self):
        return 1
        # TODO: return (LocaleInfo.getCurrentLocale().isRTL() ? 1 : 0)

Factory.registerClass('pyjamas.ui.HorizontalSplitPanel', HorizontalSplitPanel)

<|endoftext|>


<commit_before># Copyright (C) 2019 The Android Open Source Project
#
# 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.

load("@perfetto_cfg//:perfetto_cfg.bzl", "PERFETTO_CONFIG")
load("@perfetto//bazel:proto_gen.bzl", "proto_gen")

# +----------------------------------------------------------------------------+
# | Base C++ rules.                                                            |
# +----------------------------------------------------------------------------+

def default_cc_args():
    return {
        "deps": PERFETTO_CONFIG.deps.build_config,
        "copts": [],
        "includes": ["include"],
        "linkopts": select({
            "@perfetto//bazel:os_linux": ["-ldl", "-lrt", "-lpthread"],
            "@perfetto//bazel:os_osx": [],
            "@perfetto//bazel:os_windows": [],
            "//conditions:default": ["-ldl"],
        }),
    }

def perfetto_cc_library(**kwargs):
    args = _merge_dicts(default_cc_args(), kwargs)
    if not _rule_override("cc_library", **args):
        native.cc_library(**args)

def perfetto_cc_binary(**kwargs):
    args = _merge_dicts(default_cc_args(), kwargs)
    if not _rule_override("cc_binary", **args):
        native.cc_binary(**args)

def perfetto_py_binary(**kwargs):
    if not _rule_override("py_binary", **kwargs):
        native.py_binary(**kwargs)

# +----------------------------------------------------------------------------+
# | Proto-related rules                                                        |
# +----------------------------------------------------------------------------+

def perfetto_proto_library(**kwargs):
    if not _rule_override("proto_library", **kwargs):
        native.proto_library(**kwargs)

def perfetto_cc_proto_library(**kwargs):
    if not _rule_override("cc_proto_library", **kwargs):
        native.cc_proto_library(**kwargs)

def perfetto_java_proto_library(**kwargs):
    if not _rule_override("java_proto_library", **kwargs):
        native.java_proto_library(**kwargs)

# +----------------------------------------------------------------------------+
# | Misc rules.                                                                |
# +----------------------------------------------------------------------------+

# Unlike all the other rules, this is an noop by default because Bazel does not
# support gensignature.
def perfetto_gensignature_internal_only(**kwargs):
    _rule_override("gensignature_internal_only", **kwargs)

# Generates .pbzero.{cc,h} from .proto(s). We deliberately do NOT generate
# conventional .pb.{cc,h} from here as protozero gen sources do not have any
# dependency on libprotobuf.
def perfetto_cc_protozero_library(name, deps, **kwargs):
    if _rule_override(
        "cc_protozero_library",
        name = name,
        deps = deps,
        **kwargs
    ):
        return

    proto_gen(
        name = name + "_src",
        deps = deps,
        suffix = "pbzero",
        plugin = PERFETTO_CONFIG.root + ":protozero_plugin",
        wrapper_namespace = "pbzero",
        protoc = PERFETTO_CONFIG.deps.protoc[0],
        root = PERFETTO_CONFIG.root,
    )

    native.filegroup(
        name = name + "_h",
        srcs = [":" + name + "_src"],
        output_group = "h",
    )

    perfetto_cc_library(
        name = name,
        srcs = [":" + name + "_src"],
        hdrs = [":" + name + "_h"],
        deps = [PERFETTO_CONFIG.root + ":libprotozero"],
        **kwargs
    )

# Generates .ipc.{cc,h} and .pb.{cc.h} from .proto(s). The IPC sources depend
# on .pb.h so we need to generate also the standard protobuf sources here.
def perfetto_cc_ipc_library(name, deps, **kwargs):
    if _rule_override("cc_ipc_library", name = name, deps = deps, **kwargs):
        return

    # A perfetto_cc_ipc_library has two types of dependencies:
    # 1. Exactly one dependency on a proto_library target. This defines the
    #    .proto sources for the target
    # 2. Zero or more deps on other perfetto_cc_protocpp_library targets. This
    #    to deal with the case of foo.proto including common.proto from another
    #    target.
    _proto_deps = [d for d in deps if d.endswith("_protos")]
    _cc_deps = [d for d in deps if d not in _proto_deps]
    if len(_proto_deps) != 1:
        fail("Too many proto deps for target %s" % name)

    # Generates .ipc.{cc,h}.
    proto_gen(
        name = name + "_src",
        deps = _proto_deps,
        suffix = "ipc",
        plugin = PERFETTO_CONFIG.root + ":ipc_plugin",
        wrapper_namespace = "gen",
        protoc = PERFETTO_CONFIG.deps.protoc[0],
        root = PERFETTO_CONFIG.root,
    )

    native.filegroup(
        name = name + "_h",
        srcs = [":" + name + "_src"],
        output_group = "h",
    )

    perfetto_cc_library(
        name = name,
        srcs = [":" + name + "_src"],
        hdrs = [":" + name + "_h"],
        deps = [
            # Generated .ipc.{cc,h} depend on this and protozero.
            PERFETTO_CONFIG.root + ":perfetto_ipc",
            PERFETTO_CONFIG.root + ":libprotozero",
        ] + _cc_deps,
        **kwargs
    )

# Generates .gen.{cc,h} from .proto(s).
def perfetto_cc_protocpp_library(name, deps, **kwargs):
    if _rule_override(
        "cc_protocpp_library",
        name = name,
        deps = deps,
        **kwargs
    ):
        return

    # A perfetto_cc_protocpp_library has two types of dependencies:
    # 1. Exactly one dependency on a proto_library target. This defines the
    #    .proto sources for the target
    # 2. Zero or more deps on other perfetto_cc_protocpp_library targets. This
    #    to deal with the case of foo.proto including common.proto from another
    #    target.
    _proto_deps = [d for d in deps if d.endswith("_protos")]
    _cc_deps = [d for d in deps if d not in _proto_deps]
    if len(_proto_deps) != 1:
        fail("Too many proto deps for target %s" % name)

    proto_gen(
        name = name + "_gen",
        deps = _proto_deps,
        suffix = "gen",
        plugin = PERFETTO_CONFIG.root + ":cppgen_plugin",
        wrapper_namespace = "gen",
        protoc = PERFETTO_CONFIG.deps.protoc[0],
        root = PERFETTO_CONFIG.root,
    )

    native.filegroup(
        name = name + "_gen_h",
        srcs = [":" + name + "_gen"],
        output_group = "h",
    )

    perfetto_cc_library(
        name = name,
        srcs = [":" + name + "_gen"],
        hdrs = [":" + name + "_gen_h"],
        deps = [
            PERFETTO_CONFIG.root + ":libprotozero"
        ] + _cc_deps,
        **kwargs
    )

# +----------------------------------------------------------------------------+
# | Misc utility functions                                                     |
# +----------------------------------------------------------------------------+

def _rule_override(rule_name, **kwargs):
    overrides = getattr(PERFETTO_CONFIG, "rule_overrides", struct())
    overridden_rule = getattr(overrides, rule_name, None)
    if overridden_rule:
        overridden_rule(**kwargs)
        return True
    return False

def _merge_dicts(*args):
    res = {}
    for arg in args:
        for k, v in arg.items():
            if type(v) == "string" or type(v) == "bool":
                res[k] = v
            elif type(v) == "list" or type(v) == "select":
                res[k] = res.get(k, []) + v
            else:
                fail("key type not supported: " + type(v))
    return res
<commit_msg>bazel: Disable warning about unused system_header pragma<commit_after># Copyright (C) 2019 The Android Open Source Project
#
# 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.

load("@perfetto_cfg//:perfetto_cfg.bzl", "PERFETTO_CONFIG")
load("@perfetto//bazel:proto_gen.bzl", "proto_gen")

# +----------------------------------------------------------------------------+
# | Base C++ rules.                                                            |
# +----------------------------------------------------------------------------+

def default_cc_args():
    return {
        "deps": PERFETTO_CONFIG.deps.build_config,
        "copts": [
            "-Wno-pragma-system-header-outside-header",
        ],
        "includes": ["include"],
        "linkopts": select({
            "@perfetto//bazel:os_linux": ["-ldl", "-lrt", "-lpthread"],
            "@perfetto//bazel:os_osx": [],
            "@perfetto//bazel:os_windows": [],
            "//conditions:default": ["-ldl"],
        }),
    }

def perfetto_cc_library(**kwargs):
    args = _merge_dicts(default_cc_args(), kwargs)
    if not _rule_override("cc_library", **args):
        native.cc_library(**args)

def perfetto_cc_binary(**kwargs):
    args = _merge_dicts(default_cc_args(), kwargs)
    if not _rule_override("cc_binary", **args):
        native.cc_binary(**args)

def perfetto_py_binary(**kwargs):
    if not _rule_override("py_binary", **kwargs):
        native.py_binary(**kwargs)

# +----------------------------------------------------------------------------+
# | Proto-related rules                                                        |
# +----------------------------------------------------------------------------+

def perfetto_proto_library(**kwargs):
    if not _rule_override("proto_library", **kwargs):
        native.proto_library(**kwargs)

def perfetto_cc_proto_library(**kwargs):
    if not _rule_override("cc_proto_library", **kwargs):
        native.cc_proto_library(**kwargs)

def perfetto_java_proto_library(**kwargs):
    if not _rule_override("java_proto_library", **kwargs):
        native.java_proto_library(**kwargs)

# +----------------------------------------------------------------------------+
# | Misc rules.                                                                |
# +----------------------------------------------------------------------------+

# Unlike all the other rules, this is an noop by default because Bazel does not
# support gensignature.
def perfetto_gensignature_internal_only(**kwargs):
    _rule_override("gensignature_internal_only", **kwargs)

# Generates .pbzero.{cc,h} from .proto(s). We deliberately do NOT generate
# conventional .pb.{cc,h} from here as protozero gen sources do not have any
# dependency on libprotobuf.
def perfetto_cc_protozero_library(name, deps, **kwargs):
    if _rule_override(
        "cc_protozero_library",
        name = name,
        deps = deps,
        **kwargs
    ):
        return

    proto_gen(
        name = name + "_src",
        deps = deps,
        suffix = "pbzero",
        plugin = PERFETTO_CONFIG.root + ":protozero_plugin",
        wrapper_namespace = "pbzero",
        protoc = PERFETTO_CONFIG.deps.protoc[0],
        root = PERFETTO_CONFIG.root,
    )

    native.filegroup(
        name = name + "_h",
        srcs = [":" + name + "_src"],
        output_group = "h",
    )

    perfetto_cc_library(
        name = name,
        srcs = [":" + name + "_src"],
        hdrs = [":" + name + "_h"],
        deps = [PERFETTO_CONFIG.root + ":libprotozero"],
        **kwargs
    )

# Generates .ipc.{cc,h} and .pb.{cc.h} from .proto(s). The IPC sources depend
# on .pb.h so we need to generate also the standard protobuf sources here.
def perfetto_cc_ipc_library(name, deps, **kwargs):
    if _rule_override("cc_ipc_library", name = name, deps = deps, **kwargs):
        return

    # A perfetto_cc_ipc_library has two types of dependencies:
    # 1. Exactly one dependency on a proto_library target. This defines the
    #    .proto sources for the target
    # 2. Zero or more deps on other perfetto_cc_protocpp_library targets. This
    #    to deal with the case of foo.proto including common.proto from another
    #    target.
    _proto_deps = [d for d in deps if d.endswith("_protos")]
    _cc_deps = [d for d in deps if d not in _proto_deps]
    if len(_proto_deps) != 1:
        fail("Too many proto deps for target %s" % name)

    # Generates .ipc.{cc,h}.
    proto_gen(
        name = name + "_src",
        deps = _proto_deps,
        suffix = "ipc",
        plugin = PERFETTO_CONFIG.root + ":ipc_plugin",
        wrapper_namespace = "gen",
        protoc = PERFETTO_CONFIG.deps.protoc[0],
        root = PERFETTO_CONFIG.root,
    )

    native.filegroup(
        name = name + "_h",
        srcs = [":" + name + "_src"],
        output_group = "h",
    )

    perfetto_cc_library(
        name = name,
        srcs = [":" + name + "_src"],
        hdrs = [":" + name + "_h"],
        deps = [
            # Generated .ipc.{cc,h} depend on this and protozero.
            PERFETTO_CONFIG.root + ":perfetto_ipc",
            PERFETTO_CONFIG.root + ":libprotozero",
        ] + _cc_deps,
        **kwargs
    )

# Generates .gen.{cc,h} from .proto(s).
def perfetto_cc_protocpp_library(name, deps, **kwargs):
    if _rule_override(
        "cc_protocpp_library",
        name = name,
        deps = deps,
        **kwargs
    ):
        return

    # A perfetto_cc_protocpp_library has two types of dependencies:
    # 1. Exactly one dependency on a proto_library target. This defines the
    #    .proto sources for the target
    # 2. Zero or more deps on other perfetto_cc_protocpp_library targets. This
    #    to deal with the case of foo.proto including common.proto from another
    #    target.
    _proto_deps = [d for d in deps if d.endswith("_protos")]
    _cc_deps = [d for d in deps if d not in _proto_deps]
    if len(_proto_deps) != 1:
        fail("Too many proto deps for target %s" % name)

    proto_gen(
        name = name + "_gen",
        deps = _proto_deps,
        suffix = "gen",
        plugin = PERFETTO_CONFIG.root + ":cppgen_plugin",
        wrapper_namespace = "gen",
        protoc = PERFETTO_CONFIG.deps.protoc[0],
        root = PERFETTO_CONFIG.root,
    )

    native.filegroup(
        name = name + "_gen_h",
        srcs = [":" + name + "_gen"],
        output_group = "h",
    )

    perfetto_cc_library(
        name = name,
        srcs = [":" + name + "_gen"],
        hdrs = [":" + name + "_gen_h"],
        deps = [
            PERFETTO_CONFIG.root + ":libprotozero"
        ] + _cc_deps,
        **kwargs
    )

# +----------------------------------------------------------------------------+
# | Misc utility functions                                                     |
# +----------------------------------------------------------------------------+

def _rule_override(rule_name, **kwargs):
    overrides = getattr(PERFETTO_CONFIG, "rule_overrides", struct())
    overridden_rule = getattr(overrides, rule_name, None)
    if overridden_rule:
        overridden_rule(**kwargs)
        return True
    return False

def _merge_dicts(*args):
    res = {}
    for arg in args:
        for k, v in arg.items():
            if type(v) == "string" or type(v) == "bool":
                res[k] = v
            elif type(v) == "list" or type(v) == "select":
                res[k] = res.get(k, []) + v
            else:
                fail("key type not supported: " + type(v))
    return res
<|endoftext|>


<commit_before>#!/usr/bin/python
# -*- coding: utf-8 -*-

'''
Calculate photons and radiation dose per second
'''

from pylab import *
import numpy as np
import os

# Setup parameters
FOV = 10  # cm. Approximation of a wrist (10 * 10 * 5cm)
Area = FOV ** 2  # cm²
Thickness = 5  # cm
Volume = Area * Thickness
Density = 1.02  # g/cm³
Weight = float(Volume) * Density / 1000  # kg

# @40kV, half bone, half muscle
AttenuationCoefficient = []
AttenuationCoefficient.append(np.mean((2.685e-1, 6.655-1)))
# @70kV (0.5*60+0.5*80), both half bone, half muscle
AttenuationCoefficient.append(np.mean((np.mean((2.048e-01,3.148e-01)),
                                       np.mean((1.823e-01,2.229e-01)))))

'''
Skeletal muscle (http://is.gd/D88OFv)
    Energy         μ/ρ       μen/ρ
    (MeV)       (cm2/g)    (cm2/g)
    1.00000E-02  5.356E+00  4.964E+00
    1.50000E-02  1.693E+00  1.396E+00
    2.00000E-02  8.205E-01  5.638E-01
    3.00000E-02  3.783E-01  1.610E-01
    4.00000E-02  *2.685E-01*  7.192E-02
    5.00000E-02  2.262E-01  4.349E-02
    6.00000E-02  *2.048E-01*  3.258E-02
    8.00000E-02  *1.823E-01*  2.615E-02
Cortical bone (http://is.gd/2176eQ)
    Energy         μ/ρ       μen/ρ
    (MeV)       (cm2/g)    (cm2/g)
    1.00000E-02  2.851E+01  2.680E+01
    1.50000E-02  9.032E+00  8.388E+00
    2.00000E-02  4.001E+00  3.601E+00
    3.00000E-02  1.331E+00  1.070E+00
    4.00000E-02  *6.655E-01*  4.507E-01
    5.00000E-02  4.242E-01  2.336E-01
    6.00000E-02  *3.148E-01* 1.400E-01
    8.00000E-02  *2.229E-01*  6.896E-02
'''

r = 140  # cm, Distance from source to sample
eta = 1e-9  # *ZV
Z = 74  # Tungsten
eV = 1.602e-19  # J

QFactor = 1  # http://en.wikipedia.org/wiki/Dosimetry#Equivalent_Dose
WeightingFactor = 0.12  # http://en.wikipedia.org/wiki/Dosimetry#Effective_dose
ExposureTime = 100e-3  # s

# Read xray spectra
Spectrapath = '/afs/psi.ch/project/EssentialMed/Dev/Spectra'
Spectra = [(os.path.join(Spectrapath, 'Xray-Spectrum_046kV.txt')),
           (os.path.join(Spectrapath, 'Xray-Spectrum_070kV.txt'))]

Data = [(np.loadtxt(FileName)) for FileName in Spectra]
SourceVoltage = [int(open(FileName).readlines()[3].split()[7])
                 for FileName in Spectra]
AverageEnergy = [float(open(FileName).readlines()[6].split()[3])
                 for FileName in Spectra]

# Give out values
for Voltage, Current, case in zip((SourceVoltage[0], SourceVoltage[1]),
                                  (50, 50), range(len(Spectra))):
    print 80 * '-'
    print 'For a voltage of', Voltage, 'kV and a current of', Current, 'mAs'
    print '    - we have a mean energy of', round(AverageEnergy[case],4), 'keV'

    # Calculate the number of photons from the tube to the sample
    #~ N0 = (VI/E)*eta*(A/4Pir²)
    N0 = (Voltage * Current) / (Voltage * eV) * \
        eta * Z * Voltage * \
        Area / (4 * np.pi * r ** 2)

    print '    - the tube emitts %.4e' % N0, 'photons per second'

    # Number of absorbed photons
    #~ N = N0(1-e^-uT)
    N = N0 * (1 - math.e ** (-AttenuationCoefficient[case] * Thickness))

    print '    - %.4e' % N, 'photons/s are absorbed in the sample, if we',\
        'assume the sample to have an attenuation coefficient of',\
        AttenuationCoefficient[case], 'cm^-1 (@' + str(Voltage), 'kV)'

    # Absorbed radiation dose per second
    #~ Da = Eneregy / Weight  # J/kg per second
    AverageEnergy[case] = 28
    Da = N * AverageEnergy[case] * 1000 * eV / Weight

    print '    -', round(Da, 4), 'Gy/s are absorbed by the sample, if we',\
        'assume it is', Weight, 'kg'

    # Effective dose per second
    #~ De = Da * Wr, WR = Q * N
    De = Da * QFactor * WeightingFactor

    print '    -', round(De*1000, 4), 'mSv/s is the effective dose'

    # Total effective dose on the sample
    D = De * ExposureTime

    print '    -', round(D*1000, 4), 'Sv is the effective dose on the sample',\
        'for an exposure time of =', ExposureTime, 's)'
<commit_msg>Construct relative path of Spectra So we can also run the script over SSH, when the files might be in another (relative) path<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-

'''
Calculate photons and radiation dose per second
'''

from pylab import *
import numpy as np
import os

# Setup parameters
FOV = 10  # cm. Approximation of a wrist (10 * 10 * 5cm)
Area = FOV ** 2  # cm²
Thickness = 5  # cm
Volume = Area * Thickness
Density = 1.02  # g/cm³
Weight = float(Volume) * Density / 1000  # kg

# @40kV, half bone, half muscle
AttenuationCoefficient = []
AttenuationCoefficient.append(np.mean((2.685e-1, 6.655-1)))
# @70kV (0.5*60+0.5*80), both half bone, half muscle
AttenuationCoefficient.append(np.mean((np.mean((2.048e-01,3.148e-01)),
                                       np.mean((1.823e-01,2.229e-01)))))

'''
Skeletal muscle (http://is.gd/D88OFv)
    Energy         μ/ρ       μen/ρ
    (MeV)       (cm2/g)    (cm2/g)
    1.00000E-02  5.356E+00  4.964E+00
    1.50000E-02  1.693E+00  1.396E+00
    2.00000E-02  8.205E-01  5.638E-01
    3.00000E-02  3.783E-01  1.610E-01
    4.00000E-02  *2.685E-01*  7.192E-02
    5.00000E-02  2.262E-01  4.349E-02
    6.00000E-02  *2.048E-01*  3.258E-02
    8.00000E-02  *1.823E-01*  2.615E-02
Cortical bone (http://is.gd/2176eQ)
    Energy         μ/ρ       μen/ρ
    (MeV)       (cm2/g)    (cm2/g)
    1.00000E-02  2.851E+01  2.680E+01
    1.50000E-02  9.032E+00  8.388E+00
    2.00000E-02  4.001E+00  3.601E+00
    3.00000E-02  1.331E+00  1.070E+00
    4.00000E-02  *6.655E-01*  4.507E-01
    5.00000E-02  4.242E-01  2.336E-01
    6.00000E-02  *3.148E-01* 1.400E-01
    8.00000E-02  *2.229E-01*  6.896E-02
'''

r = 140  # cm, Distance from source to sample
eta = 1e-9  # *ZV
Z = 74  # Tungsten
eV = 1.602e-19  # J

QFactor = 1  # http://en.wikipedia.org/wiki/Dosimetry#Equivalent_Dose
WeightingFactor = 0.12  # http://en.wikipedia.org/wiki/Dosimetry#Effective_dose
ExposureTime = 100e-3  # s

# Read xray spectra
Spectrapath = os.path.join(os.getcwd(),'Spectra')
Spectra = [(os.path.join(Spectrapath, 'Xray-Spectrum_046kV.txt')),
           (os.path.join(Spectrapath, 'Xray-Spectrum_070kV.txt'))]

Data = [(np.loadtxt(FileName)) for FileName in Spectra]
SourceVoltage = [int(open(FileName).readlines()[3].split()[7])
                 for FileName in Spectra]
AverageEnergy = [float(open(FileName).readlines()[6].split()[3])
                 for FileName in Spectra]

# Give out values
for Voltage, Current, case in zip((SourceVoltage[0], SourceVoltage[1]),
                                  (50, 50), range(len(Spectra))):
    print 80 * '-'
    print 'For a voltage of', Voltage, 'kV and a current of', Current, 'mAs'
    print '    - we have a mean energy of', round(AverageEnergy[case],4), 'keV'

    # Calculate the number of photons from the tube to the sample
    #~ N0 = (VI/E)*eta*(A/4Pir²)
    N0 = (Voltage * Current) / (Voltage * eV) * \
        eta * Z * Voltage * \
        Area / (4 * np.pi * r ** 2)

    print '    - the tube emitts %.4e' % N0, 'photons per second'

    # Number of absorbed photons
    #~ N = N0(1-e^-uT)
    N = N0 * (1 - math.e ** (-AttenuationCoefficient[case] * Thickness))

    print '    - %.4e' % N, 'photons/s are absorbed in the sample, if we',\
        'assume the sample to have an attenuation coefficient of',\
        AttenuationCoefficient[case], 'cm^-1 (@' + str(Voltage), 'kV)'

    # Absorbed radiation dose per second
    #~ Da = Eneregy / Weight  # J/kg per second
    AverageEnergy[case] = 28
    Da = N * AverageEnergy[case] * 1000 * eV / Weight

    print '    -', round(Da, 4), 'Gy/s are absorbed by the sample, if we',\
        'assume it is', Weight, 'kg'

    # Effective dose per second
    #~ De = Da * Wr, WR = Q * N
    De = Da * QFactor * WeightingFactor

    print '    -', round(De*1000, 4), 'mSv/s is the effective dose'

    # Total effective dose on the sample
    D = De * ExposureTime

    print '    -', round(D*1000, 4), 'Sv is the effective dose on the sample',\
        'for an exposure time of =', ExposureTime, 's)'
<|endoftext|>