<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  Copyright (C) 2013  Matt Jeffery <matt@clan.se>
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

import sys
import unittest2
from mock import patch

from semetric.apiclient import SemetricAPI
from semetric.apiclient.exc import APIError
from semetric.apiclient.entity.base import Entity
from semetric.apiclient.entity.artist import Artist
from semetric.apiclient.entity.chart import Chart
from .consts import (
    APIKEY,
    ARTIST_ADELE,
    ARTIST_ADELE_ID
)

# Base string type for Python3
if sys.version_info >= (3,): # pragma: no cover
    basestring = str

class TestSemetricAPI(unittest2.TestCase):

    def test_get_request_bad(self):

        api = SemetricAPI(APIKEY)

        # Make the api response
        with patch.object(api.client, 'request', autospec=True) as api_mock:
            api_mock.return_value = ""
            with self.assertRaises(APIError):
                api.get(Artist, name="lady gaga")

    def test_search_request_artist(self):

        api = SemetricAPI(APIKEY)

        # Make the api response
        with patch.object(api.client, 'request', autospec=True) as api_mock:
            api_mock.return_value = []
            api.search(Artist, name="lady gaga")

            api_mock.assert_called_once_with("artist", q="lady gaga")

    def test_get_request_artist(self):

        api = SemetricAPI(APIKEY)

        # Make the api response
        with patch.object(api.client, 'request', autospec=True) as api_mock:
            # Setup the API response
            api_mock.return_value = Artist(apisession=api.client, id="87e0e4ccc7f4415cbd6ba60ad49943b6")
            a = api.get(Artist, id="87e0e4ccc7f4415cbd6ba60ad49943b6")
            assert not api_mock.called, "the API should only be called when accessing a property that isn't cached"

            # The API should only be called if an unknown value is accessed
            print a.name
            api_mock.assert_called_once_with("artist/87e0e4ccc7f4415cbd6ba60ad49943b6")

    def test_search_request_not_implemented(self):

        api = SemetricAPI(APIKEY)
        with self.assertRaises(NotImplementedError):
            api.search(Entity, name="foo")

    def test_search_request_entity(self):

        api = SemetricAPI(APIKEY)

        # Make the api response
        with patch.object(api.client, 'request', autospec=True) as api_mock:
            api_mock.return_value = Entity(apisession=api.client, id="87e0e4ccc7f4415cbd6ba60ad49943b6")
            api.get(Entity, id="87e0e4ccc7f4415cbd6ba60ad49943b6")
            assert not api_mock.called, "the API should only be called when accessing a property that isn't cached"

    def test_get_chart_with_country(self):

        api = SemetricAPI(APIKEY)

        # Make the api response
        with patch.object(api.client, 'request', autospec=True) as api_mock:
            api_mock.return_value = Chart(apisession=api.client, id="0695f0bba6144dfaa390e9b9f017ceab", country="CA")
            api.get(Chart, id="0695f0bba6144dfaa390e9b9f017ceab", country="CA")

            api_mock.assert_called_once_with("chart/0695f0bba6144dfaa390e9b9f017ceab", country="CA")

    def test_get_chart_without_country(self):

        api = SemetricAPI(APIKEY)

        # Make the api response
        with patch.object(api.client, 'request', autospec=True) as api_mock:
            api_mock.return_value = Chart(apisession=api.client, id="0695f0bba6144dfaa390e9b9f017ceab")
            api.get(Chart, id="0695f0bba6144dfaa390e9b9f017ceab")

            api_mock.assert_called_once_with("chart/0695f0bba6144dfaa390e9b9f017ceab", country="ALL")

    def test_get_artist_timeseries(self):

        api = SemetricAPI(APIKEY)

        # Make the api response
        with patch.object(api.client, 'request', autospec=True) as api_mock:
            api_mock.return_value = Entity(apisession=api.client, **ARTIST_ADELE)
            artist = api.get(Artist, id=ARTIST_ADELE_ID)

            assert isinstance(artist, Artist)
            assert not api_mock.called, "the API should only be called when accessing a property that isn't cached"

            artist.timeseries("plays/total")
            api_mock.assert_called_once_with("artist/e6ee861435b24f67a6283e00bf820bab/plays/total",
                                             country="ALL",
                                             variant="diff",
                                             processing="processed",
                                             granularity="day")
<commit_msg>removed print, sorry python 3<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  Copyright (C) 2013  Matt Jeffery <matt@clan.se>
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

import sys
import unittest2
from mock import patch

from semetric.apiclient import SemetricAPI
from semetric.apiclient.exc import APIError
from semetric.apiclient.entity.base import Entity
from semetric.apiclient.entity.artist import Artist
from semetric.apiclient.entity.chart import Chart
from .consts import (
    APIKEY,
    ARTIST_ADELE,
    ARTIST_ADELE_ID
)

# Base string type for Python 3
if sys.version_info >= (3,): # pragma: no cover
    basestring = str

class TestSemetricAPI(unittest2.TestCase):

    def test_get_request_bad(self):

        api = SemetricAPI(APIKEY)

        # Make the api response
        with patch.object(api.client, 'request', autospec=True) as api_mock:
            api_mock.return_value = ""
            with self.assertRaises(APIError):
                api.get(Artist, name="lady gaga")

    def test_search_request_artist(self):

        api = SemetricAPI(APIKEY)

        # Make the api response
        with patch.object(api.client, 'request', autospec=True) as api_mock:
            api_mock.return_value = []
            api.search(Artist, name="lady gaga")

            api_mock.assert_called_once_with("artist", q="lady gaga")

    def test_get_request_artist(self):

        api = SemetricAPI(APIKEY)

        # Make the api response
        with patch.object(api.client, 'request', autospec=True) as api_mock:
            # Setup the API response
            api_mock.return_value = Artist(apisession=api.client, id="87e0e4ccc7f4415cbd6ba60ad49943b6")
            a = api.get(Artist, id="87e0e4ccc7f4415cbd6ba60ad49943b6")
            assert not api_mock.called, "the API should only be called when accessing a property that isn't cached"

            # The API should only be called if an unknown value is accessed
            a.name
            api_mock.assert_called_once_with("artist/87e0e4ccc7f4415cbd6ba60ad49943b6")

    def test_search_request_not_implemented(self):

        api = SemetricAPI(APIKEY)
        with self.assertRaises(NotImplementedError):
            api.search(Entity, name="foo")

    def test_search_request_entity(self):

        api = SemetricAPI(APIKEY)

        # Make the api response
        with patch.object(api.client, 'request', autospec=True) as api_mock:
            api_mock.return_value = Entity(apisession=api.client, id="87e0e4ccc7f4415cbd6ba60ad49943b6")
            api.get(Entity, id="87e0e4ccc7f4415cbd6ba60ad49943b6")
            assert not api_mock.called, "the API should only be called when accessing a property that isn't cached"

    def test_get_chart_with_country(self):

        api = SemetricAPI(APIKEY)

        # Make the api response
        with patch.object(api.client, 'request', autospec=True) as api_mock:
            api_mock.return_value = Chart(apisession=api.client, id="0695f0bba6144dfaa390e9b9f017ceab", country="CA")
            api.get(Chart, id="0695f0bba6144dfaa390e9b9f017ceab", country="CA")

            api_mock.assert_called_once_with("chart/0695f0bba6144dfaa390e9b9f017ceab", country="CA")

    def test_get_chart_without_country(self):

        api = SemetricAPI(APIKEY)

        # Make the api response
        with patch.object(api.client, 'request', autospec=True) as api_mock:
            api_mock.return_value = Chart(apisession=api.client, id="0695f0bba6144dfaa390e9b9f017ceab")
            api.get(Chart, id="0695f0bba6144dfaa390e9b9f017ceab")

            api_mock.assert_called_once_with("chart/0695f0bba6144dfaa390e9b9f017ceab", country="ALL")

    def test_get_artist_timeseries(self):

        api = SemetricAPI(APIKEY)

        # Make the api response
        with patch.object(api.client, 'request', autospec=True) as api_mock:
            api_mock.return_value = Entity(apisession=api.client, **ARTIST_ADELE)
            artist = api.get(Artist, id=ARTIST_ADELE_ID)

            assert isinstance(artist, Artist)
            assert not api_mock.called, "the API should only be called when accessing a property that isn't cached"

            artist.timeseries("plays/total")
            api_mock.assert_called_once_with("artist/e6ee861435b24f67a6283e00bf820bab/plays/total",
                                             country="ALL",
                                             variant="diff",
                                             processing="processed",
                                             granularity="day")
<|endoftext|>


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

'''
test_xmljson
----------------------------------

Tests for `xmljson` module.
'''

import sys
import unittest

from collections import OrderedDict as od
from lxml.etree import tostring as tostring, fromstring
import lxml.html
import lxml.etree
import xml.etree.cElementTree
import xmljson

# For Python 3, decode byte strings as UTF-8
if sys.version_info[0] == 3:
    def decode(s):
        return s.decode('utf-8')
elif sys.version_info[0] == 2:
    def decode(s):
        return s

class TestXmlJson(unittest.TestCase):

    def setUp(self):
        pass

    def check_etree(self, conv):
        def assertEqual(obj, *strings):
            tree = conv.etree(obj)
            self.assertEqual(len(tree), len(strings))
            for left, right in zip(tree, strings):
                self.assertEqual(decode(tostring(left)), ''.join(right))

        return assertEqual

    def check_data(self, conv):
        def assertEqual(obj, string):
            result_obj = conv.data(fromstring(string))
            self.assertEqual(obj, result_obj)

        return assertEqual

    def test_custom_dict(self):
        'Conversion to dict uses OrderedDict'
        eq = self.check_data(xmljson.BadgerFish(dict_type=od))
        eq({'root': od([('a', {}), ('x', {}), ('b', {}), ('y', {}), ('c', {}), ('z', {})])},
           '<root><x/><y/><c/><z/></root>')

    def test_custom_root(self):
        for etree in (xml.etree.cElementTree, lxml.etree, lxml.html):
            bf = xmljson.BadgerFish(element=etree.Element)
            self.assertEqual(
                decode(etree.tostring(bf.etree({'p': {'$': 1}}, etree.fromstring('')))),
                '
1
')

class TestBadgerFish(TestXmlJson):

    def test_etree(self):
        'BadgerFish conversion from data to etree'
        eq = self.check_etree(xmljson.BadgerFish(dict_type=od))

        # Dicts
        eq({})
        eq({'x': 'a'}, '<x></x>')
        eq({'x': {'@x': 1}}, '<x x="1"/>')
        eq(od([
            ('x', {'@x': 1}),
            ('y', 'z')
        ]), '<x x="1"/>', '<y><z/></y>')

        # Attributes
        eq({'p': {'@id': 1, '$': 'text'}}, '
text
')
        eq({'div': {'@id': 2, '$': 'parent-text', 'p': {'$': 'text'}}},
            '
parent-text
text

')

        # From http://www.sklar.com/badgerfish/
        # Text content of elements goes in the $ property of an object.
        eq({'alice': {'$': 'bob'}}, '<alice>bob</alice>')

        # Nested elements become nested properties
        eq({'alice': od([
            ('bob', {'$': 'charlie'}),
            ('david', {'$': 'edgar'})])},
           '<alice><bob>charlie</bob><david>edgar</david></alice>')

        # Multiple elements at the same level become array elements.
        eq({'alice': {'bob': [{'$': 'charlie'}]}},
           '<alice><bob>charlie</bob></alice>')
        eq({'alice': {'bob': [{'$': 'charlie'}, {'$': 'david'}]}},
           '<alice><bob>charlie</bob><bob>david</bob></alice>')

        # Attributes go in properties whose names begin with @.
        eq({'alice': {'$': 'bob', '@charlie': 'david'}},
            '<alice charlie="david">bob</alice>')

    def test_data(self):
        'BadgerFish conversion from etree to data'
        eq = self.check_data(xmljson.BadgerFish(dict_type=od))

        # Dicts
        eq({'x': {'a': {}}}, '<x></x>')
        eq({'x': {'@x': 1}}, '<x x="1"/>')
        eq({'root': od([('x', {'@x': 1}), ('y', {'z': {}})])},
           '<root><x x="1"/><y><z/></y></root>')

        # Attributes
        eq({'p': {'@id': 1, '$': 'text'}}, '
text
')
        eq({'div': {'@id': 2, '$': 'parent-text', 'p': {'$': 'text'}}},
            '
parent-text
text

')

        # From http://www.sklar.com/badgerfish/
        # Text content of elements goes in the $ property of an object.
        eq({'alice': {'$': 'bob'}}, '<alice>bob</alice>')

        # Nested elements become nested properties
        eq({'alice': od([
            ('bob', {'$': 'charlie'}),
            ('david', {'$': 'edgar'})])},
           '<alice><bob>charlie</bob><david>edgar</david></alice>')

        # Multiple elements at the same level become array elements.
        eq({'alice': {'bob': {'$': 'charlie'}}},
           '<alice><bob>charlie</bob></alice>')
        eq({'alice': {'bob': [{'$': 'charlie'}, {'$': 'david'}]}},
           '<alice><bob>charlie</bob><bob>david</bob></alice>')

        # Attributes go in properties whose names begin with @.
        eq({'alice': {'$': 'bob', '@charlie': 'david'}},
            '<alice charlie="david">bob</alice>')

class TestParker(TestXmlJson):

    def test_etree(self):
        'Parker conversion from data to etree'
        eq = self.check_etree(xmljson.Parker(dict_type=od))

        # Dicts
        eq({})
        eq({'x': 'a'}, '<x>a</x>')
        with self.assertRaises(ValueError):
            eq({'x': {'@x': 1}}, '<x x="1"/>')
        eq(od([
            ('x', 'a'),
            ('y', 'b')
        ]), '<x>a</x>', '<y>b</y>')

        # Nested elements
        eq({'alice': od([
            ('bob', {'charlie': {}}),
            ('david', {'edgar': {}})])},
           '<alice><bob><charlie/></bob><david><edgar/></david></alice>')

        # Multiple elements at the same level become array elements.
        eq({'alice': {'bob': [{'charlie': {}}, {'david': {}}]}},
           '<alice><bob><charlie/></bob><bob><david/></bob></alice>')

    def test_data(self):
        'Parker conversion from etree to data'
        eq = self.check_data(xmljson.Parker(dict_type=od))

        # Dicts
        eq(None, '<x/>')
        eq(od([('x', None), ('y', {'z': None})]),
           '<root><x/><y><z/></y></root>')

        # Nested elements become nested properties
        eq({'bob': None, 'david': None},
           '<root><bob/><david/></root>')

        # https://developer.mozilla.org/en-US/docs/JXON#The_Parker_Convention

        # The root element will be absorbed, for there is only one:
        eq('text', '<root>text</root>')

        # Element names become object properties:
        eq({'name': 'Xml', 'encoding': 'ASCII'},
           '<root><name>Xml</name><encoding>ASCII</encoding></root>')

        # Numbers are recognized (integers and decimals):
        eq({'age': 12, 'height': 1.73},
           '<root><age>12</age><height>1.73</height></root>')

        # Booleans are recognized case insensitive:
        eq({'checked': True, 'answer': False},
           '<root><checked>True</checked><answer>FALSE</answer></root>')

        # Strings are escaped:
        eq('Quote: " New-line:\n',
           '<root>Quote: " New-line:\n</root>')

        # Empty elements will become null:
        eq({'nil': None, 'empty': None},
           '<root><nil/><empty></empty></root>')

        # If all sibling elements have the same name, they become an array
        eq({'bob': [{'charlie': None}, {'david': None}]},
           '<root><bob><charlie/></bob><bob><david/></bob></root>')
        eq({'item': [1, 2, "three"]},
           '<root><item>1</item><item>2</item><item>three</item></root>')
        eq({'item': [1, 2]},
           '<root><item>1</item><item>2</item></root>')

        # Mixed mode text-nodes, comments and attributes get absorbed:
        eq({'element': 1},
           '<root version="1.0">testing<element test="true">1</element></root>')

        # Namespaces get absorbed, and prefixes will just be part of the property name:
        eq({'{http://zanstra.com/ding}dong': 'binnen'},
           '<root xmlns:ding="http://zanstra.com/ding"><ding:dong>binnen</ding:dong></root>')

class TestGData(TestXmlJson):

    def test_etree(self):
        'GData conversion from etree to data'
        eq = self.check_etree(xmljson.GData(dict_type=od))

        # Dicts
        eq({})
        eq({'x': 'a'}, '<x></x>')
        with self.assertRaises(ValueError):
            eq({'x': {'@x': 1}}, '<x x="1"/>')
        eq({'x': {'y': 'a'}}, '<x><y></y></x>')
        eq(od([
            ('x', {}),
            ('y', 'z')
        ]), '<x/>', '<y><z/></y>')

        # Attributes
        eq({'p': {'$t': 'text'}}, '
text
')
        eq({'div': {'$t': 'parent-text', 'p': {'$t': 'text'}}},
            '
parent-text
text

')

        # From http://www.sklar.com/badgerfish/
        # Text content of elements goes in the $ property of an object.
        eq({'alice': {'$t': 'bob'}}, '<alice>bob</alice>')

        # Nested elements become nested properties
        eq({'alice': od([
            ('bob', {'$t': 'charlie'}),
            ('david', {'$t': 'edgar'})])},
           '<alice><bob>charlie</bob><david>edgar</david></alice>')

        # Multiple elements at the same level become array elements.
        eq({'alice': {'bob': [{'$t': 'charlie'}]}},
           '<alice><bob>charlie</bob></alice>')
        eq({'alice': {'bob': [{'$t': 'charlie'}, {'$t': 'david'}]}},
           '<alice><bob>charlie</bob><bob>david</bob></alice>')

        # Attributes go in properties whose names begin with @.
        eq({'alice': {'$t': 'bob'}},
            '<alice>bob</alice>')

    def test_data(self):
        'GData conversion from data to etree'
        eq = self.check_data(xmljson.GData(dict_type=od))

        # Dicts
        eq({'x': {'a': {}}}, '<x></x>')
        eq({'x': {'y': {'z': {}}}}, '<x><y><z/></y></x>')
        eq({'root': od([('x', {}), ('y', {'z': {}})])},
           '<root><x/><y><z/></y></root>')

        # Attributes
        eq({'p': {'$t': 'text'}}, '
text
')
        eq({'div': {'$t': 'parent-text', 'p': {'$t': 'text'}}},
            '
parent-text
text

')

        # From http://www.sklar.com/badgerfish/
        # Text content of elements goes in the $ property of an object.
        eq({'alice': {'$t': 'bob'}}, '<alice>bob</alice>')

        # Nested elements become nested properties
        eq({'alice': od([
            ('bob', {'$t': 'charlie'}),
            ('david', {'$t': 'edgar'})])},
           '<alice><bob>charlie</bob><david>edgar</david></alice>')

        # Multiple elements at the same level become array elements.
        eq({'alice': {'bob': {'$t': 'charlie'}}},
           '<alice><bob>charlie</bob></alice>')
        eq({'alice': {'bob': [{'$t': 'charlie'}, {'$t': 'david'}]}},
           '<alice><bob>charlie</bob><bob>david</bob></alice>')

        # Comments do not matter
        eq({'root': {'$t': 'testing', 'version': 1.0, 'element': {'$t': 1, 'test': True}}},
           '<root version="1.0">testing<element test="true">1</element></root>')

    def test_xml_namespace(self):
        'XML namespaces are not yet implemented'
        with self.assertRaises(ValueError):
            xmljson.badgerfish.etree({'alice': {'@xmlns': {'$': 'http:\/\/some-namespace'}}})
<commit_msg>Use JSON to specify test cases not Python objects<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
test_xmljson
----------------------------------

Tests for `xmljson` module.
'''

import sys
import json
import unittest

from collections import OrderedDict as od
from lxml.etree import tostring as tostring, fromstring
import lxml.html
import lxml.etree
import xml.etree.cElementTree
import xmljson

# For Python 3, decode byte strings as UTF-8
if sys.version_info[0] == 3:
    def decode(s):
        return s.decode('utf-8')
elif sys.version_info[0] == 2:
    def decode(s):
        return s

class TestXmlJson(unittest.TestCase):

    def setUp(self):
        pass

    def check_etree(self, conv):
        def assertEqual(obj, *strings):
            tree = conv.etree(obj)
            self.assertEqual(len(tree), len(strings))
            for left, right in zip(tree, strings):
                self.assertEqual(decode(tostring(left)), ''.join(right))

        return assertEqual

    def check_data(self, conv):
        def assertEqual(jsonstring, xmlstring):
            first = json.loads(jsonstring, object_pairs_hook=od)
            second = conv.data(fromstring(xmlstring))
            self.assertEqual(first, second)

        return assertEqual

    def test_custom_dict(self):
        'Conversion to dict uses OrderedDict'
        eq = self.check_data(xmljson.BadgerFish(dict_type=od))
        eq('{"root": {"a": {}, "x": {}, "b": {}, "y": {}, "c": {}, "z": {}}}',
           '<root><x/><y/><c/><z/></root>')

    def test_custom_root(self):
        for etree in (xml.etree.cElementTree, lxml.etree, lxml.html):
            bf = xmljson.BadgerFish(element=etree.Element)
            self.assertEqual(
                decode(etree.tostring(bf.etree({'p': {'$': 1}}, etree.fromstring('')))),
                '
1
')

class TestBadgerFish(TestXmlJson):

    def test_etree(self):
        'BadgerFish conversion from data to etree'
        eq = self.check_etree(xmljson.BadgerFish(dict_type=od))

        # Dicts
        eq({})
        eq({'x': 'a'}, '<x></x>')
        eq({'x': {'@x': 1}}, '<x x="1"/>')
        eq(od([
            ('x', {'@x': 1}),
            ('y', 'z')
        ]), '<x x="1"/>', '<y><z/></y>')

        # Attributes
        eq({'p': {'@id': 1, '$': 'text'}}, '
text
')
        eq({'div': {'@id': 2, '$': 'parent-text', 'p': {'$': 'text'}}},
            '
parent-text
text

')

        # From http://www.sklar.com/badgerfish/
        # Text content of elements goes in the $ property of an object.
        eq({'alice': {'$': 'bob'}}, '<alice>bob</alice>')

        # Nested elements become nested properties
        eq({'alice': od([
            ('bob', {'$': 'charlie'}),
            ('david', {'$': 'edgar'})])},
           '<alice><bob>charlie</bob><david>edgar</david></alice>')

        # Multiple elements at the same level become array elements.
        eq({'alice': {'bob': [{'$': 'charlie'}]}},
           '<alice><bob>charlie</bob></alice>')
        eq({'alice': {'bob': [{'$': 'charlie'}, {'$': 'david'}]}},
           '<alice><bob>charlie</bob><bob>david</bob></alice>')

        # Attributes go in properties whose names begin with @.
        eq({'alice': {'$': 'bob', '@charlie': 'david'}},
            '<alice charlie="david">bob</alice>')

    def test_data(self):
        'BadgerFish conversion from etree to data'
        eq = self.check_data(xmljson.BadgerFish(dict_type=od))

        # Dicts
        eq('{"x": {"a": {}}}', '<x></x>')
        eq('{"x": {"@x": 1}}', '<x x="1"/>')
        eq('{"root": {"x": {"@x": 1}, "y": {"z": {}}}}',
           '<root><x x="1"/><y><z/></y></root>')

        # Attributes
        eq('{"p": {"@id": 1, "$": "text"}}', '
text
')
        eq('{"div": {"@id": 2, "$": "parent-text", "p": {"$": "text"}}}',
           '
parent-text
text

')

        # From http://www.sklar.com/badgerfish/
        # Text content of elements goes in the $ property of an object.
        eq('{"alice": {"$": "bob"}}', '<alice>bob</alice>')

        # Nested elements become nested properties
        eq('{"alice": {"bob": {"$": "charlie"}, "david": {"$": "edgar"}}}',
           '<alice><bob>charlie</bob><david>edgar</david></alice>')

        # Multiple elements at the same level become array elements.
        eq('{"alice": {"bob": {"$": "charlie"}}}',
           '<alice><bob>charlie</bob></alice>')
        eq('{"alice": {"bob": [{"$": "charlie"}, {"$": "david"}]}}',
           '<alice><bob>charlie</bob><bob>david</bob></alice>')

        # Attributes go in properties whose names begin with @.
        eq('{"alice": {"@charlie": "david", "$": "bob"}}',
            '<alice charlie="david">bob</alice>')

class TestParker(TestXmlJson):

    def test_etree(self):
        'Parker conversion from data to etree'
        eq = self.check_etree(xmljson.Parker(dict_type=od))

        # Dicts
        eq({})
        eq({'x': 'a'}, '<x>a</x>')
        with self.assertRaises(ValueError):
            eq({'x': {'@x': 1}}, '<x x="1"/>')
        eq(od([
            ('x', 'a'),
            ('y', 'b')
        ]), '<x>a</x>', '<y>b</y>')

        # Nested elements
        eq({'alice': od([
            ('bob', {'charlie': {}}),
            ('david', {'edgar': {}})])},
           '<alice><bob><charlie/></bob><david><edgar/></david></alice>')

        # Multiple elements at the same level become array elements.
        eq({'alice': {'bob': [{'charlie': {}}, {'david': {}}]}},
           '<alice><bob><charlie/></bob><bob><david/></bob></alice>')

    def test_data(self):
        'Parker conversion from etree to data'
        eq = self.check_data(xmljson.Parker(dict_type=od))

        # Dicts
        eq('null', '<x/>')
        eq('{"x": null, "y": {"z": null}}',
           '<root><x/><y><z/></y></root>')

        # Nested elements become nested properties
        eq('{"bob": null, "david": null}',
           '<root><bob/><david/></root>')

        # https://developer.mozilla.org/en-US/docs/JXON#The_Parker_Convention

        # The root element will be absorbed, for there is only one:
        eq('"text"', '<root>text</root>')

        # Element names become object properties:
        eq('{"name": "Xml", "encoding": "ASCII"}',
           '<root><name>Xml</name><encoding>ASCII</encoding></root>')

        # Numbers are recognized (integers and decimals):
        eq('{"age": 12, "height": 1.73}',
           '<root><age>12</age><height>1.73</height></root>')

        # Booleans are recognized case insensitive:
        eq('{"checked": true, "answer": false}',
           '<root><checked>True</checked><answer>FALSE</answer></root>')

        # Strings are escaped:
        eq('"Quote: \\" New-line:\\n"',
           '<root>Quote: " New-line:\n</root>')

        # Empty elements will become null:
        eq('{"nil": null, "empty": null}',
           '<root><nil/><empty></empty></root>')

        # If all sibling elements have the same name, they become an array
        eq('{"bob": [{"charlie": null}, {"david": null}]}',
           '<root><bob><charlie/></bob><bob><david/></bob></root>')
        eq('{"item": [1, 2, "three"]}',
           '<root><item>1</item><item>2</item><item>three</item></root>')
        eq('{"item": [1, 2]}',
           '<root><item>1</item><item>2</item></root>')

        # Mixed mode text-nodes, comments and attributes get absorbed:
        eq('{"element": 1}',
           '<root version="1.0">testing<element test="true">1</element></root>')

        # Namespaces get absorbed, and prefixes will just be part of the property name:
        eq('{"{http://zanstra.com/ding}dong": "binnen"}',
           '<root xmlns:ding="http://zanstra.com/ding"><ding:dong>binnen</ding:dong></root>')

class TestGData(TestXmlJson):

    def test_etree(self):
        'GData conversion from etree to data'
        eq = self.check_etree(xmljson.GData(dict_type=od))

        # Dicts
        eq({})
        eq({'x': 'a'}, '<x></x>')
        with self.assertRaises(ValueError):
            eq({'x': {'@x': 1}}, '<x x="1"/>')
        eq({'x': {'y': 'a'}}, '<x><y></y></x>')
        eq(od([
            ('x', {}),
            ('y', 'z')
        ]), '<x/>', '<y><z/></y>')

        # Attributes
        eq({'p': {'$t': 'text'}}, '
text
')
        eq({'div': {'$t': 'parent-text', 'p': {'$t': 'text'}}},
            '
parent-text
text

')

        # From http://www.sklar.com/badgerfish/
        # Text content of elements goes in the $ property of an object.
        eq({'alice': {'$t': 'bob'}}, '<alice>bob</alice>')

        # Nested elements become nested properties
        eq({'alice': od([
            ('bob', {'$t': 'charlie'}),
            ('david', {'$t': 'edgar'})])},
           '<alice><bob>charlie</bob><david>edgar</david></alice>')

        # Multiple elements at the same level become array elements.
        eq({'alice': {'bob': [{'$t': 'charlie'}]}},
           '<alice><bob>charlie</bob></alice>')
        eq({'alice': {'bob': [{'$t': 'charlie'}, {'$t': 'david'}]}},
           '<alice><bob>charlie</bob><bob>david</bob></alice>')

        # Attributes go in properties whose names begin with @.
        eq({'alice': {'$t': 'bob'}},
            '<alice>bob</alice>')

    def test_data(self):
        'GData conversion from data to etree'
        eq = self.check_data(xmljson.GData(dict_type=od))

        # Dicts
        eq('{"x": {"a": {}}}', '<x></x>')
        eq('{"x": {"y": {"z": {}}}}', '<x><y><z/></y></x>')
        eq('{"root": {"x": {}, "y": {"z": {}}}}',
           '<root><x/><y><z/></y></root>')

        # Attributes
        eq('{"p": {"$t": "text"}}', '
text
')
        eq('{"div": {"$t": "parent-text", "p": {"$t": "text"}}}',
            '
parent-text
text

')

        # From http://www.sklar.com/badgerfish/
        # Text content of elements goes in the $ property of an object.
        eq('{"alice": {"$t": "bob"}}', '<alice>bob</alice>')

        # Nested elements become nested properties
        eq('{"alice": {"bob": {"$t": "charlie"}, "david": {"$t": "edgar"}}}',
           '<alice><bob>charlie</bob><david>edgar</david></alice>')

        # Multiple elements at the same level become array elements.
        eq('{"alice": {"bob": {"$t": "charlie"}}}',
           '<alice><bob>charlie</bob></alice>')
        eq('{"alice": {"bob": [{"$t": "charlie"}, {"$t": "david"}]}}',
           '<alice><bob>charlie</bob><bob>david</bob></alice>')

        # Comments do not matter
        eq('{"root": {"version": 1.0, "$t": "testing", "element": {"test": true, "$t": 1}}}',
           '<root version="1.0">testing<element test="true">1</element></root>')

    def test_xml_namespace(self):
        'XML namespaces are not yet implemented'
        with self.assertRaises(ValueError):
            xmljson.badgerfish.etree({'alice': {'@xmlns': {'$': 'http:\/\/some-namespace'}}})
<|endoftext|>


<commit_before>#!/usr/bin/env python2.3
import sys, tempfile, os, shutil
from StringIO import StringIO
import unittest
from logging import getLogger, DEBUG, INFO
#getLogger().setLevel(DEBUG)

sys.path.insert(0, '..')

config_home = tempfile.mktemp()
cache_home = tempfile.mktemp()
os.environ['XDG_CONFIG_HOME'] = config_home
os.environ['XDG_CACHE_HOME'] = cache_home

from zeroinstall.injector import model, basedir, autopolicy, gpg, iface_cache
import data
reload(basedir)

import server

foo_iface_uri = 'http://foo'

class No:
	def readline(self):
		return "n\n"

class TestDownload(unittest.TestCase):
	def setUp(self):
		os.mkdir(config_home, 0700)
		os.mkdir(cache_home, 0700)
		if os.environ.has_key('DISPLAY'):
			del os.environ['DISPLAY']
		self.gnupg_home = tempfile.mktemp()
		os.environ['GNUPGHOME'] = self.gnupg_home
		os.mkdir(self.gnupg_home, 0700)
		stream = tempfile.TemporaryFile()
		stream.write(data.thomas_key)
		stream.seek(0)
		gpg.import_key(stream)
		iface_cache.iface_cache._interfaces = {}

	def tearDown(self):
		shutil.rmtree(config_home)
		shutil.rmtree(cache_home)
		shutil.rmtree(self.gnupg_home)

	def testGetIFace(self):
		old_out = sys.stdout
		try:
			sys.stdout = StringIO()
			child = server.handle_requests('Hello', '6FCF121BE2390E0B.gpg')
			policy = autopolicy.AutoPolicy('http://localhost:8000/Hello', download_only = False)
			assert policy.need_download()
			sys.stdin = No()
			try:
				policy.download_and_execute(['Hello'])
				assert 0
			except model.SafeException, ex:
				assert "Not signed with a trusted key" in str(ex)
			os.waitpid(child, 0)
		finally:
			sys.stdout = old_out

suite = unittest.makeSuite(TestDownload)
if __name__ == '__main__':
	sys.argv.append('-v')
	unittest.main()
<commit_msg>Moved env init into setUp, so it doesn't affect other tests.<commit_after>#!/usr/bin/env python2.3
import sys, tempfile, os, shutil
from StringIO import StringIO
import unittest
from logging import getLogger, DEBUG, INFO
#getLogger().setLevel(DEBUG)

sys.path.insert(0, '..')

from zeroinstall.injector import model, basedir, autopolicy, gpg, iface_cache
import data

import server

foo_iface_uri = 'http://foo'

class No:
	def readline(self):
		return "n\n"

class TestDownload(unittest.TestCase):
	def setUp(self):
		self.config_home = tempfile.mktemp()
		self.cache_home = tempfile.mktemp()
		os.environ['XDG_CONFIG_HOME'] = self.config_home
		os.environ['XDG_CACHE_HOME'] = self.cache_home
		reload(basedir)

		os.mkdir(self.config_home, 0700)
		os.mkdir(self.cache_home, 0700)
		if os.environ.has_key('DISPLAY'):
			del os.environ['DISPLAY']
		self.gnupg_home = tempfile.mktemp()
		os.environ['GNUPGHOME'] = self.gnupg_home
		os.mkdir(self.gnupg_home, 0700)
		stream = tempfile.TemporaryFile()
		stream.write(data.thomas_key)
		stream.seek(0)
		gpg.import_key(stream)
		iface_cache.iface_cache._interfaces = {}

	def tearDown(self):
		shutil.rmtree(self.config_home)
		shutil.rmtree(self.cache_home)
		shutil.rmtree(self.gnupg_home)

	def testGetIFace(self):
		old_out = sys.stdout
		try:
			sys.stdout = StringIO()
			child = server.handle_requests('Hello', '6FCF121BE2390E0B.gpg')
			policy = autopolicy.AutoPolicy('http://localhost:8000/Hello', download_only = False)
			assert policy.need_download()
			sys.stdin = No()
			try:
				policy.download_and_execute(['Hello'])
				assert 0
			except model.SafeException, ex:
				assert "Not signed with a trusted key" in str(ex)
			os.waitpid(child, 0)
		finally:
			sys.stdout = old_out

suite = unittest.makeSuite(TestDownload)
if __name__ == '__main__':
	sys.argv.append('-v')
	unittest.main()
<|endoftext|>


<commit_before>import datetime
import math
import os
import random

import utils
from point import Point

module_logger = utils.get_logger(__name__)

POSSIBLE_MUTATIONS = range(9)
MOVE_POINT, CHANGE_COLOR, CHANGE_OPACITY, MOVE, SCALE, ROTATE, CHANGE_LEVEL, REMOVE_TRIANGLE, ADD_TRIANGLE = POSSIBLE_MUTATIONS
TWO_PI = math.pi * 2
MINIMUM_NUM_TRIANGLES = 10

#######################################################################
def clamp(low, num, high):
    return max(low, min(num, high))

#######################################################################
class Evolver(object):
    ###################################################################
    def __init__(self, source_image, output_folder, num_triangles, save_frequency, save_index=0):
        self.source_image = source_image
        self.best = None
        self.output_folder = output_folder
        self.size = Point(self.source_image.size[0], self.source_image.size[1])
        self.num_triangles = num_triangles
        self.save_frequency = save_frequency
        self.last_saved_time = datetime.datetime(1970, 1, 1)
        self.save_index = save_index
        self.previous_fitness = 0
        self.initial_fitness = 0

    ###################################################################
    def checkpoint(self):
        if (datetime.datetime.now() - self.last_saved_time) >= self.save_frequency:
            self.best.save_file(os.path.join(self.output_folder, "intermediate_%03d.txt" % self.save_index))
            self.best.save_image(os.path.join(self.output_folder, "intermediate_%03d.png" % self.save_index))
            self.save_index += 1
            self.last_saved_time = datetime.datetime.now()

            fitness = self.best.get_fitness(self.source_image)
            diff = self.previous_fitness - fitness
            diff_from_initial = self.initial_fitness - fitness
            module_logger.info("best: %s", len(self.best.triangles))
            module_logger.info("fitness diff: %s %s %s: %s", diff, diff_from_initial, 100.0 * diff_from_initial / fitness, fitness)
            self.previous_fitness = fitness

    ###################################################################
    def randomly_move_triangle(self, tri, variance):
        dx = random.randint(-variance, variance)
        dy = random.randint(-variance, variance)
        tri.move(dx, dy)

    ###################################################################
    def randomly_move_point(self, tri, variance):
        index = random.randint(0, 2)
        dx = random.randint(-variance, variance)
        dy = random.randint(-variance, variance)
        tri.move_point(index, dx, dy)

    ###################################################################
    def randomly_change_color(self, triangle):
        variance = 50
        index = random.randint(0, 2)
        c = list(triangle.color)
        c[index] += random.randint(-variance, variance)
        c[index] = clamp(0, c[index], 255)
        triangle.color = tuple(c)

    ###################################################################
    def randomly_change_opacity(self, triangle):
        variance = 50
        value = triangle.opacity + random.randint(-variance, variance)
        triangle.opacity = clamp(0, value, 255)

    ###################################################################
    def mutate(self, mutation, triangle):
        variance = max(self.size.x, self.size.y)
        if mutation == MOVE:
            self.randomly_move_triangle(triangle, variance)
        elif mutation == SCALE:
            triangle.scale(random.uniform(0, 2))
        elif mutation == ROTATE:
            triangle.rotate(random.uniform(0, TWO_PI))
        elif mutation == MOVE_POINT:
            self.randomly_move_point(triangle, variance)
        elif mutation == CHANGE_COLOR:
            self.randomly_change_color(triangle)
        elif mutation == CHANGE_OPACITY:
            self.randomly_change_opacity(triangle)

    ###################################################################
    def evolve(self, start_sketch):
        self.best = start_sketch
        self.previous_fitness = self.best.get_fitness(self.source_image)
        self.initial_fitness = self.previous_fitness
        new_sketch = start_sketch
        count = 0
        while True:
            self.checkpoint()
            if self.best.get_fitness(self.source_image) == 0:
                break
            count += 1
            new_sketch = self.best.clone()
            index = random.randint(0, len(new_sketch.triangles) - 1)
            triangle = new_sketch.triangles[index]
            mutation = random.choice(POSSIBLE_MUTATIONS)
            if mutation == REMOVE_TRIANGLE:
                if len(new_sketch.triangles) > MINIMUM_NUM_TRIANGLES:
                    del new_sketch.triangles[index]
            if mutation == ADD_TRIANGLE:
                if len(new_sketch.triangles) < self.num_triangles:
                    triangle = utils.create_random_triangles(self.size, 1)[0]
                    new_sketch.triangles.append(triangle)
            if mutation == CHANGE_LEVEL:
                new_index = random.randint(0, len(new_sketch.triangles) - 1)
                del new_sketch.triangles[index]
                new_sketch.triangles.insert(new_index, triangle)
            else:
                self.mutate(mutation, triangle)

            if new_sketch.get_fitness(self.source_image) <= self.best.get_fitness(self.source_image):
                self.best = new_sketch
        module_logger.info("evolved: %s", len(new_sketch.triangles))
        module_logger.info("%s %s", self.best.get_fitness(self.source_image), start_sketch.get_fitness(self.source_image))
        module_logger.info("evolution count: %s", count)
        return self.best
<commit_msg>Added evolution count to output<commit_after>import datetime
import math
import os
import random

import utils
from point import Point

module_logger = utils.get_logger(__name__)

POSSIBLE_MUTATIONS = range(9)
MOVE_POINT, CHANGE_COLOR, CHANGE_OPACITY, MOVE, SCALE, ROTATE, CHANGE_LEVEL, REMOVE_TRIANGLE, ADD_TRIANGLE = POSSIBLE_MUTATIONS
TWO_PI = math.pi * 2
MINIMUM_NUM_TRIANGLES = 10

#######################################################################
def clamp(low, num, high):
    return max(low, min(num, high))

#######################################################################
class Evolver(object):
    ###################################################################
    def __init__(self, source_image, output_folder, num_triangles, save_frequency, save_index=0):
        self.source_image = source_image
        self.best = None
        self.output_folder = output_folder
        self.size = Point(self.source_image.size[0], self.source_image.size[1])
        self.num_triangles = num_triangles
        self.save_frequency = save_frequency
        self.last_saved_time = datetime.datetime(1970, 1, 1)
        self.save_index = save_index
        self.previous_fitness = 0
        self.initial_fitness = 0

    ###################################################################
    def checkpoint(self, evolution_count):
        if (datetime.datetime.now() - self.last_saved_time) >= self.save_frequency:
            self.best.save_file(os.path.join(self.output_folder, "intermediate_%03d.txt" % self.save_index))
            self.best.save_image(os.path.join(self.output_folder, "intermediate_%03d.png" % self.save_index))
            self.save_index += 1
            self.last_saved_time = datetime.datetime.now()

            fitness = self.best.get_fitness(self.source_image)
            diff = self.previous_fitness - fitness
            diff_from_initial = self.initial_fitness - fitness
            module_logger.info("evolution count: %s", evolution_count)
            module_logger.info("best: %s", len(self.best.triangles))
            module_logger.info("fitness diff: %s %s %s: %s", diff, diff_from_initial, 100.0 * diff_from_initial / fitness, fitness)
            self.previous_fitness = fitness

    ###################################################################
    def randomly_move_triangle(self, tri, variance):
        dx = random.randint(-variance, variance)
        dy = random.randint(-variance, variance)
        tri.move(dx, dy)

    ###################################################################
    def randomly_move_point(self, tri, variance):
        index = random.randint(0, 2)
        dx = random.randint(-variance, variance)
        dy = random.randint(-variance, variance)
        tri.move_point(index, dx, dy)

    ###################################################################
    def randomly_change_color(self, triangle):
        variance = 50
        index = random.randint(0, 2)
        c = list(triangle.color)
        c[index] += random.randint(-variance, variance)
        c[index] = clamp(0, c[index], 255)
        triangle.color = tuple(c)

    ###################################################################
    def randomly_change_opacity(self, triangle):
        variance = 50
        value = triangle.opacity + random.randint(-variance, variance)
        triangle.opacity = clamp(0, value, 255)

    ###################################################################
    def mutate(self, mutation, triangle):
        variance = max(self.size.x, self.size.y)
        if mutation == MOVE:
            self.randomly_move_triangle(triangle, variance)
        elif mutation == SCALE:
            triangle.scale(random.uniform(0, 2))
        elif mutation == ROTATE:
            triangle.rotate(random.uniform(0, TWO_PI))
        elif mutation == MOVE_POINT:
            self.randomly_move_point(triangle, variance)
        elif mutation == CHANGE_COLOR:
            self.randomly_change_color(triangle)
        elif mutation == CHANGE_OPACITY:
            self.randomly_change_opacity(triangle)

    ###################################################################
    def evolve(self, start_sketch):
        self.best = start_sketch
        self.previous_fitness = self.best.get_fitness(self.source_image)
        self.initial_fitness = self.previous_fitness
        new_sketch = start_sketch
        count = 0
        while True:
            self.checkpoint(count)
            if self.best.get_fitness(self.source_image) == 0:
                break
            count += 1
            new_sketch = self.best.clone()
            index = random.randint(0, len(new_sketch.triangles) - 1)
            triangle = new_sketch.triangles[index]
            mutation = random.choice(POSSIBLE_MUTATIONS)
            if mutation == REMOVE_TRIANGLE:
                if len(new_sketch.triangles) > MINIMUM_NUM_TRIANGLES:
                    del new_sketch.triangles[index]
            if mutation == ADD_TRIANGLE:
                if len(new_sketch.triangles) < self.num_triangles:
                    triangle = utils.create_random_triangles(self.size, 1)[0]
                    new_sketch.triangles.append(triangle)
            if mutation == CHANGE_LEVEL:
                new_index = random.randint(0, len(new_sketch.triangles) - 1)
                del new_sketch.triangles[index]
                new_sketch.triangles.insert(new_index, triangle)
            else:
                self.mutate(mutation, triangle)

            if new_sketch.get_fitness(self.source_image) <= self.best.get_fitness(self.source_image):
                self.best = new_sketch
        module_logger.info("evolved: %s", len(new_sketch.triangles))
        module_logger.info("%s %s", self.best.get_fitness(self.source_image), start_sketch.get_fitness(self.source_image))
        module_logger.info("evolution count: %s", count)
        return self.best
<|endoftext|>


<commit_before>import numpy as np

from .util      import diagonal_dot, unitize
from .points    import point_plane_distance
from .constants import tol

def cross(triangles):
    '''
    Returns the cross product of two edges from input triangles

    triangles: vertices of triangles (n,3,3)
    returns:   cross product of two edge vectors (n,3)
    '''
    vectors = np.diff(triangles, axis=1)
    crosses = np.cross(vectors[:,0], vectors[:,1])
    return crosses

def area(triangles=None, crosses=None, sum=True):
    '''
    Calculates the sum area of input triangles

    Arguments
    ----------
    triangles: vertices of triangles (n,3,3)
    sum:       bool, return summed area or individual triangle area

    Returns
    ----------
    area:
        if sum: float, sum area of triangles
        else:   (n,) float, individual area of triangles
    '''
    if crosses is None:
        crosses = cross(triangles)
    area    = (np.sum(crosses**2, axis=1)**.5)*.5
    if sum:
        return np.sum(area)
    return area

def normals(triangles=None, crosses=None):
    '''
    Calculates the normals of input triangles

    triangles: vertices of triangles, (n,3,3)
    returns:   normal vectors, (n,3)
    '''
    if crosses is None:
        crosses = cross(triangles)
    normals, valid = unitize(crosses, check_valid=True)
    return normals, valid

def all_coplanar(triangles):
    '''
    Given a list of triangles, return True if they are all coplanar, and False if not.

    triangles: vertices of triangles, (n,3,3)
    returns:   all_coplanar, bool
    '''
    test_normal  = normals(triangles)[0]
    test_vertex  = triangles[0][0]
    distances    = point_plane_distance(points       = triangles[1:].reshape((-1,3)),
                                        plane_normal = test_normal,
                                        plane_origin = test_vertex)
    all_coplanar = np.all(np.abs(distances) < tol.zero)
    return all_coplanar

def any_coplanar(triangles):
    '''
    Given a list of triangles, if the FIRST triangle is coplanar with ANY
    of the following triangles, return True.
    Otherwise, return False.
    '''
    test_normal  = normals(triangles)[0]
    test_vertex  = triangles[0][0]
    distances    = point_plane_distance(points       = triangles[1:].reshape((-1,3)),
                                        plane_normal = test_normal,
                                        plane_origin = test_vertex)
    any_coplanar = np.any(np.all(np.abs(distances.reshape((-1,3)) < tol.zero), axis=1))
    return any_coplanar

def mass_properties(triangles, crosses=None, density = 1.0, skip_inertia=False):
    '''
    Calculate the mass properties of a group of triangles.

    Implemented from:
    http://www.geometrictools.com/Documentation/PolyhedralMassProperties.pdf

    Arguments
    ----------
    '''
    if crosses is None:
        crosses = cross(triangles)
    surface_area = np.sum(np.sum(crosses**2, axis=1)**.5)*.5

    # these are the subexpressions of the integral
    f1 = triangles.sum(axis=1)

    # triangles[:,0,:] will give rows like [[x0, y0, z0], ...] (the first vertex of every triangle)
    # triangles[:,:,0] will give rows like [[x0, x1, x2], ...] (the x coordinates of every triangle)
    f2 = (triangles[:,0,:]**2 +
          triangles[:,1,:]**2 +
          triangles[:,0,:]*triangles[:,1,:] +
          triangles[:,2,:]*f1)

    f3 = ((triangles[:,0,:]**3) +
          (triangles[:,0,:]**2) * (triangles[:,1,:]) +
          (triangles[:,0,:])    * (triangles[:,1,:]**2) +
          (triangles[:,1,:]**3) +
          (triangles[:,2,:]*f2))

    g0 = (f2 + (triangles[:,0,:] + f1)*triangles[:,0,:])
    g1 = (f2 + (triangles[:,1,:] + f1)*triangles[:,1,:])
    g2 = (f2 + (triangles[:,2,:] + f1)*triangles[:,2,:])

    integral      = np.zeros((10, len(f1)))
    integral[0]   = crosses[:,0] * f1[:,0]
    integral[1:4] = (crosses * f2).T
    integral[4:7] = (crosses * f3).T

    for i in range(3):
        triangle_i    = np.mod(i+1, 3)
        integral[i+7] = crosses[:,i] * ((triangles[:,0, triangle_i] * g0[:,i]) +
                                        (triangles[:,1, triangle_i] * g1[:,i]) +
                                        (triangles[:,2, triangle_i] * g2[:,i]))

    coefficents = 1.0 / np.array([6,24,24,24,60,60,60,120,120,120])
    integrated  = integral.sum(axis=1) * coefficents

    volume      = integrated[0]
    center_mass = integrated[1:4] / volume

    result = {'density'      : density,
              'surface_area' : surface_area,
              'volume'       : volume,
              'mass'         : density * volume,
              'center_mass'  : center_mass.tolist()}

    if skip_inertia:
        return result

    inertia = np.zeros((3,3))
    inertia[0,0] = integrated[5] + integrated[6] - (volume * (center_mass[[1,2]]**2).sum())
    inertia[1,1] = integrated[4] + integrated[6] - (volume * (center_mass[[0,2]]**2).sum())
    inertia[2,2] = integrated[4] + integrated[5] - (volume * (center_mass[[0,1]]**2).sum())
    inertia[0,1] = (integrated[7] - (volume * np.product(center_mass[[0,1]])))
    inertia[1,2] = (integrated[8] - (volume * np.product(center_mass[[1,2]])))
    inertia[0,2] = (integrated[9] - (volume * np.product(center_mass[[0,2]])))
    inertia[2,0] = inertia[0,2]
    inertia[2,1] = inertia[1,2]
    inertia[1,0] = inertia[0,1]
    inertia *= density

    result['inertia'] = inertia.tolist()

    return result

def windings_aligned(triangles, normals_compare):
    '''
    Given a set of triangles and a set of normals determine if the two are aligned

    Arguments
    ----------
    triangles: (n,3,3) set of vertex locations
    normals_compare: (n,3) set of normals

    Returns
    ----------
    aligned: (n) bool list, are normals aligned with triangles
    '''

    calculated, valid = normals(triangles)
    difference = diagonal_dot(calculated, normals_compare[valid])
    result = np.zeros(len(triangles), dtype=np.bool)
    result[valid] = difference > 0.0
    return result

def bounds_tree(triangles):
    '''
    Given a set of triangles, create an r-tree for broad- phase
    collision detection

    Arguments
    ---------
    triangles: (n, 3, 3) list of vertices

    Returns
    ---------
    tree: Rtree object
    '''
    from rtree import index

    # the property object required to get a 3D r-tree index
    properties = index.Property()
    properties.dimension = 3
    # the (n,6) interleaved bounding box for every triangle
    tri_bounds = np.column_stack((triangles.min(axis=1), triangles.max(axis=1)))

    # stream loading wasn't getting proper index
    tree = index.Index(properties=properties)
    for i, bounds in enumerate(tri_bounds):
        tree.insert(i, bounds)
    return tree

def nondegenerate(triangles):
    '''
    Find all triangles which have nonzero area.
    Degenerate triangles are divided into two cases:
    1) Two of the three vertices are colocated
    2) All three vertices are unique but colinear

    Arguments
    ----------
    triangles: (n, 3, 3) float, set of triangles

    Returns
    ----------
    nondegenerate: (n,) bool array of triangles that have area
    '''
    a, valid_a = unitize(triangles[:,1] - triangles[:,0], check_valid=True)
    b, valid_b = unitize(triangles[:,2] - triangles[:,0], check_valid=True)

    diff = np.zeros((len(triangles), 3))
    diff[valid_a]  = a
    diff[valid_b] -= b

    ok = (np.abs(diff) > tol.merge).any(axis=1)
    ok[np.logical_not(valid_a)] = False
    ok[np.logical_not(valid_b)] = False

    return ok
<commit_msg>added barycentric_to_cartesian<commit_after>import numpy as np

from .util      import diagonal_dot, unitize, is_shape
from .points    import point_plane_distance
from .constants import tol

def cross(triangles):
    '''
    Returns the cross product of two edges from input triangles

    triangles: vertices of triangles (n,3,3)
    returns:   cross product of two edge vectors (n,3)
    '''
    vectors = np.diff(triangles, axis=1)
    crosses = np.cross(vectors[:,0], vectors[:,1])
    return crosses

def area(triangles=None, crosses=None, sum=True):
    '''
    Calculates the sum area of input triangles

    Arguments
    ----------
    triangles: vertices of triangles (n,3,3)
    sum:       bool, return summed area or individual triangle area

    Returns
    ----------
    area:
        if sum: float, sum area of triangles
        else:   (n,) float, individual area of triangles
    '''
    if crosses is None:
        crosses = cross(triangles)
    area    = (np.sum(crosses**2, axis=1)**.5)*.5
    if sum:
        return np.sum(area)
    return area

def normals(triangles=None, crosses=None):
    '''
    Calculates the normals of input triangles

    triangles: vertices of triangles, (n,3,3)
    returns:   normal vectors, (n,3)
    '''
    if crosses is None:
        crosses = cross(triangles)
    normals, valid = unitize(crosses, check_valid=True)
    return normals, valid

def all_coplanar(triangles):
    '''
    Given a list of triangles, return True if they are all coplanar, and False if not.

    triangles: vertices of triangles, (n,3,3)
    returns:   all_coplanar, bool
    '''
    test_normal  = normals(triangles)[0]
    test_vertex  = triangles[0][0]
    distances    = point_plane_distance(points       = triangles[1:].reshape((-1,3)),
                                        plane_normal = test_normal,
                                        plane_origin = test_vertex)
    all_coplanar = np.all(np.abs(distances) < tol.zero)
    return all_coplanar

def any_coplanar(triangles):
    '''
    Given a list of triangles, if the FIRST triangle is coplanar with ANY
    of the following triangles, return True.
    Otherwise, return False.
    '''
    test_normal  = normals(triangles)[0]
    test_vertex  = triangles[0][0]
    distances    = point_plane_distance(points       = triangles[1:].reshape((-1,3)),
                                        plane_normal = test_normal,
                                        plane_origin = test_vertex)
    any_coplanar = np.any(np.all(np.abs(distances.reshape((-1,3)) < tol.zero), axis=1))
    return any_coplanar

def mass_properties(triangles, crosses=None, density = 1.0, skip_inertia=False):
    '''
    Calculate the mass properties of a group of triangles.

    Implemented from:
    http://www.geometrictools.com/Documentation/PolyhedralMassProperties.pdf

    Arguments
    ----------
    '''
    if crosses is None:
        crosses = cross(triangles)
    surface_area = np.sum(np.sum(crosses**2, axis=1)**.5)*.5

    # these are the subexpressions of the integral
    f1 = triangles.sum(axis=1)

    # triangles[:,0,:] will give rows like [[x0, y0, z0], ...] (the first vertex of every triangle)
    # triangles[:,:,0] will give rows like [[x0, x1, x2], ...] (the x coordinates of every triangle)
    f2 = (triangles[:,0,:]**2 +
          triangles[:,1,:]**2 +
          triangles[:,0,:]*triangles[:,1,:] +
          triangles[:,2,:]*f1)

    f3 = ((triangles[:,0,:]**3) +
          (triangles[:,0,:]**2) * (triangles[:,1,:]) +
          (triangles[:,0,:])    * (triangles[:,1,:]**2) +
          (triangles[:,1,:]**3) +
          (triangles[:,2,:]*f2))

    g0 = (f2 + (triangles[:,0,:] + f1)*triangles[:,0,:])
    g1 = (f2 + (triangles[:,1,:] + f1)*triangles[:,1,:])
    g2 = (f2 + (triangles[:,2,:] + f1)*triangles[:,2,:])

    integral      = np.zeros((10, len(f1)))
    integral[0]   = crosses[:,0] * f1[:,0]
    integral[1:4] = (crosses * f2).T
    integral[4:7] = (crosses * f3).T

    for i in range(3):
        triangle_i    = np.mod(i+1, 3)
        integral[i+7] = crosses[:,i] * ((triangles[:,0, triangle_i] * g0[:,i]) +
                                        (triangles[:,1, triangle_i] * g1[:,i]) +
                                        (triangles[:,2, triangle_i] * g2[:,i]))

    coefficents = 1.0 / np.array([6,24,24,24,60,60,60,120,120,120])
    integrated  = integral.sum(axis=1) * coefficents

    volume      = integrated[0]
    center_mass = integrated[1:4] / volume

    result = {'density'      : density,
              'surface_area' : surface_area,
              'volume'       : volume,
              'mass'         : density * volume,
              'center_mass'  : center_mass.tolist()}

    if skip_inertia:
        return result

    inertia = np.zeros((3,3))
    inertia[0,0] = integrated[5] + integrated[6] - (volume * (center_mass[[1,2]]**2).sum())
    inertia[1,1] = integrated[4] + integrated[6] - (volume * (center_mass[[0,2]]**2).sum())
    inertia[2,2] = integrated[4] + integrated[5] - (volume * (center_mass[[0,1]]**2).sum())
    inertia[0,1] = (integrated[7] - (volume * np.product(center_mass[[0,1]])))
    inertia[1,2] = (integrated[8] - (volume * np.product(center_mass[[1,2]])))
    inertia[0,2] = (integrated[9] - (volume * np.product(center_mass[[0,2]])))
    inertia[2,0] = inertia[0,2]
    inertia[2,1] = inertia[1,2]
    inertia[1,0] = inertia[0,1]
    inertia *= density

    result['inertia'] = inertia.tolist()

    return result

def windings_aligned(triangles, normals_compare):
    '''
    Given a set of triangles and a set of normals determine if the two are aligned

    Arguments
    ----------
    triangles: (n,3,3) set of vertex locations
    normals_compare: (n,3) set of normals

    Returns
    ----------
    aligned: (n) bool list, are normals aligned with triangles
    '''

    calculated, valid = normals(triangles)
    difference = diagonal_dot(calculated, normals_compare[valid])
    result = np.zeros(len(triangles), dtype=np.bool)
    result[valid] = difference > 0.0
    return result

def bounds_tree(triangles):
    '''
    Given a set of triangles, create an r-tree for broad- phase
    collision detection

    Arguments
    ---------
    triangles: (n, 3, 3) list of vertices

    Returns
    ---------
    tree: Rtree object
    '''
    from rtree import index

    # the property object required to get a 3D r-tree index
    properties = index.Property()
    properties.dimension = 3
    # the (n,6) interleaved bounding box for every triangle
    tri_bounds = np.column_stack((triangles.min(axis=1), triangles.max(axis=1)))

    # stream loading wasn't getting proper index
    tree = index.Index(properties=properties)
    for i, bounds in enumerate(tri_bounds):
        tree.insert(i, bounds)
    return tree

def nondegenerate(triangles):
    '''
    Find all triangles which have nonzero area.
    Degenerate triangles are divided into two cases:
    1) Two of the three vertices are colocated
    2) All three vertices are unique but colinear

    Arguments
    ----------
    triangles: (n, 3, 3) float, set of triangles

    Returns
    ----------
    nondegenerate: (n,) bool array of triangles that have area
    '''
    a, valid_a = unitize(triangles[:,1] - triangles[:,0], check_valid=True)
    b, valid_b = unitize(triangles[:,2] - triangles[:,0], check_valid=True)

    diff = np.zeros((len(triangles), 3))
    diff[valid_a]  = a
    diff[valid_b] -= b

    ok = (np.abs(diff) > tol.merge).any(axis=1)
    ok[np.logical_not(valid_a)] = False
    ok[np.logical_not(valid_b)] = False

    return ok

def barycentric_to_cartesian(triangles, barycentric, barycentric_index):
    '''
    Convert a set of barycentric coordinates on a list of triangles to cartesian points

    Arguments
    ----------
    triangles:         (n,3,3) float, set of triangles in space
    barycentric:       (m,2) float, barycentric coordinates
    barycentric_index: (m,) int, which index of triangles is each barycentric coordinate for

    Returns
    -----------
    points: (m,3) float, points in space
    '''
    barycentric = np.asanyarray(barycentric, dtype=np.float64)
    barycentric_index = np.asanyarray(barycentric_index, dtype=np.int64)
    triangles = np.asanyarray(triangles, dtype=np.float64)

    if is_shape(barycentric, (-1,2)):
        barycentric  = np.column_stack((barycentric, 1.0-barycentric.sum(axis=1)))
    elif not is_shape(barycentric, (-1,3)):
        raise ValueError('Barycentric shape incorrect!')

    if (barycentric < -tol.merge).any():
        raise ValueError('Barycentric coordinates have negative terms!')

    barycentric /= barycentric.sum(axis=1).reshape((-1,1))
    points = (triangles[barycentric_index]  * barycentric.reshape((-1,3,1))).sum(axis=1)

    return points
<|endoftext|>


<commit_before>
class Interpreter(object):

    def __init__(self):
        self.initialize()

    def initialize(self):
        self.stack = []
        self.altstack = []
        self.pc = 0
        self.pbegincodehash = 0
        self.nop_count = 0
        self.vf_exec = []
        self.errstr = ''
        self.flags = 0

    """
    Verifies a Script by executing it and returns true if it is valid.
    This function needs to be provided with the scriptSig and the scriptPubkey
    separately.

    :param script_sig: the script's first part (corresponding to the tx input)
    :param script_pubkey: the script's last part (corresponding to the tx output)
    :param tx: the transaction containing the script_sig in one input (used to
        check signature validity for some opcodes like OP_CHECKSIG)
    :param nin: index of the transaction input containing the scriptSig verified.
    :param flags: evaluation flags. See Interpreter.SCRIPT_* constants

    Translated from bitcoind's VerifyScript
    """
    def verify(self, script_sig, script_pubkey, tx, nin, flags):
        pass
<commit_msg>add interpreter flags<commit_after>from bitforge import Transaction
from bitforge.tools import Buffer

class Interpreter(object):

    def __init__(self):
        self.initialize()

    def initialize(self):
        self.stack = []
        self.altstack = []
        self.pc = 0
        self.pbegincodehash = 0
        self.nop_count = 0
        self.vf_exec = []
        self.errstr = ''
        self.flags = 0

    """
    Verifies a Script by executing it and returns true if it is valid.
    This function needs to be provided with the scriptSig and the scriptPubkey
    separately.

    :param script_sig: the script's first part (corresponding to the tx input)
    :param script_pubkey: the script's last part (corresponding to the tx output)
    :param tx: the transaction containing the script_sig in one input (used to
        check signature validity for some opcodes like OP_CHECKSIG)
    :param nin: index of the transaction input containing the scriptSig verified.
    :param flags: evaluation flags. See Interpreter.SCRIPT_* constants

    Translated from bitcoind's VerifyScript
    """
    def verify(self, script_sig, script_pubkey, tx, nin, flags):
        self.script = script_sig
        self.tx = tx or Transaction([], [])
        self.nin = nin or 0
        self.flags = flags or 0

        return False

    # Interpreter constants
    true = Buffer([1])
    false = Buffer([])

    MAX_SCRIPT_ELEMENT_SIZE = 520
    LOCKTIME_THRESHOLD = 500000000

    # Flags taken from bitcoind
    # bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
    SCRIPT_VERIFY_NONE = 0

    # Evaluate P2SH subscripts (softfork safe, BIP16).
    SCRIPT_VERIFY_P2SH = 1 << 0

    # Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure.
    # Passing a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) to checksig causes that pubkey to be
    # skipped (not softfork safe: this flag can widen the validity of OP_CHECKSIG OP_NOT).
    SCRIPT_VERIFY_STRICTENC = 1 << 1

    # Passing a non-strict-DER signature to a checksig operation causes script failure (softfork safe, BIP62 rule 1)
    SCRIPT_VERIFY_DERSIG = 1 << 2

    # Passing a non-strict-DER signature or one with S > order/2 to a checksig operation causes script failure
    # (softfork safe, BIP62 rule 5).
    SCRIPT_VERIFY_LOW_S = 1 << 3

    # Verify dummy stack item consumed by CHECKMULTISIG is of zero-length (softfork safe, BIP62 rule 7).
    SCRIPT_VERIFY_NULLDUMMY = 1 << 4

    # Using a non-push operator in the scriptSig causes script failure (softfork safe, BIP62 rule 2).
    SCRIPT_VERIFY_SIGPUSHONLY = 1 << 5

    # Require minimal encodings for all push operations (OP_0... OP_16, OP_1NEGATE where possible, direct
    # pushes up to 75 bytes, OP_PUSHDATA up to 255 bytes, OP_PUSHDATA2 for anything larger). Evaluating
    # any other push causes the script to fail (BIP62 rule 3).
    # In addition, whenever a stack element is interpreted as a number, it must be of minimal length (BIP62 rule 4).
    # (softfork safe)
    SCRIPT_VERIFY_MINIMALDATA = 1 << 6

    # Discourage use of NOPs reserved for upgrades (NOP1-10)
    #
    # Provided so that nodes can avoid accepting or mining transactions
    # containing executed NOP's whose meaning may change after a soft-fork,
    # thus rendering the script invalid; with this flag set executing
    # discouraged NOPs fails the script. This verification flag will never be
    # a mandatory flag applied to scripts in a block. NOPs that are not
    # executed, e.g.  within an unexecuted IF ENDIF block, are *not* rejected.
    SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = 1 << 7

    # CLTV See BIP65 for details.
    SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = 1 << 9
<|endoftext|>


<commit_before># standard modules
import StringIO
from unittest import TestCase

# custom modules
from iago.DatabaseProvider import DB

class TestDB(TestCase):
	def test_read_empty(self):
		s = StringIO.StringIO('{}')
		d = DB()
		try:
			d.read(s)
		except KeyError:
			self.fail('DB cannot handle empty JSON files.')
<commit_msg>Fix test to specify file format<commit_after># standard modules
import StringIO
from unittest import TestCase

# custom modules
from iago.DatabaseProvider import DB

class TestDB(TestCase):
	def test_read_empty(self):
		s = StringIO.StringIO('{}')
		d = DB()
		try:
			d.read(s, format='json')
		except KeyError:
			self.fail('DB cannot handle empty JSON files.')
<|endoftext|>


<commit_before>#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""
This script runs every build as the first hook (See DEPS). If it detects that
the build should be clobbered, it will delete the contents of the build
directory.

A landmine is tripped when a builder checks out a different revision, and the
diff between the new landmines and the old ones is non-null. At this point, the
build is clobbered.
"""

import difflib
import errno
import gyp_environment
import logging
import optparse
import os
import shutil
import sys
import subprocess
import time

import landmine_utils

SRC_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))

def get_build_dir(build_tool, is_iphone=False):
  """
  Returns output directory absolute path dependent on build and targets.
  Examples:
    r'c:\b\build\slave\win\build\src\out'
    '/mnt/data/b/build/slave/linux/build/src/out'
    '/b/build/slave/ios_rel_device/build/src/xcodebuild'

  Keep this function in sync with tools/build/scripts/slave/compile.py
  """
  ret = None
  if build_tool == 'xcode':
    ret = os.path.join(SRC_DIR, 'xcodebuild')
  elif build_tool in ['make', 'ninja', 'ninja-ios']:  # TODO: Remove ninja-ios.
    if ('CHROMIUM_OUT_DIR' not in os.environ and
        'output_dir' in landmine_utils.gyp_generator_flags()):
      output_dir = landmine_utils.gyp_generator_flags()['output_dir']
    else:
      output_dir = os.environ.get('CHROMIUM_OUT_DIR', 'out')
    ret = os.path.join(SRC_DIR, output_dir)
  else:
    raise NotImplementedError('Unexpected GYP_GENERATORS (%s)' % build_tool)
  return os.path.abspath(ret)

def extract_gn_build_commands(build_ninja_file):
  """Extracts from a build.ninja the commands to run GN.

  The commands to run GN are the gn rule and build.ninja build step at the
  top of the build.ninja file. We want to keep these when deleting GN builds
  since we want to preserve the command-line flags to GN.

  On error, returns the empty string."""
  result = ""
  with open(build_ninja_file, 'r') as f:
    # Read until the second blank line. The first thing GN writes to the file
    # is the "rule gn" and the second is the section for "build build.ninja",
    # separated by blank lines.
    num_blank_lines = 0
    while num_blank_lines < 2:
      line = f.readline()
      if len(line) == 0:
        return ''  # Unexpected EOF.
      result += line
      if line[0] == '\n':
        num_blank_lines = num_blank_lines + 1
  return result

def delete_build_dir(build_dir):
  # GN writes a build.ninja.d file. Note that not all GN builds have args.gn.
  build_ninja_d_file = os.path.join(build_dir, 'build.ninja.d')
  if not os.path.exists(build_ninja_d_file):
    shutil.rmtree(build_dir)
    return

  # GN builds aren't automatically regenerated when you sync. To avoid
  # messing with the GN workflow, erase everything but the args file, and
  # write a dummy build.ninja file that will automatically rerun GN the next
  # time Ninja is run.
  build_ninja_file = os.path.join(build_dir, 'build.ninja')
  build_commands = extract_gn_build_commands(build_ninja_file)

  try:
    gn_args_file = os.path.join(build_dir, 'args.gn')
    with open(gn_args_file, 'r') as f:
      args_contents = f.read()
  except IOError:
    args_contents = ''

  shutil.rmtree(build_dir)

  # Put back the args file (if any).
  os.mkdir(build_dir)
  if args_contents != '':
    with open(gn_args_file, 'w') as f:
      f.write(args_contents)

  # Write the build.ninja file sufficiently to regenerate itself.
  with open(os.path.join(build_dir, 'build.ninja'), 'w') as f:
    if build_commands != '':
      f.write(build_commands)
    else:
      # Couldn't parse the build.ninja file, write a default thing.
      f.write('''rule gn
command = gn -q gen //out/%s/
description = Regenerating ninja files

build build.ninja: gn
generator = 1
depfile = build.ninja.d
''' % (os.path.split(build_dir)[1]))

  # Write a .d file for the build which references a nonexistant file. This
  # will make Ninja always mark the build as dirty.
  with open(build_ninja_d_file, 'w') as f:
    f.write('build.ninja: nonexistant_file.gn\n')

def clobber_if_necessary(new_landmines):
  """Does the work of setting, planting, and triggering landmines."""
  out_dir = get_build_dir(landmine_utils.builder())
  landmines_path = os.path.normpath(os.path.join(out_dir, '..', '.landmines'))
  try:
    os.makedirs(out_dir)
  except OSError as e:
    if e.errno == errno.EEXIST:
      pass

  if os.path.exists(landmines_path):
    with open(landmines_path, 'r') as f:
      old_landmines = f.readlines()
    if old_landmines != new_landmines:
      old_date = time.ctime(os.stat(landmines_path).st_ctime)
      diff = difflib.unified_diff(old_landmines, new_landmines,
          fromfile='old_landmines', tofile='new_landmines',
          fromfiledate=old_date, tofiledate=time.ctime(), n=0)
      sys.stdout.write('Clobbering due to:\n')
      sys.stdout.writelines(diff)

      # Clobber contents of build directory but not directory itself: some
      # checkouts have the build directory mounted.
      for f in os.listdir(out_dir):
        path = os.path.join(out_dir, f)
        if os.path.isfile(path):
          os.unlink(path)
        elif os.path.isdir(path):
          delete_build_dir(path)

  # Save current set of landmines for next time.
  with open(landmines_path, 'w') as f:
    f.writelines(new_landmines)

def process_options():
  """Returns a list of landmine emitting scripts."""
  parser = optparse.OptionParser()
  parser.add_option(
      '-s', '--landmine-scripts', action='append',
      default=[os.path.join(SRC_DIR, 'build', 'get_landmines.py')],
      help='Path to the script which emits landmines to stdout. The target '
           'is passed to this script via option -t. Note that an extra '
           'script can be specified via an env var EXTRA_LANDMINES_SCRIPT.')
  parser.add_option('-v', '--verbose', action='store_true',
      default=('LANDMINES_VERBOSE' in os.environ),
      help=('Emit some extra debugging information (default off). This option '
          'is also enabled by the presence of a LANDMINES_VERBOSE environment '
          'variable.'))

  options, args = parser.parse_args()

  if args:
    parser.error('Unknown arguments %s' % args)

  logging.basicConfig(
      level=logging.DEBUG if options.verbose else logging.ERROR)

  extra_script = os.environ.get('EXTRA_LANDMINES_SCRIPT')
  if extra_script:
    return options.landmine_scripts + [extra_script]
  else:
    return options.landmine_scripts

def main():
  landmine_scripts = process_options()

  if landmine_utils.builder() in ('dump_dependency_json', 'eclipse'):
    return 0

  gyp_environment.SetEnvironment()

  landmines = []
  for s in landmine_scripts:
    proc = subprocess.Popen([sys.executable, s], stdout=subprocess.PIPE)
    output, _ = proc.communicate()
    landmines.extend([('%s\n' % l.strip()) for l in output.splitlines()])
  clobber_if_necessary(landmines)

  return 0

if __name__ == '__main__':
  sys.exit(main())
<commit_msg>Prevent landmines.py from deleting your source directory.<commit_after>#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""
This script runs every build as the first hook (See DEPS). If it detects that
the build should be clobbered, it will delete the contents of the build
directory.

A landmine is tripped when a builder checks out a different revision, and the
diff between the new landmines and the old ones is non-null. At this point, the
build is clobbered.
"""

import difflib
import errno
import gyp_environment
import logging
import optparse
import os
import shutil
import sys
import subprocess
import time

import landmine_utils

SRC_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))

def get_build_dir(build_tool, is_iphone=False):
  """
  Returns output directory absolute path dependent on build and targets.
  Examples:
    r'c:\b\build\slave\win\build\src\out'
    '/mnt/data/b/build/slave/linux/build/src/out'
    '/b/build/slave/ios_rel_device/build/src/xcodebuild'

  Keep this function in sync with tools/build/scripts/slave/compile.py
  """
  ret = None
  if build_tool == 'xcode':
    ret = os.path.join(SRC_DIR, 'xcodebuild')
  elif build_tool in ['make', 'ninja', 'ninja-ios']:  # TODO: Remove ninja-ios.
    if 'CHROMIUM_OUT_DIR' in os.environ:
      output_dir = os.environ.get('CHROMIUM_OUT_DIR').strip()
      if not output_dir:
        raise Error('CHROMIUM_OUT_DIR environment variable is set but blank!')
    else:
      output_dir = landmine_utils.gyp_generator_flags().get('output_dir', 'out')
    ret = os.path.join(SRC_DIR, output_dir)
  else:
    raise NotImplementedError('Unexpected GYP_GENERATORS (%s)' % build_tool)
  return os.path.abspath(ret)

def extract_gn_build_commands(build_ninja_file):
  """Extracts from a build.ninja the commands to run GN.

  The commands to run GN are the gn rule and build.ninja build step at the
  top of the build.ninja file. We want to keep these when deleting GN builds
  since we want to preserve the command-line flags to GN.

  On error, returns the empty string."""
  result = ""
  with open(build_ninja_file, 'r') as f:
    # Read until the second blank line. The first thing GN writes to the file
    # is the "rule gn" and the second is the section for "build build.ninja",
    # separated by blank lines.
    num_blank_lines = 0
    while num_blank_lines < 2:
      line = f.readline()
      if len(line) == 0:
        return ''  # Unexpected EOF.
      result += line
      if line[0] == '\n':
        num_blank_lines = num_blank_lines + 1
  return result

def delete_build_dir(build_dir):
  # GN writes a build.ninja.d file. Note that not all GN builds have args.gn.
  build_ninja_d_file = os.path.join(build_dir, 'build.ninja.d')
  if not os.path.exists(build_ninja_d_file):
    shutil.rmtree(build_dir)
    return

  # GN builds aren't automatically regenerated when you sync. To avoid
  # messing with the GN workflow, erase everything but the args file, and
  # write a dummy build.ninja file that will automatically rerun GN the next
  # time Ninja is run.
  build_ninja_file = os.path.join(build_dir, 'build.ninja')
  build_commands = extract_gn_build_commands(build_ninja_file)

  try:
    gn_args_file = os.path.join(build_dir, 'args.gn')
    with open(gn_args_file, 'r') as f:
      args_contents = f.read()
  except IOError:
    args_contents = ''

  shutil.rmtree(build_dir)

  # Put back the args file (if any).
  os.mkdir(build_dir)
  if args_contents != '':
    with open(gn_args_file, 'w') as f:
      f.write(args_contents)

  # Write the build.ninja file sufficiently to regenerate itself.
  with open(os.path.join(build_dir, 'build.ninja'), 'w') as f:
    if build_commands != '':
      f.write(build_commands)
    else:
      # Couldn't parse the build.ninja file, write a default thing.
      f.write('''rule gn
command = gn -q gen //out/%s/
description = Regenerating ninja files

build build.ninja: gn
generator = 1
depfile = build.ninja.d
''' % (os.path.split(build_dir)[1]))

  # Write a .d file for the build which references a nonexistant file. This
  # will make Ninja always mark the build as dirty.
  with open(build_ninja_d_file, 'w') as f:
    f.write('build.ninja: nonexistant_file.gn\n')

def clobber_if_necessary(new_landmines):
  """Does the work of setting, planting, and triggering landmines."""
  out_dir = get_build_dir(landmine_utils.builder())
  landmines_path = os.path.normpath(os.path.join(out_dir, '..', '.landmines'))
  try:
    os.makedirs(out_dir)
  except OSError as e:
    if e.errno == errno.EEXIST:
      pass

  if os.path.exists(landmines_path):
    with open(landmines_path, 'r') as f:
      old_landmines = f.readlines()
    if old_landmines != new_landmines:
      old_date = time.ctime(os.stat(landmines_path).st_ctime)
      diff = difflib.unified_diff(old_landmines, new_landmines,
          fromfile='old_landmines', tofile='new_landmines',
          fromfiledate=old_date, tofiledate=time.ctime(), n=0)
      sys.stdout.write('Clobbering due to:\n')
      sys.stdout.writelines(diff)

      # Clobber contents of build directory but not directory itself: some
      # checkouts have the build directory mounted.
      for f in os.listdir(out_dir):
        path = os.path.join(out_dir, f)
        if os.path.isfile(path):
          os.unlink(path)
        elif os.path.isdir(path):
          delete_build_dir(path)

  # Save current set of landmines for next time.
  with open(landmines_path, 'w') as f:
    f.writelines(new_landmines)

def process_options():
  """Returns a list of landmine emitting scripts."""
  parser = optparse.OptionParser()
  parser.add_option(
      '-s', '--landmine-scripts', action='append',
      default=[os.path.join(SRC_DIR, 'build', 'get_landmines.py')],
      help='Path to the script which emits landmines to stdout. The target '
           'is passed to this script via option -t. Note that an extra '
           'script can be specified via an env var EXTRA_LANDMINES_SCRIPT.')
  parser.add_option('-v', '--verbose', action='store_true',
      default=('LANDMINES_VERBOSE' in os.environ),
      help=('Emit some extra debugging information (default off). This option '
          'is also enabled by the presence of a LANDMINES_VERBOSE environment '
          'variable.'))

  options, args = parser.parse_args()

  if args:
    parser.error('Unknown arguments %s' % args)

  logging.basicConfig(
      level=logging.DEBUG if options.verbose else logging.ERROR)

  extra_script = os.environ.get('EXTRA_LANDMINES_SCRIPT')
  if extra_script:
    return options.landmine_scripts + [extra_script]
  else:
    return options.landmine_scripts

def main():
  landmine_scripts = process_options()

  if landmine_utils.builder() in ('dump_dependency_json', 'eclipse'):
    return 0

  gyp_environment.SetEnvironment()

  landmines = []
  for s in landmine_scripts:
    proc = subprocess.Popen([sys.executable, s], stdout=subprocess.PIPE)
    output, _ = proc.communicate()
    landmines.extend([('%s\n' % l.strip()) for l in output.splitlines()])
  clobber_if_necessary(landmines)

  return 0

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


<commit_before>from __future__ import absolute_import

import pytest
import os
import sys
try:
    from cStringIO import StringIO as BytesIO
except ImportError:
    from io import BytesIO
import struct

prefix = '.'
for i in range(0, 3):
    if os.path.isdir(os.path.join(prefix, 'pycdlib')):
        sys.path.insert(0, prefix)
        break
    else:
        prefix = '../' + prefix

import pycdlib.dr

# XA
def test_xa_parse_initialized_twice():
    xa = pycdlib.dr.XARecord()
    xa.parse(b'\x00\x00\x00\x00\x00\x00\x58\x41\x00\x00\x00\x00\x00\x00')
    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInternalError) as excinfo:
        xa.parse(b'\x00\x00\x00\x00\x00\x00\x58\x41\x00\x00\x00\x00\x00\x00')
    assert(str(excinfo.value) == 'This XARecord is already initialized')

def test_xa_parse_bad_reserved():
    xa = pycdlib.dr.XARecord()
    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        xa.parse(b'\x00\x00\x00\x00\x00\x00\x58\x41\x00\x00\x00\x00\x00\x01')
    assert(str(excinfo.value) == 'Unused fields should be 0')

def test_xa_new_initialized_twice():
    xa = pycdlib.dr.XARecord()
    xa.new()
    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInternalError) as excinfo:
        xa.new()
    assert(str(excinfo.value) == 'This XARecord is already initialized')

def test_xa_record_not_initialized():
    xa = pycdlib.dr.XARecord()
    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInternalError) as excinfo:
        xa.record()
    assert(str(excinfo.value) == 'This XARecord is not initialized')
<commit_msg>Additional tests for DirectoryRecord.<commit_after>from __future__ import absolute_import

import pytest
import os
import sys
try:
    from cStringIO import StringIO as BytesIO
except ImportError:
    from io import BytesIO
import struct

prefix = '.'
for i in range(0, 3):
    if os.path.isdir(os.path.join(prefix, 'pycdlib')):
        sys.path.insert(0, prefix)
        break
    else:
        prefix = '../' + prefix

import pycdlib.dr

# XA
def test_xa_parse_initialized_twice():
    xa = pycdlib.dr.XARecord()
    xa.parse(b'\x00\x00\x00\x00\x00\x00\x58\x41\x00\x00\x00\x00\x00\x00')
    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInternalError) as excinfo:
        xa.parse(b'\x00\x00\x00\x00\x00\x00\x58\x41\x00\x00\x00\x00\x00\x00')
    assert(str(excinfo.value) == 'This XARecord is already initialized')

def test_xa_parse_bad_reserved():
    xa = pycdlib.dr.XARecord()
    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        xa.parse(b'\x00\x00\x00\x00\x00\x00\x58\x41\x00\x00\x00\x00\x00\x01')
    assert(str(excinfo.value) == 'Unused fields should be 0')

def test_xa_new_initialized_twice():
    xa = pycdlib.dr.XARecord()
    xa.new()
    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInternalError) as excinfo:
        xa.new()
    assert(str(excinfo.value) == 'This XARecord is already initialized')

def test_xa_record_not_initialized():
    xa = pycdlib.dr.XARecord()
    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInternalError) as excinfo:
        xa.record()
    assert(str(excinfo.value) == 'This XARecord is not initialized')

# DR
def test_dr_parse_initialized_twice():
    dr = pycdlib.dr.DirectoryRecord()
    dr.parse(None, b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00'*7 + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00', None)
    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInternalError) as excinfo:
        dr.parse(None, b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00'*7 + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00', None)
    assert(str(excinfo.value) == 'Directory Record already initialized')

def test_dr_bad_record_length():
    dr = pycdlib.dr.DirectoryRecord()
    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        dr.parse(None, b'\x00' * 256, None)
    assert(str(excinfo.value) == 'Directory record longer than 255 bytes!')

def test_dr_bad_extent_location():
    dr = pycdlib.dr.DirectoryRecord()
    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        dr.parse(None, b'\x00\x00\x01\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00'*7 + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00', None)
    assert(str(excinfo.value) == 'Little-endian (1) and big-endian (2) extent location disagree')

def test_dr_bad_seqnum():
    dr = pycdlib.dr.DirectoryRecord()
    with pytest.raises(pycdlib.pycdlibexception.PyCdlibInvalidISO) as excinfo:
        dr.parse(None, b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00'*7 + b'\x00\x00\x00\x01\x00\x00\x02\x00\x00', None)
    assert(str(excinfo.value) == 'Little-endian and big-endian seqnum disagree')
<|endoftext|>


<commit_before>#!/usr/bin/env python
# check_stable.py
#
# Retrieve latest stable version from static.rust-lang.org
# Compare the stable version to ensure we have a corresponding docker tag
#
# If we have not built it, print the version we need to build and exit 0
# If we have built it, exit 1

import urllib.request as urllib
import json
import toml
import sys

# Dockerhub repo to compare rust-lang release with
DOCKERHUB_REPO="clux/muslrust"

def rust_stable_version():
    """Retrieve the latest rust stable version from static.rust-lang.org"""
    url = 'https://static.rust-lang.org/dist/channel-rust-stable.toml'
    req = urllib.urlopen(url)
    data = toml.loads(req.read().decode("utf-8"))
    req.close()
    return data['pkg']['rust']['version'].split()[0]

def tag_exists(tag):
    """Retrieve our built tags and check we have built a given one"""
    url = f'https://registry.hub.docker.com/v1/repositories/{DOCKERHUB_REPO}/tags'
    req = urllib.urlopen(url)
    data = json.loads(req.read())
    req.close()
    for x in data:
        if x['name'] == tag:
            return True
    return False

if __name__ == '__main__':
    latest_stable = rust_stable_version()
    stable_tag = f'{latest_stable}-stable'
    if tag_exists(stable_tag):
        print(f'tag {stable_tag} already built')
        sys.exit(1)
    else:
        print(f'need to build {latest_stable}')
        sys.exit(0)
<commit_msg>Use docker registry API v2<commit_after>#!/usr/bin/env python
# check_stable.py
#
# Retrieve latest stable version from static.rust-lang.org
# Compare the stable version to ensure we have a corresponding docker tag
#
# If we have not built it, print the version we need to build and exit 0
# If we have built it, exit 1

import urllib.request as urllib
import json
import toml
import sys

# Dockerhub repo to compare rust-lang release with
DOCKERHUB_REPO="clux/muslrust"

def rust_stable_version():
    """Retrieve the latest rust stable version from static.rust-lang.org"""
    url = 'https://static.rust-lang.org/dist/channel-rust-stable.toml'
    req = urllib.urlopen(url)
    data = toml.loads(req.read().decode("utf-8"))
    req.close()
    return data['pkg']['rust']['version'].split()[0]

def tag_exists(tag):
    """Retrieve our built tags and check we have built a given one"""
    (namespace, repo) = DOCKERHUB_REPO.split("/")
    url = f'https://registry.hub.docker.com/v2/namespaces/{namespace}/repositories/{repo}/tags'
    req = urllib.urlopen(url)
    data = json.loads(req.read())
    req.close()
    for x in data['results']:
        if x['name'] == tag:
            return True
    return False

if __name__ == '__main__':
    latest_stable = rust_stable_version()
    stable_tag = f'{latest_stable}-stable'
    if tag_exists(stable_tag):
        print(f'tag {stable_tag} already built')
        sys.exit(1)
    else:
        print(f'need to build {latest_stable}')
        sys.exit(0)
<|endoftext|>