<commit_before>import unittest
import mock
import six
import tarfile
import os
import tempfile

from dogen.generator import Generator
from dogen.errors import Error
from dogen import version, DEFAULT_SCRIPT_EXEC, DEFAULT_SCRIPT_USER

class TestConfig(unittest.TestCase):
    def setUp(self):
        self.log = mock.Mock()
        self.descriptor = tempfile.NamedTemporaryFile(delete=False)

    def tearDown(self):
        os.remove(self.descriptor.name)

    def test_default_values(self):
        self.generator = Generator(self.log, self.descriptor.name, "target")
        self.assertEqual(self.generator.output, "target")
        self.assertEqual(self.generator.dockerfile, "target/Dockerfile")
        self.assertEqual(self.generator.descriptor, self.descriptor.name)
        self.assertEqual(self.generator.template, None)
        self.assertEqual(self.generator.scripts, None)
        self.assertEqual(self.generator.additional_scripts, None)
        self.assertEqual(self.generator.without_sources, False)
        self.assertEqual(self.generator.dist_git, False)
        # Set to True in the configure() method later
        self.assertEqual(self.generator.ssl_verify, None)
        self.assertFalse(self.generator.dist_git)

    def test_fail_if_version_mismatch(self):
        with self.descriptor as f:
            f.write("dogen:\n  version: 99999.9.9-dev1".encode())

        self.generator = Generator(self.log, self.descriptor.name, "target")

        with self.assertRaises(Error) as cm:
            self.generator.configure()

        self.assertEquals(
            str(cm.exception), "You try to parse descriptor that requires Dogen version 99999.9.9-dev1, but you run version %s" % version)

    def test_skip_ssl_verification_in_descriptor(self):
        with self.descriptor as f:
            f.write("dogen:\n  ssl_verify: false".encode())

        generator = Generator(self.log, self.descriptor.name, "target")
        generator.configure()
        self.assertFalse(generator.ssl_verify)

    def test_do_not_skip_ssl_verification_in_descriptor(self):
        with self.descriptor as f:
            f.write("dogen:\n  ssl_verify: true".encode())

        generator = Generator(self.log, self.descriptor.name, "target")
        generator.configure()
        self.assertTrue(generator.ssl_verify)

    def test_custom_template_in_descriptor(self):
        with self.descriptor as f:
            f.write("dogen:\n  template: custom-template.jinja".encode())

        generator = Generator(self.log, self.descriptor.name, "target")
        generator.configure()
        self.assertEqual(generator.template, "custom-template.jinja")

    def test_custom_template_in_cli_should_override_in_descriptor(self):
        with self.descriptor as f:
            f.write("dogen:\n  template: custom-template.jinja".encode())

        generator = Generator(self.log, self.descriptor.name, "target", template="cli-template.jinja")
        generator.configure()
        self.assertEqual(generator.template, "cli-template.jinja")

    def test_do_not_skip_ssl_verification_in_cli_true_should_override_descriptor(self):
        with self.descriptor as f:
            f.write("dogen:\n  ssl_verify: false".encode())

        generator = Generator(self.log, self.descriptor.name, "target", ssl_verify=True)
        generator.configure()
        self.assertTrue(generator.ssl_verify)

    def test_do_not_skip_ssl_verification_in_cli_false_should_override_descriptor(self):
        with self.descriptor as f:
            f.write("dogen:\n  ssl_verify: true".encode())

        generator = Generator(self.log, self.descriptor.name, "target", ssl_verify=False)
        generator.configure()
        self.assertFalse(generator.ssl_verify)

    @mock.patch('dogen.generator.os.path.exists', return_value=True)
    def test_custom_scripts_dir_in_descriptor(self, mock_patch):
        with self.descriptor as f:
            f.write("dogen:\n  scripts: custom-scripts".encode())

        generator = Generator(self.log, self.descriptor.name, "target")
        generator.configure()
        mock_patch.assert_called_with('custom-scripts')
        self.assertEqual(generator.scripts, "custom-scripts")

    @mock.patch('dogen.generator.os.path.exists', return_value=True)
    def test_custom_scripts_dir_in_cli_should_override_in_descriptor(self, mock_patch):
        with self.descriptor as f:
            f.write("dogen:\n  template: custom-scripts".encode())

        generator = Generator(self.log, self.descriptor.name, "target", scripts="custom-scripts-cli")
        generator.configure()
        mock_patch.assert_called_with('custom-scripts-cli')
        self.assertEqual(generator.scripts, "custom-scripts-cli")

    @mock.patch('dogen.generator.os.path.exists', return_value=True)
    def test_scripts_dir_found_by_convention(self, mock_patch):
        with self.descriptor as f:
            f.write("dogen:\n  scripts: custom-scripts".encode())

        generator = Generator(self.log, self.descriptor.name, "target")
        generator.configure()
        mock_patch.assert_called_with('custom-scripts')
        self.assertEqual(generator.scripts, "custom-scripts")

    def test_custom_additional_scripts_in_descriptor(self):
        with self.descriptor as f:
            f.write("dogen:\n  additional_scripts:\n    - http://host/somescript".encode())

        generator = Generator(self.log, self.descriptor.name, "target")
        generator.configure()
        self.assertEqual(generator.additional_scripts, ["http://host/somescript"])

    def test_custom_additional_scripts_in_cli_should_override_in_descriptor(self):
        with self.descriptor as f:
            f.write("dogen:\n  additional_scripts:\n    - http://host/somescript".encode())

        generator = Generator(self.log, self.descriptor.name, "target", additional_scripts=["https://otherhost/otherscript"])
        generator.configure()
        self.assertEqual(generator.additional_scripts, ["https://otherhost/otherscript"])

    @mock.patch('dogen.generator.os.path.exists', return_value=True)
    def helper_test_script_exec(self, exec_to_test, cfg, mock_patch):
        """Helper method for tests around script exec value"""
        with self.descriptor as f:
            f.write(cfg.encode())

        generator = Generator(self.log, self.descriptor.name, "target", scripts="scripts")
        generator.configure()
        generator._handle_scripts()
        self.assertEqual(generator.cfg['scripts'][0]['exec'], exec_to_test)

    def test_default_script_exec(self):
        """Ensure that when no 'exec' is defined for a script and DOGEN_SCRIPT_EXEC is
           unset, the default is used."""

        os.environ.pop('DOGEN_SCRIPT_EXEC', None)
        cfg = "scripts:\n    - package: somepackage"

        self.helper_test_script_exec(DEFAULT_SCRIPT_EXEC, cfg)

    def test_env_supplied_script_exec(self):
        """Ensure that when no 'exec' is defined for a script and DOGEN_SCRIPT_EXEC is defined,
           DOGEN_SCRIPT_EXEC is used."""

        custom_script_name = "somescript.sh"
        # we must be sure that DEFAULT_SCRIPT_EXEC is not being used by accident
        self.assertNotEqual(custom_script_name, DEFAULT_SCRIPT_EXEC)
        os.environ['DOGEN_SCRIPT_EXEC'] = custom_script_name
        cfg = "scripts:\n    - package: somepackage"

        self.helper_test_script_exec(custom_script_name, cfg)

    def test_custom_script_exec(self):
        """Ensure that when 'exec' *is* defined for a script and DOGEN_SCRIPT_EXEC is
           not defined, exec is used and not the default."""

        os.environ.pop('DOGEN_SCRIPT_EXEC', None)
        custom_script_name = "somescript.sh"
        self.assertNotEqual(custom_script_name, DEFAULT_SCRIPT_EXEC)
        cfg = "scripts:\n  - package: somepackage\n    exec: " + custom_script_name

        self.helper_test_script_exec(custom_script_name, cfg)

    def test_custom_script_exec_not_env(self):
        """Ensure that when 'exec' *is* defined for a script, it is not overridden by a
           provided value in the environment, or the default."""

        os.environ['DOGEN_SCRIPT_EXEC'] = "some_other_script.sh"
        custom_script_name = "somescript.sh"
        self.assertNotEqual(custom_script_name, DEFAULT_SCRIPT_EXEC)
        cfg = "scripts:\n  - package: somepackage\n    exec: " + custom_script_name

        self.helper_test_script_exec(custom_script_name, cfg)

    @mock.patch('dogen.generator.os.path.exists', return_value=True)
    def helper_test_script_user(self, cfg, user_to_test, mock_patch):
        """A helper for script user-related tests"""

        with self.descriptor as f:
            f.write(cfg.encode())

        generator = Generator(self.log, self.descriptor.name, "target", scripts="scripts")
        generator.configure()
        generator._handle_scripts()
        self.assertEqual(generator.cfg['scripts'][0]['user'], user_to_test)

    def test_default_script_user(self):
        """Ensure that when no 'user' is defined for a script and DOGEN_DEFAULT_USER is unset,
           the default is used."""

        os.environ.pop('DOGEN_SCRIPT_USER', None)
        cfg = "scripts:\n    - package: somepackage"

        self.helper_test_script_user(cfg, DEFAULT_SCRIPT_USER)

    def test_env_provided_script_user(self):
        """Ensure that when no 'user' is defined for a script and DOGEN_DEFAULT_USER is set,
           DOGEN_SCRIPT_USER is used."""

        env_user = os.environ['DOGEN_SCRIPT_USER'] = 'some_user'
        self.assertNotEqual(env_user, DEFAULT_SCRIPT_USER)
        cfg = "scripts:\n    - package: somepackage"

        self.helper_test_script_user(cfg, env_user)

    def test_custom_script_user_not_default(self):
        """Ensure that when 'user' *is* defined for a script and DOGEN_SCRIPT_USER is not set,
           the script user is used."""

        os.environ.pop('DOGEN_SCRIPT_USER', None)
        custom_script_user = "notroot"
        self.assertNotEqual(custom_script_user, DEFAULT_SCRIPT_USER)
        cfg = "scripts:\n  - package: somepackage\n    user: " + custom_script_user

        self.helper_test_script_user(cfg, custom_script_user)

    def test_custom_script_user_not_env(self):
        """Ensure that when 'user' *is* defined for a script and DOGEN_SCRIPT_USER is set,
           the script user is used."""

        custom_script_user = "notroot"
        env_user = "nobody"
        self.assertNotEqual(custom_script_user, DEFAULT_SCRIPT_USER)
        self.assertNotEqual(env_user, DEFAULT_SCRIPT_USER)
        os.environ['DOGEN_SCRIPT_USER'] = env_user
        cfg = "scripts:\n  - package: somepackage\n    user: " + custom_script_user

        self.helper_test_script_user(cfg, custom_script_user)
<commit_msg>Test for no scripts defined in YAML<commit_after>import unittest
import mock
import six
import tarfile
import os
import tempfile

from dogen.generator import Generator
from dogen.errors import Error
from dogen import version, DEFAULT_SCRIPT_EXEC, DEFAULT_SCRIPT_USER

class TestConfig(unittest.TestCase):
    def setUp(self):
        self.log = mock.Mock()
        self.descriptor = tempfile.NamedTemporaryFile(delete=False)

    def tearDown(self):
        os.remove(self.descriptor.name)

    def test_default_values(self):
        self.generator = Generator(self.log, self.descriptor.name, "target")
        self.assertEqual(self.generator.output, "target")
        self.assertEqual(self.generator.dockerfile, "target/Dockerfile")
        self.assertEqual(self.generator.descriptor, self.descriptor.name)
        self.assertEqual(self.generator.template, None)
        self.assertEqual(self.generator.scripts, None)
        self.assertEqual(self.generator.additional_scripts, None)
        self.assertEqual(self.generator.without_sources, False)
        self.assertEqual(self.generator.dist_git, False)
        # Set to True in the configure() method later
        self.assertEqual(self.generator.ssl_verify, None)
        self.assertFalse(self.generator.dist_git)

    def test_fail_if_version_mismatch(self):
        with self.descriptor as f:
            f.write("dogen:\n  version: 99999.9.9-dev1".encode())

        self.generator = Generator(self.log, self.descriptor.name, "target")

        with self.assertRaises(Error) as cm:
            self.generator.configure()

        self.assertEquals(
            str(cm.exception), "You try to parse descriptor that requires Dogen version 99999.9.9-dev1, but you run version %s" % version)

    def test_skip_ssl_verification_in_descriptor(self):
        with self.descriptor as f:
            f.write("dogen:\n  ssl_verify: false".encode())

        generator = Generator(self.log, self.descriptor.name, "target")
        generator.configure()
        self.assertFalse(generator.ssl_verify)

    def test_do_not_skip_ssl_verification_in_descriptor(self):
        with self.descriptor as f:
            f.write("dogen:\n  ssl_verify: true".encode())

        generator = Generator(self.log, self.descriptor.name, "target")
        generator.configure()
        self.assertTrue(generator.ssl_verify)

    def test_custom_template_in_descriptor(self):
        with self.descriptor as f:
            f.write("dogen:\n  template: custom-template.jinja".encode())

        generator = Generator(self.log, self.descriptor.name, "target")
        generator.configure()
        self.assertEqual(generator.template, "custom-template.jinja")

    def test_custom_template_in_cli_should_override_in_descriptor(self):
        with self.descriptor as f:
            f.write("dogen:\n  template: custom-template.jinja".encode())

        generator = Generator(self.log, self.descriptor.name, "target", template="cli-template.jinja")
        generator.configure()
        self.assertEqual(generator.template, "cli-template.jinja")

    def test_do_not_skip_ssl_verification_in_cli_true_should_override_descriptor(self):
        with self.descriptor as f:
            f.write("dogen:\n  ssl_verify: false".encode())

        generator = Generator(self.log, self.descriptor.name, "target", ssl_verify=True)
        generator.configure()
        self.assertTrue(generator.ssl_verify)

    def test_do_not_skip_ssl_verification_in_cli_false_should_override_descriptor(self):
        with self.descriptor as f:
            f.write("dogen:\n  ssl_verify: true".encode())

        generator = Generator(self.log, self.descriptor.name, "target", ssl_verify=False)
        generator.configure()
        self.assertFalse(generator.ssl_verify)

    @mock.patch('dogen.generator.os.path.exists', return_value=True)
    def test_custom_scripts_dir_in_descriptor(self, mock_patch):
        with self.descriptor as f:
            f.write("dogen:\n  scripts: custom-scripts".encode())

        generator = Generator(self.log, self.descriptor.name, "target")
        generator.configure()
        mock_patch.assert_called_with('custom-scripts')
        self.assertEqual(generator.scripts, "custom-scripts")

    @mock.patch('dogen.generator.os.path.exists', return_value=True)
    def test_custom_scripts_dir_in_cli_should_override_in_descriptor(self, mock_patch):
        with self.descriptor as f:
            f.write("dogen:\n  template: custom-scripts".encode())

        generator = Generator(self.log, self.descriptor.name, "target", scripts="custom-scripts-cli")
        generator.configure()
        mock_patch.assert_called_with('custom-scripts-cli')
        self.assertEqual(generator.scripts, "custom-scripts-cli")

    @mock.patch('dogen.generator.os.path.exists', return_value=True)
    def test_scripts_dir_found_by_convention(self, mock_patch):
        with self.descriptor as f:
            f.write("dogen:\n  scripts: custom-scripts".encode())

        generator = Generator(self.log, self.descriptor.name, "target")
        generator.configure()
        mock_patch.assert_called_with('custom-scripts')
        self.assertEqual(generator.scripts, "custom-scripts")

    def test_custom_additional_scripts_in_descriptor(self):
        with self.descriptor as f:
            f.write("dogen:\n  additional_scripts:\n    - http://host/somescript".encode())

        generator = Generator(self.log, self.descriptor.name, "target")
        generator.configure()
        self.assertEqual(generator.additional_scripts, ["http://host/somescript"])

    def test_custom_additional_scripts_in_cli_should_override_in_descriptor(self):
        with self.descriptor as f:
            f.write("dogen:\n  additional_scripts:\n    - http://host/somescript".encode())

        generator = Generator(self.log, self.descriptor.name, "target", additional_scripts=["https://otherhost/otherscript"])
        generator.configure()
        self.assertEqual(generator.additional_scripts, ["https://otherhost/otherscript"])

    @mock.patch('dogen.generator.os.path.exists', return_value=True)
    def helper_test_script_exec(self, exec_to_test, cfg, mock_patch):
        """Helper method for tests around script exec value"""
        with self.descriptor as f:
            f.write(cfg.encode())

        generator = Generator(self.log, self.descriptor.name, "target", scripts="scripts")
        generator.configure()
        generator._handle_scripts()
        self.assertEqual(generator.cfg['scripts'][0]['exec'], exec_to_test)

    def test_default_script_exec(self):
        """Ensure that when no 'exec' is defined for a script and DOGEN_SCRIPT_EXEC is
           unset, the default is used."""

        os.environ.pop('DOGEN_SCRIPT_EXEC', None)
        cfg = "scripts:\n    - package: somepackage"

        self.helper_test_script_exec(DEFAULT_SCRIPT_EXEC, cfg)

    def test_env_supplied_script_exec(self):
        """Ensure that when no 'exec' is defined for a script and DOGEN_SCRIPT_EXEC is defined,
           DOGEN_SCRIPT_EXEC is used."""

        custom_script_name = "somescript.sh"
        # we must be sure that DEFAULT_SCRIPT_EXEC is not being used by accident
        self.assertNotEqual(custom_script_name, DEFAULT_SCRIPT_EXEC)
        os.environ['DOGEN_SCRIPT_EXEC'] = custom_script_name
        cfg = "scripts:\n    - package: somepackage"

        self.helper_test_script_exec(custom_script_name, cfg)

    def test_custom_script_exec(self):
        """Ensure that when 'exec' *is* defined for a script and DOGEN_SCRIPT_EXEC is
           not defined, exec is used and not the default."""

        os.environ.pop('DOGEN_SCRIPT_EXEC', None)
        custom_script_name = "somescript.sh"
        self.assertNotEqual(custom_script_name, DEFAULT_SCRIPT_EXEC)
        cfg = "scripts:\n  - package: somepackage\n    exec: " + custom_script_name

        self.helper_test_script_exec(custom_script_name, cfg)

    def test_custom_script_exec_not_env(self):
        """Ensure that when 'exec' *is* defined for a script, it is not overridden by a
           provided value in the environment, or the default."""

        os.environ['DOGEN_SCRIPT_EXEC'] = "some_other_script.sh"
        custom_script_name = "somescript.sh"
        self.assertNotEqual(custom_script_name, DEFAULT_SCRIPT_EXEC)
        cfg = "scripts:\n  - package: somepackage\n    exec: " + custom_script_name

        self.helper_test_script_exec(custom_script_name, cfg)

    @mock.patch('dogen.generator.os.path.exists', return_value=True)
    def helper_test_script_user(self, cfg, user_to_test, mock_patch):
        """A helper for script user-related tests"""

        with self.descriptor as f:
            f.write(cfg.encode())

        generator = Generator(self.log, self.descriptor.name, "target", scripts="scripts")
        generator.configure()
        generator._handle_scripts()
        self.assertEqual(generator.cfg['scripts'][0]['user'], user_to_test)

    def test_default_script_user(self):
        """Ensure that when no 'user' is defined for a script and DOGEN_DEFAULT_USER is unset,
           the default is used."""

        os.environ.pop('DOGEN_SCRIPT_USER', None)
        cfg = "scripts:\n    - package: somepackage"

        self.helper_test_script_user(cfg, DEFAULT_SCRIPT_USER)

    def test_env_provided_script_user(self):
        """Ensure that when no 'user' is defined for a script and DOGEN_DEFAULT_USER is set,
           DOGEN_SCRIPT_USER is used."""

        env_user = os.environ['DOGEN_SCRIPT_USER'] = 'some_user'
        self.assertNotEqual(env_user, DEFAULT_SCRIPT_USER)
        cfg = "scripts:\n    - package: somepackage"

        self.helper_test_script_user(cfg, env_user)

    def test_custom_script_user_not_default(self):
        """Ensure that when 'user' *is* defined for a script and DOGEN_SCRIPT_USER is not set,
           the script user is used."""

        os.environ.pop('DOGEN_SCRIPT_USER', None)
        custom_script_user = "notroot"
        self.assertNotEqual(custom_script_user, DEFAULT_SCRIPT_USER)
        cfg = "scripts:\n  - package: somepackage\n    user: " + custom_script_user

        self.helper_test_script_user(cfg, custom_script_user)

    def test_custom_script_user_not_env(self):
        """Ensure that when 'user' *is* defined for a script and DOGEN_SCRIPT_USER is set,
           the script user is used."""

        custom_script_user = "notroot"
        env_user = "nobody"
        self.assertNotEqual(custom_script_user, DEFAULT_SCRIPT_USER)
        self.assertNotEqual(env_user, DEFAULT_SCRIPT_USER)
        os.environ['DOGEN_SCRIPT_USER'] = env_user
        cfg = "scripts:\n  - package: somepackage\n    user: " + custom_script_user

        self.helper_test_script_user(cfg, custom_script_user)

    def test_no_scripts_defined(self):
        "make sure _handle_scripts doesn't blow up when there are no scripts"

        with self.descriptor as f:
            f.write("name: somecfg\n".encode())

        generator = Generator(self.log, self.descriptor.name, "target", scripts="scripts")
        generator.configure()
        generator._handle_scripts()
        # success if no stack trace thrown
<|endoftext|>


<commit_before>import mock
import unittest

from boto.ec2.blockdevicemapping import BlockDeviceType

class BlockDeviceTypeTests(unittest.TestCase):
    def setUp(self):
        self.block_device_type = BlockDeviceType()

    def check_that_attribute_has_been_set(self, name, value, attribute):
        self.block_device_type.endElement(name, value, None)
        self.assertEqual(getattr(self.block_device_type, attribute), value)

    def test_endElement_sets_correct_attributes_with_values(self):
        for arguments in [("volumeId", 1, "volume_id"),
                          ("virtualName", "some name", "ephemeral_name"),
                          ("snapshotId", 1, "snapshot_id"),
                          ("volumeSize", 1, "size"),
                          ("status", "some status", "status"),
                          ("attachTime", 1, "attach_time"),
                          ("somethingRandom", "somethingRandom", "somethingRandom")]:
            self.check_that_attribute_has_been_set(arguments[0], arguments[1], arguments[2])

    def test_endElement_with_name_NoDevice_value_true(self):
        self.block_device_type.endElement("NoDevice", 'true', None)
        self.assertEqual(self.block_device_type.no_device, True)

    def test_endElement_with_name_NoDevice_value_other(self):
        self.block_device_type.endElement("NoDevice", 'something else', None)
        self.assertEqual(self.block_device_type.no_device, False)

    def test_endElement_with_name_deleteOnTermination_value_true(self):
        self.block_device_type.endElement("deleteOnTermination", "true", None)
        self.assertEqual(self.block_device_type.delete_on_termination, True)

    def test_endElement_with_name_deleteOnTermination_value_other(self):
        self.block_device_type.endElement("deleteOnTermination", 'something else', None)
        self.assertEqual(self.block_device_type.delete_on_termination, False)

if __name__ == "__main__":
    unittest.main()
<commit_msg>add BlockDeviceMappingTests<commit_after>import mock
import unittest

from boto.ec2.blockdevicemapping import BlockDeviceType, BlockDeviceMapping

class BlockDeviceTypeTests(unittest.TestCase):
    def setUp(self):
        self.block_device_type = BlockDeviceType()

    def check_that_attribute_has_been_set(self, name, value, attribute):
        self.block_device_type.endElement(name, value, None)
        self.assertEqual(getattr(self.block_device_type, attribute), value)

    def test_endElement_sets_correct_attributes_with_values(self):
        for arguments in [("volumeId", 1, "volume_id"),
                          ("virtualName", "some name", "ephemeral_name"),
                          ("snapshotId", 1, "snapshot_id"),
                          ("volumeSize", 1, "size"),
                          ("status", "some status", "status"),
                          ("attachTime", 1, "attach_time"),
                          ("somethingRandom", "somethingRandom", "somethingRandom")]:
            self.check_that_attribute_has_been_set(arguments[0], arguments[1], arguments[2])

    def test_endElement_with_name_NoDevice_value_true(self):
        self.block_device_type.endElement("NoDevice", 'true', None)
        self.assertEqual(self.block_device_type.no_device, True)

    def test_endElement_with_name_NoDevice_value_other(self):
        self.block_device_type.endElement("NoDevice", 'something else', None)
        self.assertEqual(self.block_device_type.no_device, False)

    def test_endElement_with_name_deleteOnTermination_value_true(self):
        self.block_device_type.endElement("deleteOnTermination", "true", None)
        self.assertEqual(self.block_device_type.delete_on_termination, True)

    def test_endElement_with_name_deleteOnTermination_value_other(self):
        self.block_device_type.endElement("deleteOnTermination", 'something else', None)
        self.assertEqual(self.block_device_type.delete_on_termination, False)

class BlockDeviceMappingTests(unittest.TestCase):
    def setUp(self):
        self.block_device_mapping = BlockDeviceMapping()

    def block_device_type_eq(self, b1, b2):
        if isinstance(b1, BlockDeviceType) and isinstance(b2, BlockDeviceType):
            return all([b1.connection == b2.connection,
                        b1.ephemeral_name == b2.ephemeral_name,
                        b1.no_device == b2.no_device,
                        b1.volume_id == b2.volume_id,
                        b1.snapshot_id == b2.snapshot_id,
                        b1.status == b2.status,
                        b1.attach_time == b2.attach_time,
                        b1.delete_on_termination == b2.delete_on_termination,
                        b1.size == b2.size])

    def test_startElement_with_name_ebs_sets_and_returns_current_value(self):
        retval = self.block_device_mapping.startElement("ebs", None, None)
        assert self.block_device_type_eq(retval, BlockDeviceType(self.block_device_mapping))

    def test_startElement_with_name_virtualName_sets_and_returns_current_value(self):
        retval = self.block_device_mapping.startElement("virtualName", None, None)
        assert self.block_device_type_eq(retval, BlockDeviceType(self.block_device_mapping))

    def test_endElement_with_name_device_sets_current_name(self):
        self.block_device_mapping.endElement("device", "/dev/null", None)
        self.assertEqual(self.block_device_mapping.current_name, "/dev/null")

    def test_endElement_with_name_device_sets_current_name(self):
        self.block_device_mapping.endElement("deviceName", "some device name", None)
        self.assertEqual(self.block_device_mapping.current_name, "some device name")

    def test_endElement_with_name_item_sets_current_name_key_to_current_value(self):
        self.block_device_mapping.current_name = "some name"
        self.block_device_mapping.current_value = "some value"
        self.block_device_mapping.endElement("item", "some item", None)
        self.assertEqual(self.block_device_mapping["some name"], "some value")

if __name__ == "__main__":
    unittest.main()
<|endoftext|>


<commit_before># coding=utf-8
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from mock import patch, call
from nose.tools import assert_raises, assert_equals
import unit
import uuid

from synapseclient import Project, File, AUTHENTICATED_USERS
import synapseutils

def setup(module):
    module.syn = unit.syn

def test_copyWiki_empty_Wiki():
    entity = {"id": "syn123"}
    with patch.object(syn, "getWikiHeaders", return_value=None), \
            patch.object(syn, "get", return_value=entity):
        synapseutils.copyWiki(syn, "syn123", "syn456", updateLinks=False)

def test_copyWiki_input_validation():
    to_copy=[{'id': '8688', 'title': 'A Test Wiki'},
             {'id': '8689', 'title': 'A sub-wiki', 'parentId': '8688'},
             {'id': '8690', 'title': 'A sub-sub-wiki', 'parentId': '8689'}]
    wiki={"id": "8786",
          "title": "A Test Wiki",
          "markdown": "some text"
         }
    entity={"id":"syn123"}
    expected_calls=[call({'id': 'syn123'}, '4'),
                    call({'id': 'syn123'}, '8688'),
                    call({'id': 'syn123'}, '8689'),
                    call({'id': 'syn123'}, '8690')]
    with patch.object(syn, "getWikiHeaders", return_value=to_copy),\
            patch.object(syn, "get", return_value=entity),\
            patch.object(syn, "getWiki", return_value=wiki) as mock_getWiki,\
            patch.object(syn, "store", return_value=wiki):
        synapseutils.copyWiki(syn, "syn123", "syn456", entitySubPageId="8688", destinationSubPageId="4",
                              updateLinks=False)
        mock_getWiki.assert_has_calls(expected_calls)

        synapseutils.copyWiki(syn, "syn123", "syn456", entitySubPageId=8688.0, destinationSubPageId=4.0,
                              updateLinks=False)
        mock_getWiki.assert_has_calls(expected_calls)

        assert_raises(ValueError, synapseutils.copyWiki, syn, "syn123", "syn456", entitySubPageId="some_string",
                      updateLinks=False)

class TestCopyPermissions:
    """Test copy entities with different permissions"""
    def setup(self):
        self.project_entity = Project(name=str(uuid.uuid4()), id="syn1234")
        self.second_project = Project(name=str(uuid.uuid4()), id="syn2345")
        self.file_ent = File(name='File', parent=self.project_entity.id,
                             id="syn3456")

    def test_dont_copy_read_permissions(self):
        """Entities with READ permissions not copied"""
        permissions = {'canDownload': False}
        with patch.object(syn, "get",
                         return_value=self.file_ent) as patch_syn_get,\
             patch.object(syn, "restGET",
                          return_value=permissions) as patch_rest_get:
            copied_file = synapseutils.copy(syn, self.file_ent,
                                            destinationId=self.second_project.id,
                                            skipCopyWikiPage=True)
            assert_equals(copied_file, dict())
            patch_syn_get.assert_called_once_with(self.file_ent,
                                                  downloadFile=False)
            rest_call = "/entity/{}/permissions".format(self.file_ent.id)
            patch_rest_get.assert_called_once_with(rest_call)

class TestCopyAccessRestriction:
    """Test that entities with access restrictions aren't copied"""
    def setup(self):
        self.project_entity = Project(name=str(uuid.uuid4()), id="syn1234")
        self.second_project = Project(name=str(uuid.uuid4()), id="syn2345")
        self.file_ent = File(name='File', parent=self.project_entity.id)
        self.file_ent.id = "syn3456"

    def test_copy_entity_access_requirements(self):
        # TEST: Entity with access requirement not copied
        access_requirements = {'results': ["fee", "fi"]}
        permissions = {'canDownload': True}
        with patch.object(syn, "get",
                          return_value=self.file_ent) as patch_syn_get,\
             patch.object(syn, "restGET",
                          side_effects=[permissions,
                                        access_requirements]) as patch_rest_get:
            copied_file = synapseutils.copy(syn, self.file_ent,
                                            destinationId=self.second_project.id,
                                            skipCopyWikiPage=True)
            assert_equals(copied_file, dict())
            patch_syn_get.assert_called_once_with(self.file_ent,
                                                  downloadFile=False)
            # patch_rest_get.assert_called_once_with('/entity/{}/accessRequirement'.format(self.file_ent.id))

class TestCopy:
    """Test that certain entities aren't copied"""
    def setup(self):
        self.project_entity = Project(name=str(uuid.uuid4()), id="syn1234")
        self.second_project = Project(name=str(uuid.uuid4()), id="syn2345")
        self.file_ent = File(name='File', parent=self.project_entity.id)
        self.file_ent.id = "syn3456"

    def test_no_copy_types(self):
        """Docker repositories and EntityViews aren't copied"""
        access_requirements = {'results': []}
        permissions = {'canDownload': True}
        with patch.object(syn, "get",
                          return_value=self.project_entity) as patch_syn_get,\
             patch.object(syn, "restGET",
                          side_effect=[permissions,
                                       access_requirements]) as patch_rest_get,\
             patch.object(syn, "getChildren") as patch_get_children:
            copied_file = synapseutils.copy(syn, self.project_entity,
                                             destinationId=self.second_project.id,
                                            skipCopyWikiPage=True)
            assert_equals(copied_file, {self.project_entity.id:
                                        self.second_project.id})
            calls = [call(self.project_entity, downloadFile=False),
                     call(self.second_project.id)]
            patch_syn_get.assert_has_calls(calls)
            # patch_restget.assert_called_once_with('/entity/{}/accessRequirement'.format(self.project_entity.id))
            patch_get_children.assert_called_once_with(self.project_entity,
                                                       includeTypes=['folder', 'file',
                                                                     'table', 'link'])
<commit_msg>patch assert rest calls<commit_after># coding=utf-8
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from mock import patch, call
from nose.tools import assert_raises, assert_equals
import unit
import uuid

from synapseclient import Project, File, AUTHENTICATED_USERS
import synapseutils

def setup(module):
    module.syn = unit.syn

def test_copyWiki_empty_Wiki():
    entity = {"id": "syn123"}
    with patch.object(syn, "getWikiHeaders", return_value=None), \
            patch.object(syn, "get", return_value=entity):
        synapseutils.copyWiki(syn, "syn123", "syn456", updateLinks=False)

def test_copyWiki_input_validation():
    to_copy=[{'id': '8688', 'title': 'A Test Wiki'},
             {'id': '8689', 'title': 'A sub-wiki', 'parentId': '8688'},
             {'id': '8690', 'title': 'A sub-sub-wiki', 'parentId': '8689'}]
    wiki={"id": "8786",
          "title": "A Test Wiki",
          "markdown": "some text"
         }
    entity={"id":"syn123"}
    expected_calls=[call({'id': 'syn123'}, '4'),
                    call({'id': 'syn123'}, '8688'),
                    call({'id': 'syn123'}, '8689'),
                    call({'id': 'syn123'}, '8690')]
    with patch.object(syn, "getWikiHeaders", return_value=to_copy),\
            patch.object(syn, "get", return_value=entity),\
            patch.object(syn, "getWiki", return_value=wiki) as mock_getWiki,\
            patch.object(syn, "store", return_value=wiki):
        synapseutils.copyWiki(syn, "syn123", "syn456", entitySubPageId="8688", destinationSubPageId="4",
                              updateLinks=False)
        mock_getWiki.assert_has_calls(expected_calls)

        synapseutils.copyWiki(syn, "syn123", "syn456", entitySubPageId=8688.0, destinationSubPageId=4.0,
                              updateLinks=False)
        mock_getWiki.assert_has_calls(expected_calls)

        assert_raises(ValueError, synapseutils.copyWiki, syn, "syn123", "syn456", entitySubPageId="some_string",
                      updateLinks=False)

class TestCopyPermissions:
    """Test copy entities with different permissions"""
    def setup(self):
        self.project_entity = Project(name=str(uuid.uuid4()), id="syn1234")
        self.second_project = Project(name=str(uuid.uuid4()), id="syn2345")
        self.file_ent = File(name='File', parent=self.project_entity.id,
                             id="syn3456")

    def test_dont_copy_read_permissions(self):
        """Entities with READ permissions not copied"""
        permissions = {'canDownload': False}
        with patch.object(syn, "get",
                         return_value=self.file_ent) as patch_syn_get,\
             patch.object(syn, "restGET",
                          return_value=permissions) as patch_rest_get:
            copied_file = synapseutils.copy(syn, self.file_ent,
                                            destinationId=self.second_project.id,
                                            skipCopyWikiPage=True)
            assert_equals(copied_file, dict())
            patch_syn_get.assert_called_once_with(self.file_ent,
                                                  downloadFile=False)
            rest_call = "/entity/{}/permissions".format(self.file_ent.id)
            patch_rest_get.assert_called_once_with(rest_call)

class TestCopyAccessRestriction:
    """Test that entities with access restrictions aren't copied"""
    def setup(self):
        self.project_entity = Project(name=str(uuid.uuid4()), id="syn1234")
        self.second_project = Project(name=str(uuid.uuid4()), id="syn2345")
        self.file_ent = File(name='File', parent=self.project_entity.id)
        self.file_ent.id = "syn3456"

    def test_copy_entity_access_requirements(self):
        # TEST: Entity with access requirement not copied
        access_requirements = {'results': ["fee", "fi"]}
        permissions = {'canDownload': True}
        with patch.object(syn, "get",
                          return_value=self.file_ent) as patch_syn_get,\
             patch.object(syn, "restGET",
                          side_effects=[permissions,
                                        access_requirements]) as patch_rest_get:
            copied_file = synapseutils.copy(syn, self.file_ent,
                                            destinationId=self.second_project.id,
                                            skipCopyWikiPage=True)
            assert_equals(copied_file, dict())
            patch_syn_get.assert_called_once_with(self.file_ent,
                                                  downloadFile=False)
            calls = [call('/entity/{}/accessRequirement'.format(self.file_ent.id)),
                     call("/entity/{}/permissions".format(self.file_ent.id))]
            patch_rest_get.has_calls(calls)

class TestCopy:
    """Test that certain entities aren't copied"""
    def setup(self):
        self.project_entity = Project(name=str(uuid.uuid4()), id="syn1234")
        self.second_project = Project(name=str(uuid.uuid4()), id="syn2345")
        self.file_ent = File(name='File', parent=self.project_entity.id)
        self.file_ent.id = "syn3456"

    def test_no_copy_types(self):
        """Docker repositories and EntityViews aren't copied"""
        access_requirements = {'results': []}
        permissions = {'canDownload': True}
        with patch.object(syn, "get",
                          return_value=self.project_entity) as patch_syn_get,\
             patch.object(syn, "restGET",
                          side_effect=[permissions,
                                       access_requirements]) as patch_rest_get,\
             patch.object(syn, "getChildren") as patch_get_children:
            copied_file = synapseutils.copy(syn, self.project_entity,
                                             destinationId=self.second_project.id,
                                            skipCopyWikiPage=True)
            assert_equals(copied_file, {self.project_entity.id:
                                        self.second_project.id})
            calls = [call(self.project_entity, downloadFile=False),
                     call(self.second_project.id)]
            patch_syn_get.assert_has_calls(calls)
            calls = [call('/entity/{}/accessRequirement'.format(self.file_ent.id)),
                     call("/entity/{}/permissions".format(self.file_ent.id))]
            patch_rest_get.has_calls(calls)
            patch_get_children.assert_called_once_with(self.project_entity,
                                                       includeTypes=['folder', 'file',
                                                                     'table', 'link'])
<|endoftext|>


<commit_before>гит рулит<commit_msg>гит или не гит<commit_after>гит рулит идли нет<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

# Copyright © 2014 Cask Data, Inc.
#
# 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.

#
# Tigon documentation build configuration file
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.

import sys
import os
import subprocess

def get_sdk_version():
    # Sets the Build Version via maven
    mvn_version_cmd = "mvn help:evaluate -o -Dexpression=project.version -f ../../../pom.xml | grep -v '^\['"
    version = None
    try:
        version = subprocess.check_output(mvn_version_cmd, shell=True).strip().replace("-SNAPSHOT", "")
    except:
        print "Could not get version from maven"
        sys.exit(1)
    return version

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))

# -- General configuration ------------------------------------------------

# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.todo',
    'sphinx.ext.pngmath',
    'sphinx.ext.ifconfig',
    'rst2pdf.pdfbuilder',
    'sphinxcontrib.googleanalytics',
]

# Remove intersphinx as we are not linking to other peoples's docs with Sphinx
#    'sphinx.ext.intersphinx',

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# The suffix of source filenames.
source_suffix = '.rst'

# The encoding of source files.
#source_encoding = 'utf-8-sig'

# The master toctree document.
master_doc = 'index'

# General information about the project.
project = u'Tigon'
copyright = u'2014 Cask Data, Inc.'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = get_sdk_version() # '2.4.0'
# The full version, including alpha/beta/rc tags.
release = get_sdk_version() # '2.4.0'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
language = 'en_CDAP'
locale_dirs = ['_locale/']

# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_includes']

# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None

# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True

# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True

# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False

# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'

# The default language to highlight source code in.
highlight_language = 'java'

# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []

# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False

# Add Google Analytics ID, or over-ride on the command line with
# -D googleanalytics_id=UA-999-999-999
googleanalytics_id = 'UA-123-123-123'

# True by default, use it to turn off tracking.
# -D googleanalytics_enabled=1
# Turned off so unless the code and flag are passed on the command line, tracking is off.
googleanalytics_enabled = False

# -- Options for HTML output ----------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
#html_theme = 'default'
#html_theme = 'nature'
#html_style = 'style.css'
html_theme = 'tigon'

# Theme options are theme-specific and customize the look and feel of a theme
# further.  For a list of options available for each theme, see the
# documentation.
#html_theme_options = {"stickysidebar":"true"}

# Add any paths that contain custom themes here, relative to this directory.
html_theme_path = ['_themes']

# The name for this set of Sphinx documents.  If None, it defaults to
# "<project> v<release> documentation".
#html_title = None

# A shorter title for the navigation bar.  Default is the same as html_title.
#html_short_title = None

# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None

# The name of an image file (within the static path) to use as favicon of the
# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
html_favicon = '_static/favicon.ico'

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []

# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'

# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True

# Custom sidebar templates, maps document names to template names.
html_sidebars = {'**': ['globaltoc.html', 'relations.html', 'searchbox.html'],}

# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}

# If false, no module index is generated.
#html_domain_indices = True

# If false, no index is generated.
#html_use_index = True

# If true, the index is split into individual pages for each letter.
#html_split_index = False

# If true, links to the reST sources are added to the pages.
html_show_sourcelink = False
html_copy_source = False

# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
html_show_sphinx = False

# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True

# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it.  The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''

# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None

# Output file base name for HTML help builder.
htmlhelp_basename = 'Tigondoc'

# -- Options for LaTeX output ---------------------------------------------

latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',

# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',

# Additional stuff for the LaTeX preamble.
#'preamble': '',
}

# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
#  author, documentclass [howto, manual, or own class]).
latex_documents = [
  ('index', 'Tigon.tex', u'Tigon Documentation',
   u'Cask Data, Inc.', 'manual'),
]

# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None

# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False

# If true, show page references after internal links.
#latex_show_pagerefs = False

# If true, show URL addresses after external links.
#latex_show_urls = False

# Documents to append as an appendix to all manuals.
#latex_appendices = []

# If false, no module index is generated.
#latex_domain_indices = True

# -- Options for manual page output ---------------------------------------

# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
    ('index', 'tigon', u'Tigon Documentation',
     [u'Cask Data, Inc.'], 1)
]

# If true, show URL addresses after external links.
#man_show_urls = False

# -- Options for Texinfo output -------------------------------------------

# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
#  dir menu entry, description, category)
texinfo_documents = [
  ('index', 'Tigon', u'Tigon Documentation',
   u'Cask Data, Inc.', 'Tigon', 'Tigon',
   'Miscellaneous'),
]

# Documents to append as an appendix to all manuals.
#texinfo_appendices = []

# If false, no module index is generated.
#texinfo_domain_indices = True

# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'

# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False

# Example configuration for intersphinx: refer to the Python standard library.
#intersphinx_mapping = {'http://docs.python.org/': None}

# -- Options for PDF output --------------------------------------------------

# Grouping the document tree into PDF files. List of tuples
# (source start file, target name, title, author, options).
#
# If there is more than one author, separate them with \\.
# For example: r'Guido van Rossum\\Fred L. Drake, Jr., editor'
#
# The options element is a dictionary that lets you override
# this config per-document.
# For example,
# ('index', u'MyProject', u'My Project', u'Author Name',
#  dict(pdf_compressed = True))
# would mean that specific document would be compressed
# regardless of the global pdf_compressed setting.

pdf_documents = [
    ('index', u'Tigon', u'Tigon', u'Cask Data, Inc.'),
]

# A comma-separated list of custom stylesheets. Example:
#pdf_stylesheets = ['sphinx','kerning','a4']
pdf_stylesheets = ['pdf-stylesheet']

# A list of folders to search for stylesheets. Example:
pdf_style_path = ['.', '_templates', '_styles']

# Create a compressed PDF
# Use True/False or 1/0
# Example: compressed=True
#pdf_compressed = False

# A colon-separated list of folders to search for fonts. Example:
# pdf_font_path = ['/usr/share/fonts', '/usr/share/texmf-dist/fonts/']
pdf_font_path = ['/Library/fonts', '~/Library/Fonts']

# Language to be used for hyphenation support
pdf_language = "en_US"

# Mode for literal blocks wider than the frame. Can be
# overflow, shrink or truncate
pdf_fit_mode = "shrink"

# Section level that forces a break page.
# For example: 1 means top-level sections start in a new page
# 0 means disabled
pdf_break_level = 1

# When a section starts in a new page, force it to be 'even', 'odd',
# or just use 'any'
pdf_breakside = 'any'

# Insert footnotes where they are defined instead of
# at the end.
#pdf_inline_footnotes = True

# verbosity level. 0 1 or 2
#pdf_verbosity = 0

# If false, no index is generated.
pdf_use_index = False

# If false, no modindex is generated.
pdf_use_modindex = False

# If false, no coverpage is generated.
pdf_use_coverpage = False

# Name of the cover page template to use
#pdf_cover_template = 'sphinxcover.tmpl'

# Documents to append as an appendix to all manuals.
#pdf_appendices = []

# Enable experimental feature to split table cells. Use it
# if you get "DelayedTable too big" errors
#pdf_splittables = False

# Set the default DPI for images
#pdf_default_dpi = 72

# Enable rst2pdf extension modules (default is only vectorpdf)
# you need vectorpdf if you want to use sphinx's graphviz support
#pdf_extensions = ['vectorpdf']

# Page template name for "regular" pages
#pdf_page_template = 'cutePage'

# Show Table Of Contents at the beginning?
#pdf_use_toc = True

# How many levels deep should the table of contents be?
pdf_toc_depth = 9999

# Add section number to section references
pdf_use_numbered_links = False

# Background images fitting mode
pdf_fit_background_mode = 'scale'
<commit_msg>Fix retrieval of build version to use grep instead of maven.<commit_after># -*- coding: utf-8 -*-

# Copyright © 2014 Cask Data, Inc.
#
# 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.

#
# Tigon documentation build configuration file
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.

import sys
import os
import subprocess

def get_sdk_version():
    # Sets the Build Version
    grep_version_cmd = "grep '<version>' ../../../pom.xml | awk 'NR==1;START{print $1}'"
    version = None
    try:
        version = subprocess.check_output(grep_version_cmd, shell=True).strip().replace("-SNAPSHOT", "").replace("<version>", "").replace("</version>", "")
        print "SDK Version: %s" % version
    except:
        print "Could not get version from grep"
        sys.exit(1)
    return version

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))

# -- General configuration ------------------------------------------------

# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.todo',
    'sphinx.ext.pngmath',
    'sphinx.ext.ifconfig',
    'rst2pdf.pdfbuilder',
    'sphinxcontrib.googleanalytics',
]

# Remove intersphinx as we are not linking to other peoples's docs with Sphinx
#    'sphinx.ext.intersphinx',

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# The suffix of source filenames.
source_suffix = '.rst'

# The encoding of source files.
#source_encoding = 'utf-8-sig'

# The master toctree document.
master_doc = 'index'

# General information about the project.
project = u'Tigon'
copyright = u'2014 Cask Data, Inc.'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = get_sdk_version() # '2.4.0'
# The full version, including alpha/beta/rc tags.
release = get_sdk_version() # '2.4.0'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
language = 'en_CDAP'
locale_dirs = ['_locale/']

# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_includes']

# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None

# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True

# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True

# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False

# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'

# The default language to highlight source code in.
highlight_language = 'java'

# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []

# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False

# Add Google Analytics ID, or over-ride on the command line with
# -D googleanalytics_id=UA-999-999-999
googleanalytics_id = 'UA-123-123-123'

# True by default, use it to turn off tracking.
# -D googleanalytics_enabled=1
# Turned off so unless the code and flag are passed on the command line, tracking is off.
googleanalytics_enabled = False

# -- Options for HTML output ----------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
#html_theme = 'default'
#html_theme = 'nature'
#html_style = 'style.css'
html_theme = 'tigon'

# Theme options are theme-specific and customize the look and feel of a theme
# further.  For a list of options available for each theme, see the
# documentation.
#html_theme_options = {"stickysidebar":"true"}

# Add any paths that contain custom themes here, relative to this directory.
html_theme_path = ['_themes']

# The name for this set of Sphinx documents.  If None, it defaults to
# "<project> v<release> documentation".
#html_title = None

# A shorter title for the navigation bar.  Default is the same as html_title.
#html_short_title = None

# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None

# The name of an image file (within the static path) to use as favicon of the
# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
html_favicon = '_static/favicon.ico'

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []

# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'

# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True

# Custom sidebar templates, maps document names to template names.
html_sidebars = {'**': ['globaltoc.html', 'relations.html', 'searchbox.html'],}

# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}

# If false, no module index is generated.
#html_domain_indices = True

# If false, no index is generated.
#html_use_index = True

# If true, the index is split into individual pages for each letter.
#html_split_index = False

# If true, links to the reST sources are added to the pages.
html_show_sourcelink = False
html_copy_source = False

# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
html_show_sphinx = False

# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True

# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it.  The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''

# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None

# Output file base name for HTML help builder.
htmlhelp_basename = 'Tigondoc'

# -- Options for LaTeX output ---------------------------------------------

latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',

# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',

# Additional stuff for the LaTeX preamble.
#'preamble': '',
}

# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
#  author, documentclass [howto, manual, or own class]).
latex_documents = [
  ('index', 'Tigon.tex', u'Tigon Documentation',
   u'Cask Data, Inc.', 'manual'),
]

# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None

# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False

# If true, show page references after internal links.
#latex_show_pagerefs = False

# If true, show URL addresses after external links.
#latex_show_urls = False

# Documents to append as an appendix to all manuals.
#latex_appendices = []

# If false, no module index is generated.
#latex_domain_indices = True

# -- Options for manual page output ---------------------------------------

# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
    ('index', 'tigon', u'Tigon Documentation',
     [u'Cask Data, Inc.'], 1)
]

# If true, show URL addresses after external links.
#man_show_urls = False

# -- Options for Texinfo output -------------------------------------------

# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
#  dir menu entry, description, category)
texinfo_documents = [
  ('index', 'Tigon', u'Tigon Documentation',
   u'Cask Data, Inc.', 'Tigon', 'Tigon',
   'Miscellaneous'),
]

# Documents to append as an appendix to all manuals.
#texinfo_appendices = []

# If false, no module index is generated.
#texinfo_domain_indices = True

# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'

# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False

# Example configuration for intersphinx: refer to the Python standard library.
#intersphinx_mapping = {'http://docs.python.org/': None}

# -- Options for PDF output --------------------------------------------------

# Grouping the document tree into PDF files. List of tuples
# (source start file, target name, title, author, options).
#
# If there is more than one author, separate them with \\.
# For example: r'Guido van Rossum\\Fred L. Drake, Jr., editor'
#
# The options element is a dictionary that lets you override
# this config per-document.
# For example,
# ('index', u'MyProject', u'My Project', u'Author Name',
#  dict(pdf_compressed = True))
# would mean that specific document would be compressed
# regardless of the global pdf_compressed setting.

pdf_documents = [
    ('index', u'Tigon', u'Tigon', u'Cask Data, Inc.'),
]

# A comma-separated list of custom stylesheets. Example:
#pdf_stylesheets = ['sphinx','kerning','a4']
pdf_stylesheets = ['pdf-stylesheet']

# A list of folders to search for stylesheets. Example:
pdf_style_path = ['.', '_templates', '_styles']

# Create a compressed PDF
# Use True/False or 1/0
# Example: compressed=True
#pdf_compressed = False

# A colon-separated list of folders to search for fonts. Example:
# pdf_font_path = ['/usr/share/fonts', '/usr/share/texmf-dist/fonts/']
pdf_font_path = ['/Library/fonts', '~/Library/Fonts']

# Language to be used for hyphenation support
pdf_language = "en_US"

# Mode for literal blocks wider than the frame. Can be
# overflow, shrink or truncate
pdf_fit_mode = "shrink"

# Section level that forces a break page.
# For example: 1 means top-level sections start in a new page
# 0 means disabled
pdf_break_level = 1

# When a section starts in a new page, force it to be 'even', 'odd',
# or just use 'any'
pdf_breakside = 'any'

# Insert footnotes where they are defined instead of
# at the end.
#pdf_inline_footnotes = True

# verbosity level. 0 1 or 2
#pdf_verbosity = 0

# If false, no index is generated.
pdf_use_index = False

# If false, no modindex is generated.
pdf_use_modindex = False

# If false, no coverpage is generated.
pdf_use_coverpage = False

# Name of the cover page template to use
#pdf_cover_template = 'sphinxcover.tmpl'

# Documents to append as an appendix to all manuals.
#pdf_appendices = []

# Enable experimental feature to split table cells. Use it
# if you get "DelayedTable too big" errors
#pdf_splittables = False

# Set the default DPI for images
#pdf_default_dpi = 72

# Enable rst2pdf extension modules (default is only vectorpdf)
# you need vectorpdf if you want to use sphinx's graphviz support
#pdf_extensions = ['vectorpdf']

# Page template name for "regular" pages
#pdf_page_template = 'cutePage'

# Show Table Of Contents at the beginning?
#pdf_use_toc = True

# How many levels deep should the table of contents be?
pdf_toc_depth = 9999

# Add section number to section references
pdf_use_numbered_links = False

# Background images fitting mode
pdf_fit_background_mode = 'scale'
<|endoftext|>


<commit_before>__version__ = '0.0.12'
<commit_msg>version 0.0.13<commit_after>__version__ = '0.0.13'
<|endoftext|>


<commit_before><commit_msg>make catchall_statsd plugin better<commit_after><|endoftext|>


<commit_before>from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save, m2m_changed
from django.db.utils import DatabaseError
from fabric.api import env, run, hide, settings
from fabric.network import disconnect_all
import os
from django.conf import settings as app_settings
from ssheepdog.utils import DirtyFieldsMixin

KEYS_DIR = os.path.join(app_settings.PROJECT_ROOT,
                        '../deploy/keys')
FABRIC_WARNINGS = ['everything', 'status', 'aborts']

class UserProfile(DirtyFieldsMixin, models.Model):
    nickname = models.CharField(max_length=256)
    user = models.OneToOneField(User, primary_key=True, related_name='_profile_cache')
    ssh_key = models.TextField()
    is_active = models.BooleanField()

    def __str__(self):
        return self.nickname

    def __unicode__(self):
        return self.nickname or self.user.username

class Machine(DirtyFieldsMixin, models.Model):
    # XXX: A machine should have either an IP or hostname or both
    # Need a validator in the form supplied to the django admin
    # Consider validating on save as well... not as important
    nickname = models.CharField(max_length=256)
    hostname = models.CharField(max_length=256, blank=True, null=True)
    ip = models.CharField(max_length=256, null=True, blank=True)
    description = models.TextField()
    port = models.IntegerField(default=22)
    client = models.ForeignKey('Client', null=True, blank=True)
    is_down = models.BooleanField(default=False)
    is_active = models.BooleanField()

    def __unicode__(self):
        return self.nickname

    def save(self, *args, **kwargs):
        fields = set(['hostname', 'ip', 'port','is_active'])
        made_dirty = bool(fields.intersection(self.get_dirty_fields()))
        if made_dirty:
            self.login_set.update(is_dirty=True)
        super(Machine, self).save(*args, **kwargs)

class Login(DirtyFieldsMixin, models.Model):
    machine = models.ForeignKey('Machine')
    username = models.CharField(max_length=256)
    users = models.ManyToManyField(User, blank=True)
    client = models.ForeignKey('Client', null=True, blank=True)
    application_key = models.ForeignKey('ApplicationKey', null=True)
    is_active = models.BooleanField(default=True)
    is_dirty = models.BooleanField(default=True)

    @staticmethod
    def sync():
        try:
            for login in Login.objects.all():
                login.update_keys()
        finally:
            disconnect_all()

    def __unicode__(self):
        return self.username

    def get_application_key(self):
        if self.application_key is None:
            self.application_key = ApplicationKey.get_latest()
            self.save()
        return self.application_key

    def save(self, *args, **kwargs):
        fields = set(['machine', 'username', 'is_active'])
        made_dirty = bool(fields.intersection(self.get_dirty_fields()))
        self.is_dirty = self.is_dirty or made_dirty
        super(Login, self).save(*args, **kwargs)

    def run(self, command, private_key=None):
        """
        Ssh in to Login to run command.  Return True on success, False ow.
        """

        mach = self.machine
        env.abort_on_prompts = True
        env.key_filename = private_key or ApplicationKey.get_latest().private_key
        env.host_string = "%s@%s:%d" % (self.username,
                                        (mach.ip or mach.hostname),
                                        mach.port)
        try:
            with settings(hide(*FABRIC_WARNINGS)):
                run(command)
            return True
        except SystemExit:
            return False

    def get_authorized_keys(self):
        """
        Return a list of authorized keys strings which should be deployed
        to the machine.
        """
        keys = [ApplicationKey.get_latest().public_key]
        if self.is_active and self.machine.is_active:
            for user in (self.users
                         .filter(is_active = True)
                         .select_related('_profile_cache')):
                keys.append(user.get_profile().ssh_key)
        return keys

    def update_keys(self):
        """
        Updates the authorized_keys file on the machine attached to this login
        adding or deleting users public keys

        Returns True if successfully changed the authorized files and False if
        not (status stays dirty).  If no change attempted, return None.
        """
        if self.machine.is_down or not self.is_dirty:
            # No update required (either impossible or not needed)
            return None
        if self.run('echo "%s" > ~/.ssh/authorized_keys' % "\n".join(
            self.get_authorized_keys()),
            self.get_application_key().private_key):
            self.is_dirty = False
            self.application_key = ApplicationKey.get_latest()
            self.save()
            return True
        else:
            return False

class Client(models.Model):
    nickname = models.CharField(max_length=256)
    description = models.TextField()
    def __unicode__(self):
        return self.nickname

class ApplicationKey(models.Model):
    private_key = models.TextField()
    public_key = models.TextField()

    def save(self, *args, **kwargs):
        if not self.private_key and not self.public_key:
            self.generate_key_pair()
        super(ApplicationKey, self).save(*args, **kwargs)

    def __unicode__(self):
        return "%s ssheepdog_%s" % (self.public_key[-10:], self.pk)

    def generate_key_pair(self):
        import base64
        from Crypto.PublicKey import RSA

        key = RSA.generate(app_settings.RSA_KEY_LENGTH)
        self.private_key = key.exportKey()

        # This magic is from
        # http://stackoverflow.com/questions/2466401/how-to-generate-ssh-key-pairs-with-python

        exponent = '%x' % (key.e, )
        if len(exponent) % 2:
            exponent = '0' + exponent

        ssh_rsa = '00000007' + base64.b16encode('ssh-rsa')
        ssh_rsa += '%08x' % (len(exponent) / 2, )
        ssh_rsa += exponent

        modulus = '%x' % (key.n, )
        if len(modulus) % 2:
            modulus = '0' + modulus

        if modulus[0] in '89abcdef':
            modulus = '00' + modulus

        ssh_rsa += '%08x' % (len(modulus) / 2, )
        ssh_rsa += modulus

        self.public_key = 'ssh-rsa %s' % (
            base64.b64encode(base64.b16decode(ssh_rsa.upper())),
            )

    @staticmethod
    def get_latest(create_new=False):
        if not create_new:
            try:
                return ApplicationKey.objects.latest('pk')
            except ApplicationKey.DoesNotExist:
                pass
        key = ApplicationKey()
        key.save()
        return key

def create_user_profile(sender, instance, created, **kwargs):
    if created:
        try:
            UserProfile.objects.create(user=instance)
        except DatabaseError: # Creating fresh db from manage.py
            pass

post_save.connect(create_user_profile, sender=User)

def user_login_changed(sender, instance=None, reverse=None, model=None,
                       action=None, **kwargs):
    if action[:4] == 'pre_':
        return
    login = model if reverse else instance
    login.is_dirty = True
    login.save()

m2m_changed.connect(user_login_changed, sender=Login.users.through)
<commit_msg>sync keys and new app key button working<commit_after>from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save, m2m_changed
from django.db.utils import DatabaseError
from fabric.api import env, run, hide, settings
from fabric.network import disconnect_all
import os
from django.conf import settings as app_settings
from ssheepdog.utils import DirtyFieldsMixin

KEYS_DIR = os.path.join(app_settings.PROJECT_ROOT,
                        '../deploy/keys')
FABRIC_WARNINGS = ['everything', 'status', 'aborts']

class UserProfile(DirtyFieldsMixin, models.Model):
    nickname = models.CharField(max_length=256)
    user = models.OneToOneField(User, primary_key=True, related_name='_profile_cache')
    ssh_key = models.TextField()
    is_active = models.BooleanField()

    def __str__(self):
        return self.nickname

    def __unicode__(self):
        return self.nickname or self.user.username

class Machine(DirtyFieldsMixin, models.Model):
    # XXX: A machine should have either an IP or hostname or both
    # Need a validator in the form supplied to the django admin
    # Consider validating on save as well... not as important
    nickname = models.CharField(max_length=256)
    hostname = models.CharField(max_length=256, blank=True, null=True)
    ip = models.CharField(max_length=256, null=True, blank=True)
    description = models.TextField()
    port = models.IntegerField(default=22)
    client = models.ForeignKey('Client', null=True, blank=True)
    is_down = models.BooleanField(default=False)
    is_active = models.BooleanField()

    def __unicode__(self):
        return self.nickname

    def save(self, *args, **kwargs):
        fields = set(['hostname', 'ip', 'port','is_active'])
        made_dirty = bool(fields.intersection(self.get_dirty_fields()))
        if made_dirty:
            self.login_set.update(is_dirty=True)
        super(Machine, self).save(*args, **kwargs)

class Login(DirtyFieldsMixin, models.Model):
    machine = models.ForeignKey('Machine')
    username = models.CharField(max_length=256)
    users = models.ManyToManyField(User, blank=True)
    client = models.ForeignKey('Client', null=True, blank=True)
    application_key = models.ForeignKey('ApplicationKey', null=True)
    is_active = models.BooleanField(default=True)
    is_dirty = models.BooleanField(default=True)

    @staticmethod
    def sync():
        try:
            for login in Login.objects.all():
                login.update_keys()
                disconnect_all()
        finally:
            disconnect_all()

    def __unicode__(self):
        return self.username

    def get_application_key(self):
        if self.application_key is None:
            self.application_key = ApplicationKey.get_latest()
            self.save()
        return self.application_key

    def save(self, *args, **kwargs):
        fields = set(['machine', 'username', 'is_active'])
        made_dirty = bool(fields.intersection(self.get_dirty_fields()))
        self.is_dirty = self.is_dirty or made_dirty
        super(Login, self).save(*args, **kwargs)

    def run(self, command, private_key=None):
        """
        Ssh in to Login to run command.  Return True on success, False ow.
        """

        mach = self.machine
        env.abort_on_prompts = True
        env.key_filename = private_key or ApplicationKey.get_latest().private_key
        env.host_string = "%s@%s:%d" % (self.username,
                                        (mach.ip or mach.hostname),
                                        mach.port)
        try:
            with settings(hide(*FABRIC_WARNINGS)):
                run(command)
            return True
        except SystemExit:
            return False

    def get_authorized_keys(self):
        """
        Return a list of authorized keys strings which should be deployed
        to the machine.
        """
        keys = [ApplicationKey.get_latest().public_key]
        if self.is_active and self.machine.is_active:
            for user in (self.users
                         .filter(is_active = True)
                         .select_related('_profile_cache')):
                keys.append(user.get_profile().ssh_key)
        return keys

    def update_keys(self):
        """
        Updates the authorized_keys file on the machine attached to this login
        adding or deleting users public keys

        Returns True if successfully changed the authorized files and False if
        not (status stays dirty).  If no change attempted, return None.
        """
        if self.machine.is_down or not self.is_dirty:
            # No update required (either impossible or not needed)
            return None
        if self.run('echo "%s" > ~/.ssh/authorized_keys' % "\n".join(
            self.get_authorized_keys()),
            self.get_application_key().private_key):
            self.is_dirty = False
            self.application_key = ApplicationKey.get_latest()
            self.save()
            return True
        else:
            return False

class Client(models.Model):
    nickname = models.CharField(max_length=256)
    description = models.TextField()
    def __unicode__(self):
        return self.nickname

class ApplicationKey(models.Model):
    private_key = models.TextField()
    public_key = models.TextField()

    def save(self, *args, **kwargs):
        if not self.private_key and not self.public_key:
            self.generate_key_pair()
        super(ApplicationKey, self).save(*args, **kwargs)

    def __unicode__(self):
        return "%s ssheepdog_%s" % (self.public_key[-10:], self.pk)

    def generate_key_pair(self):
        import base64
        from Crypto.PublicKey import RSA

        key = RSA.generate(app_settings.RSA_KEY_LENGTH)
        self.private_key = key.exportKey()

        # This magic is from
        # http://stackoverflow.com/questions/2466401/how-to-generate-ssh-key-pairs-with-python

        exponent = '%x' % (key.e, )
        if len(exponent) % 2:
            exponent = '0' + exponent

        ssh_rsa = '00000007' + base64.b16encode('ssh-rsa')
        ssh_rsa += '%08x' % (len(exponent) / 2, )
        ssh_rsa += exponent

        modulus = '%x' % (key.n, )
        if len(modulus) % 2:
            modulus = '0' + modulus

        if modulus[0] in '89abcdef':
            modulus = '00' + modulus

        ssh_rsa += '%08x' % (len(modulus) / 2, )
        ssh_rsa += modulus

        self.public_key = 'ssh-rsa %s' % (
            base64.b64encode(base64.b16decode(ssh_rsa.upper())),
            )

    @staticmethod
    def get_latest(create_new=False):
        if not create_new:
            try:
                return ApplicationKey.objects.latest('pk')
            except ApplicationKey.DoesNotExist:
                pass
        key = ApplicationKey()
        key.save()
        return key

def create_user_profile(sender, instance, created, **kwargs):
    if created:
        try:
            UserProfile.objects.create(user=instance)
        except DatabaseError: # Creating fresh db from manage.py
            pass

post_save.connect(create_user_profile, sender=User)

def user_login_changed(sender, instance=None, reverse=None, model=None,
                       action=None, **kwargs):
    if action[:4] == 'pre_':
        return
    login = model if reverse else instance
    login.is_dirty = True
    login.save()

m2m_changed.connect(user_login_changed, sender=Login.users.through)
<|endoftext|>


<commit_before>#!/usr/bin/python
#
# Copyright (C) 2012 Codethink Limited

import os
import sys
import bottle

def application(environ, start_response):
    server_path = environ['MUSTARD_SERVER_PATH']
    project_path = environ['MUSTARD_PROJECT_PATH']

    sys.path.append(server_path)
    os.chdir(os.path.dirname(__file__))

    print server_path
    print os.path.dirname(__file__)

    import mustard
    app = mustard.renderer.App().run(['-p', project_path])

    return bottle.default_app().wsgi(environent, start_response)
<commit_msg>Bottle complains that Bottle objects don't have wsgi()...<commit_after>#!/usr/bin/python
#
# Copyright (C) 2012 Codethink Limited

import os
import sys
import bottle

def application(environ, start_response):
    server_path = environ['MUSTARD_SERVER_PATH']
    project_path = environ['MUSTARD_PROJECT_PATH']

    sys.path.append(server_path)
    os.chdir(os.path.dirname(__file__))

    print server_path
    print os.path.dirname(__file__)

    import mustard
    mustard.renderer.App().run(['-p', project_path])

    return bottle.wsgi(environent, start_response)
<|endoftext|>


<commit_before>from pymongo import MongoClient
from lxml import etree
from dateutil.parser import parse

import pickle
from time import gmtime, strftime
import os
import re

data_dir = '../../../bin/so_data_/'
file_name = 'Posts.xml'
db_name = 'kesh'
coll_name = 'answers'

# Load in a set of python question ids.
with open('question_ids.pickle', 'rb') as f:
    question_ids = pickle.load(f)

client = MongoClient()
db = client[db_name]
coll = db[coll_name]

context = etree.iterparse(os.path.join(data_dir, file_name),
                          events=('start', 'end'))

str_to_int = {'Id', 'PostTypeId', 'ParentId', 'Score', 'ViewCount',
              'OwnerUserId', 'AcceptedAnswerId', 'CommentCount',
              'FavoriteCount', 'LastEditorUserId'}
str_to_date = {'CreationDate', 'LastActivityDate', 'LastEditDate',
               'CommunityOwnedDate', 'ClosedDate'}

def convert(name):
   s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
   return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()

f = open(os.path.join(data_dir, './logs/{:s}.log'.format(coll_name)), 'w')
s = 'Importing {:s} data.\n\n'.format(coll_name)
f.write(s)
print(s, end='')

i = 0
answer_ids = set()

for event, elem in context:
    if event == 'end' and elem.tag == 'row':
        # Create a dictionary and convert any necessary fields.
        d = dict(elem.items())
        if int(d['post_type_id']) == 2 and int(d['parent_id']) in question_ids:
            d = {convert(k):int(v) if k in str_to_int else
                 parse(v) if k in str_to_date else
                 v for k, v in d.items()}
            coll.insert(d)
            answer_ids.add(d['id'])
            elem.clear()
            while elem.getprevious() is not None:
                del elem.getparent()[0]
            i += 1
            if i % 1000 == 0:
                s_option = (strftime('%H:%M:%S', gmtime()), d['id'])
                s = '{:s} : Id - {:d}\n'.format(*s_option)
                print(s, end='')
                f.write(s)

coll.ensure_index(convert('id'))

f.close()

with open('answer_ids.pickle', 'wb') as f:
    pickle.dump(answer_ids, f)

<commit_msg>Updated database creation files<commit_after>from pymongo import MongoClient
from lxml import etree
from dateutil.parser import parse

import pickle
from time import gmtime, strftime
import os
import re

data_dir = '../../../bin/so_data_/'
file_name = 'Posts.xml'
db_name = 'kesh'
coll_name = 'answers'

# Load in a set of python question ids.
with open('question_ids.pickle', 'rb') as f:
    question_ids = pickle.load(f)

client = MongoClient()
db = client[db_name]
coll = db[coll_name]

context = etree.iterparse(os.path.join(data_dir, file_name),
                          events=('start', 'end'))

str_to_int = {'Id', 'PostTypeId', 'ParentId', 'Score', 'ViewCount',
              'OwnerUserId', 'AcceptedAnswerId', 'CommentCount',
              'FavoriteCount', 'LastEditorUserId'}
str_to_date = {'CreationDate', 'LastActivityDate', 'LastEditDate',
               'CommunityOwnedDate', 'ClosedDate'}

def convert(name):
   s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
   return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()

f = open(os.path.join(data_dir, './logs/{:s}.log'.format(coll_name)), 'w')
s = 'Importing {:s} data.\n\n'.format(coll_name)
f.write(s)
print(s, end='')

i = 0
answer_ids = set()

for event, elem in context:
    if event == 'end' and elem.tag == 'row':
        # Create a dictionary and convert any necessary fields.
        d = dict(elem.items())
        if int(d['PostTypeId']) == 2 and int(d['ParentId']) in question_ids:
            d = {convert(k):int(v) if k in str_to_int else
                 parse(v) if k in str_to_date else
                 v for k, v in d.items()}
            coll.insert(d)
            answer_ids.add(d['id'])
            elem.clear()
            while elem.getprevious() is not None:
                del elem.getparent()[0]
            i += 1
            if i % 1000 == 0:
                s_option = (strftime('%H:%M:%S', gmtime()), d['id'])
                s = '{:s} : Id - {:d}\n'.format(*s_option)
                print(s, end='')
                f.write(s)

coll.ensure_index(convert('id'))

f.close()

with open('answer_ids.pickle', 'wb') as f:
    pickle.dump(answer_ids, f)

<|endoftext|>


<commit_before>import os.path
import uuid
import logging
import tornado.auth
import tornado.escape
import tornado.ioloop
import tornado.web
import tornado.httpserver
import tornado.options as options

from tornado.concurrent import Future
from tornado import gen
from tornado.options import define, options

import sockjs.tornado

import uimodules

import pymongo
import bson.json_util as json_util

define("port", default=8888, help="port", type=int)
define("db", default="panoptes", help="Name of the Mongo DB to use")
define("collection", default="admin", help="Name of the Mongo Collection to use")
define("debug", default=False, help="debug mode")

class Application(tornado.web.Application):

    """ The main Application entry for our PANOPTES admin interface """

    def __init__(self):
        SensorRouter = sockjs.tornado.SockJSRouter(SensorSocket, '/sensors')

        handlers = [
            (r"/", MainHandler),
            (r"/login", LoginHandler),
            (r"/logout", LogoutHandler),
            (r"/webcams", WebCamHandler),
        ] + SensorRouter.urls

        # Create a global connection to Mongo
        db = pymongo.MongoClient().panoptes

        settings = dict(
            cookie_secret="PANOPTES_SUPER_DOOPER_SECRET",
            login_url="/login",
            template_path=os.path.join(os.path.dirname(__file__), "templates"),
            static_path=os.path.join(os.path.dirname(__file__), "static"),
            xsrf_cookies=True,
            db=db,
            debug=options.debug,
            site_title="PANOPTES",
            ui_modules=uimodules,
        )

        super(Application, self).__init__(handlers, **settings)

class BaseHandler(tornado.web.RequestHandler):

    """
    BaseHandler is inherited by all Handlers and is responsible for any
    global operations. Provides the `db` property and the `get_current_user`
    """
    @property
    def db(self):
        """ Simple property to access the DB easier """
        return self.settings['db']

    def get_current_user(self):
        """
        Looks for a cookie that shows we have been logged in. If cookie
        is found, attempt to look up user info in the database
        """
        # Get email from cookie
        email = tornado.escape.to_unicode(self.get_secure_cookie("email"))
        if not email:
            return None

        # Look up user data
        user_data = self.db.admin.find_one({'username': email})
        if user_data is None:
            return None

        return user_data

class MainHandler(BaseHandler):

    @tornado.web.authenticated
    def get(self):
        user_data = self.current_user

        self.render("main.html", user_data=user_data)

class SensorSocket(sockjs.tornado.SockJSConnection):

    """ Handler for the environmental sensors.

    Implemented with sockjs for websockets or long polling
    """

    # Class level variable
    observers = set()

    def on_open(self, info):
        # Add client to the clients list
        self.observers.add(self)

    def on_message(self, message):
        # Broadcast message
        self.broadcast(self.observers, message)

    def on_close(self):
        # Remove client from the clients list and broadcast leave message
        self.observers.remove(self)

class WebCamHandler(BaseHandler):

    @tornado.web.authenticated
    def get(self):
        self.render("webcams.html")

class LoginHandler(BaseHandler):

    """
    Login and authenticate the user and perform any actions for startup
    """

    def get(self):
        self.render("login.html")

    def post(self):
        email = tornado.escape.to_unicode(self.get_argument("email"))
        self.set_secure_cookie("email", email)
        self.redirect("/")

class LogoutHandler(BaseHandler):

    """
    Operations run when the user logs out.
    """

    def get(self):
        self.clear_cookie("email")
        self.redirect("/")

def main():
    tornado.options.parse_command_line()
    http_server = tornado.httpserver.HTTPServer(Application())
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

if __name__ == '__main__':
    main()
<commit_msg>Removing extra<commit_after>import os.path
import tornado.auth
import tornado.escape
import tornado.ioloop
import tornado.web
import tornado.httpserver
import tornado.options as options

from tornado.concurrent import Future
from tornado import gen
from tornado.options import define, options

import sockjs.tornado

import uimodules

import pymongo
import bson.json_util as json_util

define("port", default=8888, help="port", type=int)
define("db", default="panoptes", help="Name of the Mongo DB to use")
define("collection", default="admin", help="Name of the Mongo Collection to use")
define("debug", default=False, help="debug mode")

class Application(tornado.web.Application):

    """ The main Application entry for our PANOPTES admin interface """

    def __init__(self):
        SensorRouter = sockjs.tornado.SockJSRouter(SensorSocket, '/sensors')

        handlers = [
            (r"/", MainHandler),
            (r"/login", LoginHandler),
            (r"/logout", LogoutHandler),
            (r"/webcams", WebCamHandler),
        ] + SensorRouter.urls

        # Create a global connection to Mongo
        db = pymongo.MongoClient().panoptes

        settings = dict(
            cookie_secret="PANOPTES_SUPER_DOOPER_SECRET",
            login_url="/login",
            template_path=os.path.join(os.path.dirname(__file__), "templates"),
            static_path=os.path.join(os.path.dirname(__file__), "static"),
            xsrf_cookies=True,
            db=db,
            debug=options.debug,
            site_title="PANOPTES",
            ui_modules=uimodules,
        )

        super(Application, self).__init__(handlers, **settings)

class BaseHandler(tornado.web.RequestHandler):

    """
    BaseHandler is inherited by all Handlers and is responsible for any
    global operations. Provides the `db` property and the `get_current_user`
    """
    @property
    def db(self):
        """ Simple property to access the DB easier """
        return self.settings['db']

    def get_current_user(self):
        """
        Looks for a cookie that shows we have been logged in. If cookie
        is found, attempt to look up user info in the database
        """
        # Get email from cookie
        email = tornado.escape.to_unicode(self.get_secure_cookie("email"))
        if not email:
            return None

        # Look up user data
        user_data = self.db.admin.find_one({'username': email})
        if user_data is None:
            return None

        return user_data

class MainHandler(BaseHandler):

    @tornado.web.authenticated
    def get(self):
        user_data = self.current_user

        self.render("main.html", user_data=user_data)

class SensorSocket(sockjs.tornado.SockJSConnection):

    """ Handler for the environmental sensors.

    Implemented with sockjs for websockets or long polling
    """

    # Class level variable
    observers = set()

    def on_open(self, info):
        # Add client to the clients list
        self.observers.add(self)

    def on_message(self, message):
        # Broadcast message
        self.broadcast(self.observers, message)

    def on_close(self):
        # Remove client from the clients list and broadcast leave message
        self.observers.remove(self)

class WebCamHandler(BaseHandler):

    @tornado.web.authenticated
    def get(self):
        self.render("webcams.html")

class LoginHandler(BaseHandler):

    """
    Login and authenticate the user and perform any actions for startup
    """

    def get(self):
        self.render("login.html")

    def post(self):
        email = tornado.escape.to_unicode(self.get_argument("email"))
        self.set_secure_cookie("email", email)
        self.redirect("/")

class LogoutHandler(BaseHandler):

    """
    Operations run when the user logs out.
    """

    def get(self):
        self.clear_cookie("email")
        self.redirect("/")

def main():
    tornado.options.parse_command_line()
    http_server = tornado.httpserver.HTTPServer(Application())
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

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