<commit_before>"""
Tests for the DjangoXBlockUserService.
"""
from django.test import TestCase
from xblock_django.user_service import (
    DjangoXBlockUserService,
    ATTR_KEY_IS_AUTHENTICATED,
    ATTR_KEY_USER_ID,
    ATTR_KEY_USERNAME,
)
from student.models import anonymous_id_for_user
from student.tests.factories import UserFactory, AnonymousUserFactory
from opaque_keys.edx.locations import SlashSeparatedCourseKey

class UserServiceTestCase(TestCase):
    """
    Tests for the DjangoXBlockUserService.
    """
    def setUp(self):
        self.user = UserFactory(username="tester", email="test@tester.com")
        self.user.profile.name = "Test Tester"
        self.anon_user = AnonymousUserFactory()

    def assert_is_anon_xb_user(self, xb_user):
        """
        A set of assertions for an anonymous XBlockUser.
        """
        self.assertFalse(xb_user.opt_attrs[ATTR_KEY_IS_AUTHENTICATED])
        self.assertIsNone(xb_user.full_name)
        self.assertListEqual(xb_user.emails, [])

    def assert_xblock_user_matches_django(self, xb_user, dj_user):
        """
        A set of assertions for comparing a XBlockUser to a django User
        """
        self.assertTrue(xb_user.opt_attrs[ATTR_KEY_IS_AUTHENTICATED])
        self.assertEqual(xb_user.emails[0], dj_user.email)
        self.assertEqual(xb_user.full_name, dj_user.profile.name)
        self.assertEqual(xb_user.opt_attrs[ATTR_KEY_USERNAME], dj_user.username)
        self.assertEqual(xb_user.opt_attrs[ATTR_KEY_USER_ID], dj_user.id)

    def test_convert_anon_user(self):
        """
        Tests for convert_django_user_to_xblock_user behavior when django user is AnonymousUser.
        """
        django_user_service = DjangoXBlockUserService(self.anon_user)
        xb_user = django_user_service.get_current_user()
        self.assertTrue(xb_user.is_current_user)
        self.assert_is_anon_xb_user(xb_user)

    def test_convert_authenticate_user(self):
        """
        Tests for convert_django_user_to_xblock_user behavior when django user is User.
        """
        django_user_service = DjangoXBlockUserService(self.user)
        xb_user = django_user_service.get_current_user()
        self.assertTrue(xb_user.is_current_user)
        self.assert_xblock_user_matches_django(xb_user, self.user)

    def test_get_anonymous_user_id_returns_none_for_non_staff_users(self):
        """
        Tests for anonymous_user_id method to return None if user is Non-Staff.
        """
        django_user_service = DjangoXBlockUserService(self.user, user_is_staff=False)

        anonymous_user_id = django_user_service.get_anonymous_user_id(username=self.user.username, course_id='edx/toy/2012_Fall')
        self.assertIsNone(anonymous_user_id)

    def test_get_anonymous_user_id_returns_none_for_non_existing_users(self):
        """
        Tests for anonymous_user_id method to return None username does not exist in system.
        """
        django_user_service = DjangoXBlockUserService(self.user, user_is_staff=True)

        anonymous_user_id = django_user_service.get_anonymous_user_id(username="No User", course_id='edx/toy/2012_Fall')
        self.assertIsNone(anonymous_user_id)

    def test_get_anonymous_user_id_returns_id_for_existing_users(self):
        """
        Tests for anonymous_user_id method returns anonymous user id for a user.
        """
        anon_user_id = anonymous_id_for_user(
            user=self.user,
            course_id=SlashSeparatedCourseKey('edX', 'toy', '2012_Fall'),
            save=True
        )

        django_user_service = DjangoXBlockUserService(self.user, user_is_staff=True)
        anonymous_user_id = django_user_service.get_anonymous_user_id(
            username=self.user.username,
            course_id='edX/toy/2012_Fall'
        )

        self.assertEqual(anonymous_user_id, anon_user_id)
<commit_msg>Refactoring the user service test.<commit_after>"""
Tests for the DjangoXBlockUserService.
"""
from django.test import TestCase
from xblock_django.user_service import (
    DjangoXBlockUserService,
    ATTR_KEY_IS_AUTHENTICATED,
    ATTR_KEY_USER_ID,
    ATTR_KEY_USERNAME,
)
from student.models import anonymous_id_for_user
from student.tests.factories import UserFactory, AnonymousUserFactory
from opaque_keys.edx.keys import CourseKey

class UserServiceTestCase(TestCase):
    """
    Tests for the DjangoXBlockUserService.
    """
    def setUp(self):
        self.user = UserFactory(username="tester", email="test@tester.com")
        self.user.profile.name = "Test Tester"
        self.anon_user = AnonymousUserFactory()

    def assert_is_anon_xb_user(self, xb_user):
        """
        A set of assertions for an anonymous XBlockUser.
        """
        self.assertFalse(xb_user.opt_attrs[ATTR_KEY_IS_AUTHENTICATED])
        self.assertIsNone(xb_user.full_name)
        self.assertListEqual(xb_user.emails, [])

    def assert_xblock_user_matches_django(self, xb_user, dj_user):
        """
        A set of assertions for comparing a XBlockUser to a django User
        """
        self.assertTrue(xb_user.opt_attrs[ATTR_KEY_IS_AUTHENTICATED])
        self.assertEqual(xb_user.emails[0], dj_user.email)
        self.assertEqual(xb_user.full_name, dj_user.profile.name)
        self.assertEqual(xb_user.opt_attrs[ATTR_KEY_USERNAME], dj_user.username)
        self.assertEqual(xb_user.opt_attrs[ATTR_KEY_USER_ID], dj_user.id)

    def test_convert_anon_user(self):
        """
        Tests for convert_django_user_to_xblock_user behavior when django user is AnonymousUser.
        """
        django_user_service = DjangoXBlockUserService(self.anon_user)
        xb_user = django_user_service.get_current_user()
        self.assertTrue(xb_user.is_current_user)
        self.assert_is_anon_xb_user(xb_user)

    def test_convert_authenticate_user(self):
        """
        Tests for convert_django_user_to_xblock_user behavior when django user is User.
        """
        django_user_service = DjangoXBlockUserService(self.user)
        xb_user = django_user_service.get_current_user()
        self.assertTrue(xb_user.is_current_user)
        self.assert_xblock_user_matches_django(xb_user, self.user)

    def test_get_anonymous_user_id_returns_none_for_non_staff_users(self):
        """
        Tests for anonymous_user_id method to return None if user is Non-Staff.
        """
        django_user_service = DjangoXBlockUserService(self.user, user_is_staff=False)

        anonymous_user_id = django_user_service.get_anonymous_user_id(username=self.user.username, course_id='edx/toy/2012_Fall')
        self.assertIsNone(anonymous_user_id)

    def test_get_anonymous_user_id_returns_none_for_non_existing_users(self):
        """
        Tests for anonymous_user_id method to return None username does not exist in system.
        """
        django_user_service = DjangoXBlockUserService(self.user, user_is_staff=True)

        anonymous_user_id = django_user_service.get_anonymous_user_id(username="No User", course_id='edx/toy/2012_Fall')
        self.assertIsNone(anonymous_user_id)

    def test_get_anonymous_user_id_returns_id_for_existing_users(self):
        """
        Tests for anonymous_user_id method returns anonymous user id for a user.
        """
        course_key = CourseKey.from_string('edX/toy/2012_Fall')
        anon_user_id = anonymous_id_for_user(
            user=self.user,
            course_id=course_key,
            save=True
        )

        django_user_service = DjangoXBlockUserService(self.user, user_is_staff=True)
        anonymous_user_id = django_user_service.get_anonymous_user_id(
            username=self.user.username,
            course_id='edX/toy/2012_Fall'
        )

        self.assertEqual(anonymous_user_id, anon_user_id)
<|endoftext|>


<commit_before>__author__ = 'jonathanwebb'
from plex import *
import cStringIO

class Parser:

    def __init__ (self):
        self.formulae = {} ## dict of string to Formula objects
        self.lex = [] ## list of lexical rules

    def addFormula(self, formula):
        if (self.__checkIfIDUsed(formula.id)):
            raise DuplicateIDException
        else:
            self.formulae[formula.id] = formula
            for rule in formula.rules:
                self.lex.append(rule)

    def __checkIfIDUsed(self, id):
        for key in self.formulae.keys():
            if id == key:
                return True
        return False

    def parse(self, input):
        new = self.lex[:]
        #new.append((Rep(Range("AZaz") | Range("09") | Str(" ")), TEXT))
        lex = Lexicon(new)
        s = cStringIO.StringIO(input)
        scanner = Scanner(lex, s)

        id = None
        inputs = []
        while 1:
            token = scanner.read()
            if token[1] is '':
                break
            else:
                if (token[0][:3] == 'id_'):
                    if (not id):
                        id = token[0][3:]
                    elif (id and id != token[0][3:]):
                        raise Exception

                else:
                    inputs.append(token[0])

class Formula:

    def __init__(self, id, formula, f):
        '''
        :param id: str
        :param formula: str
        :param f: a function that takes a list of strings
        :return: None
        '''

        self.func = f
        self.id = id

        letter = Range("AZaz")
        digit = Range("09")
        text = Rep(letter | digit | Str(" "))
        open_bracket = Str('{{')
        close_bracket = Str('}}')
        lex = Lexicon([
            (text, 'terminal'),
            (open_bracket, 'open'),
            (close_bracket, 'close')
        ])
        s = cStringIO.StringIO(formula)
        scanner = Scanner(lex, s)

        tokens = []
        while 1:
            token = scanner.read()
            if token[1] is '':
                break
            else:
                tokens.append(token)
                print token

        lexl = []
        param = False
        for instance in tokens:
            if (instance[0] == 'terminal' and not param):
                lexl.append((Str(instance[1]), 'id_' + self.id))
            elif(instance[0] == 'open'):
                param = True
            elif(instance[0] == 'close'):
                param = False

        self.rules = lexl

        for x in lexl:
            print x

class DuplicateIDException(Exception):
    pass

def testfunc():
    print "x"

if __name__ == '__main__':
    y = Formula('testfunc', 'Next bus for {{route}} at {{intersection}}', testfunc)
    x = Parser()
    x.addFormula(y)
    x.parse("Next bus for 116 at Coronation and Lawrence")<commit_msg>Git commit added texti parser<commit_after>__author__ = 'jonathanwebb'
from plex import *
import cStringIO

class TextiScanner(Scanner):

    def __init__(self, lex, string):
        list = lex[:]
        list.append(State('param', [(Rep(Range("AZaz") | Range("09") | Str(" ")), TEXT)]))
        stream = cStringIO.StringIO(string)

    def begin_param(self, text):
        self.begin("param")

    def end_param(self, text):
        self.end("param")

class Parser:

    def __init__ (self):
        self.formulae = {} ## dict of string to Formula objects
        self.lex = [] ## list of lexical rules

    def addFormula(self, formula):
        if (self.__checkIfIDUsed(formula.id)):
            raise DuplicateIDException
        else:
            self.formulae[formula.id] = formula
            for rule in formula.rules:
                self.lex.append(rule)

    def __checkIfIDUsed(self, id):
        for key in self.formulae.keys():
            if id == key:
                return True
        return False

    def parse(self, input):
        new = self.lex[:]
        new.append(State('param', [(Rep(Range("AZaz") | Range("09") | Str(" ")), TEXT)]))
        lex = Lexicon(new)

        scanner = TextiScanner(lex, input)

        id = None
        inputs = []
        while 1:
            token = scanner.read()
            if token[1] is '':
                break
            else:
                if (token[0][:3] == 'id_'):
                    if (not id):
                        id = token[0][3:]
                    elif (id and id != token[0][3:]):
                        raise Exception

                else:
                    inputs.append(token[0])

class Formula:

    def __init__(self, id, formula, f):
        '''
        :param id: str
        :param formula: str
        :param f: a function that takes a list of strings
        :return: None
        '''

        self.func = f
        self.id = id

        letter = Range("AZaz")
        digit = Range("09")
        text = Rep(letter | digit | Str(" "))
        open_bracket = Str('{{')
        close_bracket = Str('}}')
        lex = Lexicon([
            (text, 'terminal'),
            (open_bracket, 'open'),
            (close_bracket, 'close')
        ])
        s = cStringIO.StringIO(formula)
        scanner = Scanner(lex, s)

        tokens = []
        while 1:
            token = scanner.read()
            if token[1] is '':
                break
            else:
                tokens.append(token)
                print token

        lexl = []
        param = False
        for instance in tokens:
            if (instance[0] == 'terminal' and not param):
                lexl.append((Str(instance[1]), 'id_' + self.id))
            elif(instance[0] == 'open'):
                param = True
            elif(instance[0] == 'close'):
                param = False

        self.rules = lexl

        for x in lexl:
            print x

class DuplicateIDException(Exception):
    pass

def testfunc():
    print "x"

if __name__ == '__main__':
    y = Formula('testfunc', 'Next bus for {{route}} at {{intersection}}', testfunc)
    x = Parser()
    x.addFormula(y)
    x.parse("Next bus for 116 at Coronation and Lawrence")<|endoftext|>


<commit_before>from protos import deck_pb2, hero_pb2, card_pb2, player_model_pb2, weapon_pb2, minion_pb2
from helpers import *
import json
from pprint import pprint
import suggestion

expansion_sets = [
    "Basic",
    "Blackrock Mountain",
    "Classic",
    "Curse of Naxxramas",
    "Goblins vs Gnomes",
    "The Grand Tournament"
]
hero_list = [
    ["Malfurion Stormrage", "Druid"],
    ["Rexxar", "Hunter"],
    ["Jaina Proudmoore", "Mage"],
    ["Uther Lightbringer", "Paladin"],
    ["Anduin Wrynn", "Priest"],
    ["Valeera Sanguinar", "Rogue"],
    ["Thrall", "Shaman"],
    ["Gul'dan", "Warlock"],
    ["Garrosh Hellscream", "Warrior"],
    ["Alleria Windrunner", "Hunter"],
    ["Medivh", "Mage"],
    ["Magni Bronzebeard", "Warrior"]
]
hero_power_list = [
    "Shapeshift",
    "Steady Shot",
    "Fireblast",
    "Reinforce",
    "Lesser Heal",
    "Dagger Mastery",
    "Totemic Call",
    "Life Tap",
    "Armor Up!"
]

with open("AllSets.json") as json_file:
    data = json.load(json_file)

# Create Weapon
weapon = weapon_pb2.Weapon()
weapon.name = ""
weapon.durability = 0
weapon.attack = 0

# Create Hero
hero = hero_pb2.Hero()
hero.weapon.CopyFrom(weapon)
hero.armor = 0

# Create Deck
deck = deck_pb2.Deck()
with open("decks/basic_test_warlock.deck") as f:
    lines = f.readlines()
for line in lines:
    double = False
    if line[0] == '2':
        double = True
        line = line[2:]
    temp_card = card_pb2.Card()
    temp_card.has_been_used = False
    temp_card.in_hand = False
    temp_card.name = line.strip()
    deck.cards.extend([temp_card])
    if double:
        deck.cards.extend([temp_card])

player_model = player_model_pb2.PlayerModel()
player_model.name = "connor"
player_model.player_id = 0
player_model.hero.CopyFrom(hero)
player_model.deck.CopyFrom(deck)
player_model.max_mana = 1

played_first = True
cards_drawn = 0
turns_ended = 0

logfile = open("C:\Program Files (x86)\Hearthstone\Hearthstone_Data\output_log.txt", 'r')
loglines = follow(logfile)
for line in loglines:
    if "TRANSITIONING" in line:
        ## Draw Card
        if "to FRIENDLY HAND" in line:
            card_name = parseName(line)             # Get card name
            cards_drawn += 1			#count drawn cards
            if cards_drawn == 4:         #starting hand is drawn
                for card in player_model.hand:
                    if card.name == "The Coin":		#The Coin indicates playing second
                        played_first = False
            if cards_drawn >= 4:
                suggestion.suggest_play(player_model)  #print suggested play to user
                break
            for deck_card in player_model.deck.cards:    # Cycle cards
                if deck_card.name == card_name:          # If card name matches
                    # If the card matches and hasn't been used/drawn
                    if deck_card.has_been_used is False and deck_card.in_hand is False:
                        deck_card.in_hand = True         # Set the card to be in hand
                        player_model.hand.extend([deck_card])
                    else:
                        continue

        ## Summon Friendly Minion
        elif "to FRIENDLY PLAY" in line:           # Friendly Minion summoned
            card_name = parseName(line)
            is_hero = False
            is_hero_power = False
            for hero in hero_list:
                if card_name == hero[0]:
                    hero = hero_pb2.Hero()
                    hero.weapon.CopyFrom(weapon)
                    hero.armor = 0
                    hero_minion = minion_pb2.Minion()
                    hero_minion.max_health = 30
                    hero_card = card_pb2.Card()
                    hero_card.name = card_name
                    hero_card.has_been_used = True
                    hero_card.in_hand = False
                    hero_minion.card.CopyFrom(hero_card)
                    hero.minion.CopyFrom(hero_minion)
                    is_hero = True
                    break
            for hp in hero_power_list:
                if card_name == hp:
                    is_hero_power = True
                    break
            if is_hero or is_hero_power:
                continue
            for card_set in expansion_sets:
                for current_card in data[card_set]:
                    if card_name == current_card["name"]:
                        try:
                            minion = minion_pb2.Minion()
                            minion.has_attacked = False
                            minion.health = current_card["health"]
                            minion.max_health = current_card["health"]
                            minion.attack = current_card["attack"]
                            minion.spell_damage = 0
                            minion.tribe = minion_pb2.Minion.NONE
                            minion_card = card_pb2.Card()
                            minion_card.has_been_used = True
                            minion_card.in_hand = False
                            minion_card.name = card_name
                            minion.card.CopyFrom(minion_card)
                            player_model.minions.extend([minion])
                        except:
                            pass

        elif "to OPPOSING PLAY" in line:           # Opponent minion summoned
            print("Opp summoned: " + parseName(line))
        elif "to FRIENDLY SECRET" in line:         # Secret summoned by mad scientist
            print("Secret summoned: " + parseName(line))
    ## Card played or thrown back
    elif "from FRIENDLY HAND ->" in line:
		try:
			card_name = parseName(line)
			for deck_card in player_model.deck.cards:
				if deck_card.name == card_name:
					# If the card has been drawn but not used
					if deck_card.in_hand is True and deck_card.has_been_used is False:
						deck_card.in_hand = False
						# If card is played and not returned to deck
						if "FRIENDLY DECK" not in line:
							deck_card.has_been_used = True
			i = 0
			for hand_card in player_model.hand:
				if hand_card.name == card_name:
					del player_model.hand[i]
					break
				i += 1
		except:
			pass

    elif "from OPPOSING HAND" in line:           # Any opponent card played
        print("Opp played: " + parseName(line))
    elif "BlockType=ATTACK" in line \
            and ".DebugPrintPower()" in line: # Either you or opponent attacks
        print(parseName(line) + " is attacking " + parseTarget(line))
    elif "BlockType=POWER" in line \
            and "Target=0" not in line \
            and "PowerTaskList.DebugPrintPower()" in line:
        print(parseName(line) + " is targeting " + parseTarget(line))
    elif "tag=CURRENT_PLAYER value=0" in line \
            and "PowerTaskList.DebugPrintPower()" in line:
		print("END TURN") # TURN ENDS HERE
		turns_ended += 1
		if (turns_ended % 2) == played_first:
			player_model.max_mana = min(player_model.max_mana + 1, 10) #increase mana up to 10
<commit_msg>Update parser.py<commit_after>from protos import deck_pb2, hero_pb2, card_pb2, player_model_pb2, weapon_pb2, minion_pb2
from helpers import *
import json
from pprint import pprint
import suggestion
import time

expansion_sets = [
    "Basic",
    "Blackrock Mountain",
    "Classic",
    "Curse of Naxxramas",
    "Goblins vs Gnomes",
    "The Grand Tournament"
]
hero_list = [
    ["Malfurion Stormrage", "Druid"],
    ["Rexxar", "Hunter"],
    ["Jaina Proudmoore", "Mage"],
    ["Uther Lightbringer", "Paladin"],
    ["Anduin Wrynn", "Priest"],
    ["Valeera Sanguinar", "Rogue"],
    ["Thrall", "Shaman"],
    ["Gul'dan", "Warlock"],
    ["Garrosh Hellscream", "Warrior"],
    ["Alleria Windrunner", "Hunter"],
    ["Medivh", "Mage"],
    ["Magni Bronzebeard", "Warrior"]
]
hero_power_list = [
    "Shapeshift",
    "Steady Shot",
    "Fireblast",
    "Reinforce",
    "Lesser Heal",
    "Dagger Mastery",
    "Totemic Call",
    "Life Tap",
    "Armor Up!"
]

with open("AllSets.json") as json_file:
    data = json.load(json_file)

# Create Weapon
weapon = weapon_pb2.Weapon()
weapon.name = ""
weapon.durability = 0
weapon.attack = 0

# Create Hero
hero = hero_pb2.Hero()
hero.weapon.CopyFrom(weapon)
hero.armor = 0

# Create Deck
deck = deck_pb2.Deck()
with open("decks/basic_test_warlock.deck") as f:
    lines = f.readlines()
for line in lines:
    double = False
    if line[0] == '2':
        double = True
        line = line[2:]
    temp_card = card_pb2.Card()
    temp_card.has_been_used = False
    temp_card.in_hand = False
    temp_card.name = line.strip()
    deck.cards.extend([temp_card])
    if double:
        deck.cards.extend([temp_card])

player_model = player_model_pb2.PlayerModel()
player_model.name = "connor"
player_model.player_id = 0
player_model.hero.CopyFrom(hero)
player_model.deck.CopyFrom(deck)
player_model.max_mana = 1

played_first = True
cards_drawn = 0
turns_ended = 0

logfile = open("D:\Files\Hearthstone\Hearthstone_Data\output_log.txt", 'r')
logfile.seek(0,2)
while not "tag=PLAYSTATE" in line and not "value=LOST" in line:
    while True:
        line = logfile.readline()
        if not line:
            time.sleep(0.1)
        else:
            break
    if "TRANSITIONING" in line:
        ## Draw Card
        if "to FRIENDLY HAND" in line:
            card_name = parseName(line)             # Get card name
            cards_drawn += 1			#count drawn cards
            if cards_drawn == 4:         #starting hand is drawn
                for card in player_model.hand:
                    if card.name == "The Coin":		#The Coin indicates playing second
                        played_first = False
            if cards_drawn >= 4:
                suggestion.suggest_play(player_model)  #print suggested play to user
                continue
            for deck_card in player_model.deck.cards:    # Cycle cards
                if deck_card.name == card_name:          # If card name matches
                    # If the card matches and hasn't been used/drawn
                    if deck_card.has_been_used is False and deck_card.in_hand is False:
                        deck_card.in_hand = True         # Set the card to be in hand
                        player_model.hand.extend([deck_card])
                    else:
                        continue

        ## Summon Friendly Minion
        elif "to FRIENDLY PLAY" in line:           # Friendly Minion summoned
            card_name = parseName(line)
            is_hero = False
            is_hero_power = False
            for hero in hero_list:
                if card_name == hero[0]:
                    hero = hero_pb2.Hero()
                    hero.weapon.CopyFrom(weapon)
                    hero.armor = 0
                    hero_minion = minion_pb2.Minion()
                    hero_minion.max_health = 30
                    hero_card = card_pb2.Card()
                    hero_card.name = card_name
                    hero_card.has_been_used = True
                    hero_card.in_hand = False
                    hero_minion.card.CopyFrom(hero_card)
                    hero.minion.CopyFrom(hero_minion)
                    is_hero = True
                    break
            for hp in hero_power_list:
                if card_name == hp:
                    is_hero_power = True
                    break
            if is_hero or is_hero_power:
                continue
            for card_set in expansion_sets:
                for current_card in data[card_set]:
                    if card_name == current_card["name"]:
                        try:
                            minion = minion_pb2.Minion()
                            minion.has_attacked = False
                            minion.health = current_card["health"]
                            minion.max_health = current_card["health"]
                            minion.attack = current_card["attack"]
                            minion.spell_damage = 0
                            minion.tribe = minion_pb2.Minion.NONE
                            minion_card = card_pb2.Card()
                            minion_card.has_been_used = True
                            minion_card.in_hand = False
                            minion_card.name = card_name
                            minion.card.CopyFrom(minion_card)
                            player_model.minions.extend([minion])
                        except:
                            pass

        elif "to OPPOSING PLAY" in line:           # Opponent minion summoned
            print("Opp summoned: " + parseName(line))
        elif "to FRIENDLY SECRET" in line:         # Secret summoned by mad scientist
            print("Secret summoned: " + parseName(line))
    ## Card played or thrown back
    elif "from FRIENDLY HAND ->" in line:

        try:
            card_name = parseName(line)
            for deck_card in player_model.deck.cards:
                if deck_card.name == card_name:
					# If the card has been drawn but not used
                    if deck_card.in_hand is True and deck_card.has_been_used is False:
                        deck_card.in_hand = False
						# If card is played and not returned to deck
                        if "FRIENDLY DECK" not in line:
                            deck_card.has_been_used = True
            i = 0
            for hand_card in player_model.hand:
                if hand_card.name == card_name:
                    del player_model.hand[i]
                    break
                i += 1
        except:
            pass
    elif "from OPPOSING HAND" in line:           # Any opponent card played
        print("Opp played: " + parseName(line))
    elif "BlockType=ATTACK" in line \
            and ".DebugPrintPower()" in line: # Either you or opponent attacks
        print(parseName(line) + " is attacking " + parseTarget(line))
    elif "BlockType=POWER" in line \
            and "Target=0" not in line \
            and "PowerTaskList.DebugPrintPower()" in line:
        print(parseName(line) + " is targeting " + parseTarget(line))
    elif "tag=CURRENT_PLAYER value=0" in line \
            and "PowerTaskList.DebugPrintPower()" in line:
        print("END TURN") # TURN ENDS HERE
        turns_ended += 1
        if (turns_ended % 2) == played_first:
            player_model.max_mana = min(player_model.max_mana + 1, 10) #increase mana up to 10
<|endoftext|>


<commit_before>#!/usr/bin/env python
# encoding=utf-8

from __future__ import unicode_literals
import re
import sys, codecs
from copy import copy
from odict import odict # ordered dict (replace by OrderedDict on Python 3)
from bs4 import BeautifulSoup

class DanmicholoParseError(Exception):

    def __init__(self, msg):
        self.msg = msg

class DpTemplate(object):

    def getwhitespace(self, txt):
        left = ''
        rl = re.search('^([\s])+', txt)
        if rl:
            left = rl.group(0)
        right = ''
        rl = re.search('([\s])+$', txt)
        if rl:
            right= rl.group(0)
        return (left, right)

    def __init__(self, obj):
        self.name="?"
        self.parameters = odict()
        self._paramnames = odict()
        self._paramspace = odict()

        self.begin = obj['begin']
        self.end = obj['end']
        self.name = obj['name'] # preserve original form
        self._txt = obj['txt']

        # Filter out empty parameters:
        splits = filter(lambda x: x != '', obj['splits'])

        # Index for anonymous parameters starts at 1 for consistency with WP:
        pno = 1

        for s in splits:
            s = s.split('=',1)
            #[q.strip() for q in s.split('=',1)]
            if len(s) == 1:
                #wspaceb = re.search('^([\s])+',s[0])
                #wspacee = re.search('([\s])+$',s[0])
                self.parameters[pno] = s[0].strip()
                self._paramnames[pno] = ''
                self._paramspace[pno] = self.getwhitespace(s[0])
                pno += 1
            elif len(s) == 2:
                #wspacee = re.search('([\s])+$',s[1]).group(0)
                self.parameters[s[0].strip()] = s[1].strip()
                self._paramnames[s[0].strip()] = s[0]  # original, unstripped
                self._paramspace[s[0].strip()] = self.getwhitespace(s[1])
            else:
                raise DanmicholoParseError("Wrong len %d in %s " % (len(s), s))

    def modified(self):
        return self._txt != self.getwikitext()

    def original_length(self):
        return self.end - self.begin

    def current_length(self):
        return len(self.getwikitext())

    def getwikitext(self):
        tmp = '{{'+self.name
        for p in self.parameters:
            pnam = self._paramnames[p]
            sp = self._paramspace[p]
            if pnam == '':
                tmp += '|' + sp[0] + self.parameters[p] + sp[1]
            else:
                tmp += '|' + pnam+ '=' + sp[0] + self.parameters[p] + sp[1]
        tmp += '}}'
        return tmp

    def __str__(self):
        return unicode(self).encode('utf-8')

    def __unicode__(self):
        s = "<%s>" % (self.name.strip())
        for k in self.parameters.keys():
            s += "\n  %s = %s" % (k, self.parameters[k])
        return s

class DanmicholoParser(object):

    def clean_p(self,p):
        p = p.split('=',1)
        return [s.strip() for s in p]

    def __init__(self, text, debug = False):
        #self.parse(text, debug = debug)
        self.text = text
        self.errors = []
        pass

    def scan_for_templates(self, text, level = 0, debug = False, start = 0):
        """Recursive template scanner"""

        if level > 20:
            raise DanmicholoParseError("Too many recusions encountered!")

        spaces = ''.join([' ' for i in range(level)])
        if debug:
            print "%s> scan (offset = %d, length = %d)" % (spaces, start, len(text))
            #print spaces +"  "+text

        # We should keep track of all brackets, so we don't split inside a bracketed part:
        brackets = { 'round' : 0, 'square': 0, 'curly': 0, 'angle': 0 }
        templates = []
        intemplate = -1
        tmp = ''
        p = start - 1
        for c in text:
            p += 1
            if c == ')': brackets['round'] -= 1
            elif c == ']': brackets['square'] -= 1
            elif c == '}': brackets['curly'] -= 1
            elif c == '>': brackets['angle'] -= 1

            if intemplate != -1 and brackets['curly'] < 2:
                templates[intemplate]['end'] = p + 2
                templates[intemplate]['splits'].append(tmp)
                #templates[intemplate]['splits'] = map(self.clean_p, templates[intemplate]['splits'])
                #print templates[-1]['splits']
                navn = templates[intemplate]['splits'].pop(0).strip('{')
                templates[intemplate]['name'] = navn
                templates[intemplate]['txt'] = text[templates[intemplate]['begin']-start:templates[intemplate]['end']-start]
                #if debug:
                #    print spaces+"  "+c,"end, Name="+templates[intemplate]['name'],templates[intemplate]['begin'],templates[intemplate]['end']

                # Scan all splits for sub-templates:
                offset = start + templates[intemplate]['begin'] + 2 + len(navn) + 1
                #print offset
                for s in templates[intemplate]['splits']:
                    #print s
                    templates = templates + self.scan_for_templates(s, level = level + 1, debug = debug, start = offset)
                    offset += len(s) + 1
                    #offset += 1 # for the pipe

                intemplate = -1
            elif intemplate == -1 and brackets['curly'] >= 2:
                #if debug:
                #    print spaces +"  Template start at ",c
                templates.append({'begin':p-2, 'end':-1, 'splits':[]})
                intemplate = len(templates)-1
                tmp = ''

            if intemplate != -1 and c == '|' and brackets['round'] == brackets['square'] == brackets['angle'] == 0 and brackets['curly'] == 2:
                templates[intemplate]['splits'].append(tmp)
                tmp = ''
            else:
                tmp += c

            if c == '(':   brackets['round'] += 1
            elif c == '[': brackets['square'] += 1
            elif c == '{': brackets['curly'] += 1
            elif c == '<': brackets['angle'] += 1

        if brackets['curly'] != 0:
            raise DanmicholoParseError('Unbalanced curly brackets encountered!')

        if debug:
            print "%s  return %d templates" % (spaces,len(templates))
        return templates

    @property
    def maintext(self):

        # use cached value if available
        try:
            return self._maintext
        except:
            pass

        # We should keep track of all brackets, so we don't split inside a bracketed part:
        brackets = { 'round' : 0, 'square': 0, 'curly': 0, 'angle': 0 }
        intag = False
        out = ''

        soup = BeautifulSoup(self.text, 'lxml')
        souped = ''.join([unicode(q) for q in soup.findAll('body')[0].contents])
        souped = re.sub(r'<(?:/)?p>','', souped) # soup introduces paragraphs, so let's remove them

        for c in souped:

            #elif c == ']': brackets['square'] -= 1
            #elif c == '}': brackets['curly'] -= 1
            #elif c == '>': brackets['angle'] -= 1
            #elif c == '(':   brackets['round'] += 1
            #elif c == '[': brackets['square'] += 1

            if c == '}':
                brackets['curly'] -= 1
                if brackets['angle'] > 0:
                    brackets['angle'] = 0
                    intag = False
            elif c == '{':
                brackets['curly'] += 1
            elif c == '>':
                brackets['angle'] -= 1
            elif c == '<':
                brackets['angle'] += 1
                intag = True
            elif brackets['angle'] == 1 and c == '/':
                intag = False
            elif brackets['curly'] == 0 and brackets['angle'] == 0 and intag == False:
                out += c

        #print len(out), brackets['curly'], brackets['angle']
        out = re.sub(r'==[=]*','', out)
        out = re.sub(r"''[']*",'', out)
        out = re.sub(r'^#.*?$','', out, flags = re.MULTILINE)            # drop lists
        out = re.sub(r'^\*.*?$','', out, flags = re.MULTILINE)           # drop lists
        out = re.sub(r'\[\[Kategori:[^\]]+\]\]','', out)         # drop categories
        out = re.sub(r'\[\[[A-Za-z\-]+:[^\]]+\]\]','', out)       # drop interwikis and files
        out = re.sub(r'(?<!\[)\[(?!\[)[^ ]+ [^\]]+\]','', out)   # drop external links
        out = re.sub(r'\[\[(?:[^|\]]+\|)?([^\]]+)\]\]', '\\1', out)  # wikilinks as text, '[[Artikkel 1|artikkelen]]' -> 'artikkelen'

        self._maintext = out.strip()

        #if intag:
        #    raise DanmicholoParseError('Non-closed html tag encountered!')
        #if brackets['curly'] != 0:
        #    raise DanmicholoParseError('Unbalanced curly brackets encountered!')

        return out

    @property
    def tags(self):
        """
        A simple and unsophisticated HTML parser, does not even handle things like tags inside tags,
        but those should be avoided in wikitext I think.

        Returns a dictionary of tag names, with each dictionary item containing a list of the occurances of that tag,
        so you can do things like this:

        >>> nrefs = len([r for r in dp.tags['ref'] if 'content' in r])

        >>> for r in tags['ref']:
        >>>    if 'name' in r:
        >>>        print r['name']

        """

        # use cached value if available
        try:
            return self._tags
        except:
            pass

        tags = {}
        state = ''
        starttag = ''
        tagcontent = ''
        for i,c in enumerate(self.text):
            if state == 'starttag' and c == '>':
                state = 'intag'
            elif state == 'comment' and c == '>':
                state = ''
            elif state == 'endtag' and c == '>':
                state = ''
                starttag = starttag.strip().split()
                try:
                    tagname = starttag[0]
                except:
                    #if self.raise_errors:
                    #raise DanmicholoParseError("Blank/invalid html tag encountered near %d" % i)
                    self.errors.append("Blank/invalid html tag encountered near %d" % i)
                    if len(self.errors) > 10:
                        self.errors.append("Too many errors. I'm giving up")
                        break
                    continue
                tag = { }
                for a in starttag[1:]:
                    aa = [q.strip(' "\'') for q in a.split('=')]
                    if len(aa)==2:
                        tag[aa[0]] = aa[1]
                if len(tagcontent) > 0:
                    tag['content'] = tagcontent.strip()
                if not tagname in tags:
                    tags[tagname] = []
                tags[tagname].append(tag)

            elif state == 'intag' and c == '<':
                state = 'endtag'
            elif state == '' and c == '<':
                state = 'starttag'
                starttag = ''
                tagcontent = ''
            elif state == 'starttag' and c == '/':
                state = 'endtag'
            elif state == 'starttag' and c == '!':
                state = 'comment'
            elif state == 'starttag':
                starttag += c
            elif state == 'intag':
                tagcontent += c

        self._tags = tags

        return tags

    @property
    def templates(self):
        try:
            return self._templates
        except:
            pass

        templates = self.scan_for_templates(self.text)

        self._templates = odict()

        for t in templates:

            dt = DpTemplate(t)
            #print dt

            k = dt.name.strip().lower()
            if k in self._templates:
                self._templates[k].append(dt)
            else:
                self._templates[k] = [dt]

        return self._templates

    def reparse(self):
        del self._templates
        self.text = unicode(self)
        #self.parse(unicode(self))

    #def parse(self, text, debug = False):

    def __str__(self):
        return unicode(self).encode('utf-8')

    def __unicode__(self):
        mod = 0
        txt = copy(self.text)
        for key in self.templates:
            for t in self.templates[key]:
                if t.modified():
                    if mod > 0:
                        raise StandardError("Uh oh, can only handle one modification a time")
                    txt = txt[:t.begin] + t.getwikitext() + txt[t.end+1:]
                    mod += 1
                #print t.begin
        return txt

<commit_msg>raise error on unbalanced brackets<commit_after>#!/usr/bin/env python
# encoding=utf-8

from __future__ import unicode_literals
import re
import sys, codecs
from copy import copy
from odict import odict # ordered dict (replace by OrderedDict on Python 3)
from bs4 import BeautifulSoup

class DanmicholoParseError(Exception):

    def __init__(self, msg):
        self.msg = msg

class DpTemplate(object):

    def getwhitespace(self, txt):
        left = ''
        rl = re.search('^([\s])+', txt)
        if rl:
            left = rl.group(0)
        right = ''
        rl = re.search('([\s])+$', txt)
        if rl:
            right= rl.group(0)
        return (left, right)

    def __init__(self, obj):
        self.name="?"
        self.parameters = odict()
        self._paramnames = odict()
        self._paramspace = odict()

        self.begin = obj['begin']
        self.end = obj['end']
        self.name = obj['name'] # preserve original form
        self._txt = obj['txt']

        # Filter out empty parameters:
        splits = filter(lambda x: x != '', obj['splits'])

        # Index for anonymous parameters starts at 1 for consistency with WP:
        pno = 1

        for s in splits:
            s = s.split('=',1)
            #[q.strip() for q in s.split('=',1)]
            if len(s) == 1:
                #wspaceb = re.search('^([\s])+',s[0])
                #wspacee = re.search('([\s])+$',s[0])
                self.parameters[pno] = s[0].strip()
                self._paramnames[pno] = ''
                self._paramspace[pno] = self.getwhitespace(s[0])
                pno += 1
            elif len(s) == 2:
                #wspacee = re.search('([\s])+$',s[1]).group(0)
                self.parameters[s[0].strip()] = s[1].strip()
                self._paramnames[s[0].strip()] = s[0]  # original, unstripped
                self._paramspace[s[0].strip()] = self.getwhitespace(s[1])
            else:
                raise DanmicholoParseError("Wrong len %d in %s " % (len(s), s))

    def modified(self):
        return self._txt != self.getwikitext()

    def original_length(self):
        return self.end - self.begin

    def current_length(self):
        return len(self.getwikitext())

    def getwikitext(self):
        tmp = '{{'+self.name
        for p in self.parameters:
            pnam = self._paramnames[p]
            sp = self._paramspace[p]
            if pnam == '':
                tmp += '|' + sp[0] + self.parameters[p] + sp[1]
            else:
                tmp += '|' + pnam+ '=' + sp[0] + self.parameters[p] + sp[1]
        tmp += '}}'
        return tmp

    def __str__(self):
        return unicode(self).encode('utf-8')

    def __unicode__(self):
        s = "<%s>" % (self.name.strip())
        for k in self.parameters.keys():
            s += "\n  %s = %s" % (k, self.parameters[k])
        return s

class DanmicholoParser(object):

    def clean_p(self,p):
        p = p.split('=',1)
        return [s.strip() for s in p]

    def __init__(self, text, debug = False):
        #self.parse(text, debug = debug)
        self.text = text
        self.errors = []
        pass

    def scan_for_templates(self, text, level = 0, debug = False, start = 0):
        """Recursive template scanner"""

        if level > 20:
            raise DanmicholoParseError("Too many recusions encountered!")

        spaces = ''.join([' ' for i in range(level)])
        if debug:
            print "%s> scan (offset = %d, length = %d)" % (spaces, start, len(text))
            #print spaces +"  "+text

        # We should keep track of all brackets, so we don't split inside a bracketed part:
        brackets = { 'round' : 0, 'square': 0, 'curly': 0, 'angle': 0 }
        templates = []
        intemplate = -1
        tmp = ''
        p = start - 1
        for c in text:
            p += 1
            if c == ')': brackets['round'] -= 1
            elif c == ']': brackets['square'] -= 1
            elif c == '}': brackets['curly'] -= 1
            elif c == '>': brackets['angle'] -= 1

            if intemplate != -1 and brackets['curly'] < 2:
                templates[intemplate]['end'] = p + 2
                templates[intemplate]['splits'].append(tmp)
                #templates[intemplate]['splits'] = map(self.clean_p, templates[intemplate]['splits'])
                #print templates[-1]['splits']
                navn = templates[intemplate]['splits'].pop(0).strip('{')
                templates[intemplate]['name'] = navn
                templates[intemplate]['txt'] = text[templates[intemplate]['begin']-start:templates[intemplate]['end']-start]
                #if debug:
                #    print spaces+"  "+c,"end, Name="+templates[intemplate]['name'],templates[intemplate]['begin'],templates[intemplate]['end']

                # Scan all splits for sub-templates:
                offset = start + templates[intemplate]['begin'] + 2 + len(navn) + 1
                #print offset
                for s in templates[intemplate]['splits']:
                    #print s
                    templates = templates + self.scan_for_templates(s, level = level + 1, debug = debug, start = offset)
                    offset += len(s) + 1
                    #offset += 1 # for the pipe

                intemplate = -1
            elif intemplate == -1 and brackets['curly'] >= 2:
                #if debug:
                #    print spaces +"  Template start at ",c
                templates.append({'begin':p-2, 'end':-1, 'splits':[]})
                intemplate = len(templates)-1
                tmp = ''

            if intemplate != -1 and c == '|' and brackets['round'] == brackets['square'] == brackets['angle'] == 0 and brackets['curly'] == 2:
                templates[intemplate]['splits'].append(tmp)
                tmp = ''
            else:
                tmp += c

            if c == '(':   brackets['round'] += 1
            elif c == '[': brackets['square'] += 1
            elif c == '{': brackets['curly'] += 1
            elif c == '<': brackets['angle'] += 1

        if brackets['curly'] != 0:
            raise DanmicholoParseError('Unbalanced curly brackets encountered!')

        if debug:
            print "%s  return %d templates" % (spaces,len(templates))
        return templates

    @property
    def maintext(self):

        # use cached value if available
        try:
            return self._maintext
        except:
            pass

        # We should keep track of all brackets, so we don't split inside a bracketed part:
        brackets = { 'round' : 0, 'square': 0, 'curly': 0, 'angle': 0 }
        intag = False
        out = ''

        soup = BeautifulSoup(self.text, 'lxml')
        souped = ''.join([unicode(q) for q in soup.findAll('body')[0].contents])
        souped = re.sub(r'<(?:/)?p>','', souped) # soup introduces paragraphs, so let's remove them

        for c in souped:

            #elif c == ']': brackets['square'] -= 1
            #elif c == '}': brackets['curly'] -= 1
            #elif c == '>': brackets['angle'] -= 1
            #elif c == '(':   brackets['round'] += 1
            #elif c == '[': brackets['square'] += 1

            if c == '}':
                brackets['curly'] -= 1
                if brackets['angle'] > 0:
                    brackets['angle'] = 0
                    intag = False
            elif c == '{':
                brackets['curly'] += 1
            elif c == '>':
                brackets['angle'] -= 1
            elif c == '<':
                brackets['angle'] += 1
                intag = True
            elif brackets['angle'] == 1 and c == '/':
                intag = False
            elif brackets['curly'] == 0 and brackets['angle'] == 0 and intag == False:
                out += c

        #print len(out), brackets['curly'], brackets['angle']
        out = re.sub(r'==[=]*','', out)
        out = re.sub(r"''[']*",'', out)
        out = re.sub(r'^#.*?$','', out, flags = re.MULTILINE)            # drop lists
        out = re.sub(r'^\*.*?$','', out, flags = re.MULTILINE)           # drop lists
        out = re.sub(r'\[\[Kategori:[^\]]+\]\]','', out)         # drop categories
        out = re.sub(r'\[\[[A-Za-z\-]+:[^\]]+\]\]','', out)       # drop interwikis and files
        out = re.sub(r'(?<!\[)\[(?!\[)[^ ]+ [^\]]+\]','', out)   # drop external links
        out = re.sub(r'\[\[(?:[^|\]]+\|)?([^\]]+)\]\]', '\\1', out)  # wikilinks as text, '[[Artikkel 1|artikkelen]]' -> 'artikkelen'

        self._maintext = out.strip()

        #if intag:
        #    raise DanmicholoParseError('Non-closed html tag encountered!')
        if brackets['curly'] != 0:
            raise DanmicholoParseError('Unbalanced curly brackets encountered!')

        return out

    @property
    def tags(self):
        """
        A simple and unsophisticated HTML parser, does not even handle things like tags inside tags,
        but those should be avoided in wikitext I think.

        Returns a dictionary of tag names, with each dictionary item containing a list of the occurances of that tag,
        so you can do things like this:

        >>> nrefs = len([r for r in dp.tags['ref'] if 'content' in r])

        >>> for r in tags['ref']:
        >>>    if 'name' in r:
        >>>        print r['name']

        """

        # use cached value if available
        try:
            return self._tags
        except:
            pass

        tags = {}
        state = ''
        starttag = ''
        tagcontent = ''
        for i,c in enumerate(self.text):
            if state == 'starttag' and c == '>':
                state = 'intag'
            elif state == 'comment' and c == '>':
                state = ''
            elif state == 'endtag' and c == '>':
                state = ''
                starttag = starttag.strip().split()
                try:
                    tagname = starttag[0]
                except:
                    #if self.raise_errors:
                    #raise DanmicholoParseError("Blank/invalid html tag encountered near %d" % i)
                    self.errors.append("Blank/invalid html tag encountered near %d" % i)
                    if len(self.errors) > 10:
                        self.errors.append("Too many errors. I'm giving up")
                        break
                    continue
                tag = { }
                for a in starttag[1:]:
                    aa = [q.strip(' "\'') for q in a.split('=')]
                    if len(aa)==2:
                        tag[aa[0]] = aa[1]
                if len(tagcontent) > 0:
                    tag['content'] = tagcontent.strip()
                if not tagname in tags:
                    tags[tagname] = []
                tags[tagname].append(tag)

            elif state == 'intag' and c == '<':
                state = 'endtag'
            elif state == '' and c == '<':
                state = 'starttag'
                starttag = ''
                tagcontent = ''
            elif state == 'starttag' and c == '/':
                state = 'endtag'
            elif state == 'starttag' and c == '!':
                state = 'comment'
            elif state == 'starttag':
                starttag += c
            elif state == 'intag':
                tagcontent += c

        self._tags = tags

        return tags

    @property
    def templates(self):
        try:
            return self._templates
        except:
            pass

        templates = self.scan_for_templates(self.text)

        self._templates = odict()

        for t in templates:

            dt = DpTemplate(t)
            #print dt

            k = dt.name.strip().lower()
            if k in self._templates:
                self._templates[k].append(dt)
            else:
                self._templates[k] = [dt]

        return self._templates

    def reparse(self):
        del self._templates
        self.text = unicode(self)
        #self.parse(unicode(self))

    #def parse(self, text, debug = False):

    def __str__(self):
        return unicode(self).encode('utf-8')

    def __unicode__(self):
        mod = 0
        txt = copy(self.text)
        for key in self.templates:
            for t in self.templates[key]:
                if t.modified():
                    if mod > 0:
                        raise StandardError("Uh oh, can only handle one modification a time")
                    txt = txt[:t.begin] + t.getwikitext() + txt[t.end+1:]
                    mod += 1
                #print t.begin
        return txt

<|endoftext|>


<commit_before># cerbero - a multi-platform build system for Open Source software
# Copyright (C) 2012 Andoni Morales Alastruey <ylatuya@gmail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 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
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

import os

from cerbero.commands import Command, register_command
from cerbero.errors import FatalError
from cerbero.utils import _, N_, ArgparseArgument, shell

SCRIPT_TPL = '''\
#!/bin/sh

%s

%s
'''

class GenSdkShell(Command):
    doc = N_('Create a script with the shell environment for the SDK')
    name = 'gensdkshell'

    DEFAULT_CMD = '$SHELL "$@"'

    def __init__(self):
        Command.__init__(self,
            [ArgparseArgument('name', nargs=1, default='sdk-shell',
                             help=_('name of the scrips')),
            ArgparseArgument('-o', '--output-dir', default='.',
                             help=_('output directory')),
            ArgparseArgument('-p', '--prefix',
                             help=_('prefix of the SDK')),
            ArgparseArgument('--cmd', default=self.DEFAULT_CMD,
                             help=_('command to run in the script')),
            ])

    def run(self, config, args):
        name = args.name[0]
        prefix = args.prefix and args.prefix or config.prefix
        libdir = os.path.join(prefix, 'lib')
        py_prefix = config.py_prefix
        output_dir = args.output_dir
        cmd = args.cmd
        self.runargs(config, name, output_dir, prefix, libdir, py_prefix, cmd)

    def runargs(self, config, name, output_dir, prefix, libdir,
                py_prefix, cmd=None):
        cmd = cmd or self.DEFAULT_CMD
        env = {}
        env['PATH'] = \
            '%s/bin${PATH:+:$PATH}:/usr/local/bin:/usr/bin:/bin' % prefix
        env['LD_LIBRARY_PATH'] = \
            '%s${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}' % libdir
        env['PKG_CONFIG_PATH'] = '%s/lib/pkgconfig:%s/share/pkgconfig'\
             '${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}' % (prefix, prefix)
        env['XDG_DATA_DIRS'] = '%s/share${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}:'\
                '/usr/local/share:/usr/share' % prefix
        env['XDG_CONFIG_DIRS'] = \
            '%s/etc/xdg${XDG_CONFIG_DIRS:+:$XDG_CONFIG_DIRS}:/etc/xdg' % prefix
        env['GST_REGISTRY'] = '${HOME}/.gstreamer-0.10/gstreamer-sdk-registry'
        env['GST_PLUGIN_SCANNER'] = \
                '%s/libexec/gstreamer-0.10/gst-plugin-scanner' % prefix
        env['PYTHONPATH'] = '%s/%s/site-packages${PYTHONPATH:+:$PYTHONPATH}'\
                % (prefix, py_prefix)
        env['CFLAGS'] = '-I%s/include ${CFLAGS}' % prefix
        env['CXXFLAGS'] = '-I%s/include ${CXXFLAGS}' % prefix
        env['LDFLAGS'] = '-L%s ${LDFLAGS}' % libdir
        env['GIO_EXTRA_MODULES'] = '%s/gio/modules' % libdir
        envstr = ''
        for e, v in env.iteritems():
            envstr += 'export %s="%s"\n' % (e, v)
        try:
            filepath = os.path.join(output_dir, name)
            with open(filepath, 'w+') as f:
                f.write(SCRIPT_TPL % (envstr, cmd))
            shell.call("chmod +x %s" % filepath)
        except IOError, ex:
            raise FatalError(_("Error creating script: %s" % ex))

register_command(GenSdkShell)
<commit_msg>gensdkshell: use the GSTREAMER_SDK_ROOT variable for the prefix<commit_after># cerbero - a multi-platform build system for Open Source software
# Copyright (C) 2012 Andoni Morales Alastruey <ylatuya@gmail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 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
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

import os

from cerbero.commands import Command, register_command
from cerbero.errors import FatalError
from cerbero.utils import _, N_, ArgparseArgument, shell

SCRIPT_TPL = '''\
#!/bin/sh

%s

%s
'''

class GenSdkShell(Command):
    doc = N_('Create a script with the shell environment for the SDK')
    name = 'gensdkshell'

    DEFAULT_CMD = '$SHELL "$@"'

    def __init__(self):
        Command.__init__(self,
            [ArgparseArgument('name', nargs=1, default='sdk-shell',
                             help=_('name of the scrips')),
            ArgparseArgument('-o', '--output-dir', default='.',
                             help=_('output directory')),
            ArgparseArgument('-p', '--prefix',
                             help=_('prefix of the SDK')),
            ArgparseArgument('--cmd', default=self.DEFAULT_CMD,
                             help=_('command to run in the script')),
            ])

    def run(self, config, args):
        name = args.name[0]
        prefix = args.prefix and args.prefix or config.prefix
        libdir = os.path.join(prefix, 'lib')
        py_prefix = config.py_prefix
        output_dir = args.output_dir
        cmd = args.cmd
        self.runargs(config, name, output_dir, prefix, libdir, py_prefix, cmd)

    def runargs(self, config, name, output_dir, prefix, libdir,
                py_prefix, cmd=None):
        cmd = cmd or self.DEFAULT_CMD
        env = {}
        prefix_env_name = 'GSTREAMER_SDK_ROOT'
        prefix_env = '${%s}' % prefix_env_name
        libdir = libdir.replace(prefix, prefix_env)
        env['PATH'] = \
            '%s/bin${PATH:+:$PATH}:/usr/local/bin:/usr/bin:/bin' % prefix_env
        env['LD_LIBRARY_PATH'] = \
            '%s${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}' % libdir
        env['PKG_CONFIG_PATH'] = '%s/lib/pkgconfig:%s/share/pkgconfig'\
             '${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}' % (prefix_env, prefix_env)
        env['XDG_DATA_DIRS'] = '%s/share${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}:'\
                '/usr/local/share:/usr/share' % prefix_env
        env['XDG_CONFIG_DIRS'] = \
            '%s/etc/xdg${XDG_CONFIG_DIRS:+:$XDG_CONFIG_DIRS}:/etc/xdg' % prefix_env
        env['GST_REGISTRY'] = '${HOME}/.gstreamer-0.10/gstreamer-sdk-registry'
        env['GST_PLUGIN_SCANNER'] = \
                '%s/libexec/gstreamer-0.10/gst-plugin-scanner' % prefix_env
        env['PYTHONPATH'] = '%s/%s/site-packages${PYTHONPATH:+:$PYTHONPATH}'\
                % (prefix_env, py_prefix)
        env['CFLAGS'] = '-I%s/include ${CFLAGS}' % prefix_env
        env['CXXFLAGS'] = '-I%s/include ${CXXFLAGS}' % prefix_env
        env['LDFLAGS'] = '-L%s ${LDFLAGS}' % libdir
        env['GIO_EXTRA_MODULES'] = '%s/gio/modules' % libdir
        envstr = 'export %s="%s"\n' % (prefix_env_name, prefix)
        for e, v in env.iteritems():
            envstr += 'export %s="%s"\n' % (e, v)
        try:
            filepath = os.path.join(output_dir, name)
            with open(filepath, 'w+') as f:
                f.write(SCRIPT_TPL % (envstr, cmd))
            shell.call("chmod +x %s" % filepath)
        except IOError, ex:
            raise FatalError(_("Error creating script: %s" % ex))

register_command(GenSdkShell)
<|endoftext|>


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

# Copyright (c) 2012 Denis Zalevskiy
# Licensed under MIT License

from cor import *

nomatch = const('nomatch')
empty = const('empty')
end = const('end')

def ignore(*x): return empty
def value(x): return x
def first(x): return x[0]
second = nth(1)
def list2str(x): return ''.join(x)

is_parser_trace = True
debug_indent_level = 0
debug_indent_sym = '  '

def __indent_plus():
    global debug_indent_level
    debug_indent_level += 1

def __indent_minus(*args):
    global debug_indent_level
    debug_indent_level -= 1

debug_indent = Scope(__indent_plus, __indent_minus)

def debug_print(msg, *args, **kwargs):
    global debug_indent_sym, debug_indent_level
    print debug_indent_sym * debug_indent_level, \
        msg.format(*args, **kwargs)

def parser(name):
    def mk_name(name):
        return ''.join(['?', name])
    def deco(fn):
        global is_parser_trace
        fn.__name__ = mk_name(name)
        def wrapper(*args, **kwargs):
            global debug_indent
            debug_print("{}({}) {{", fn.__name__,
                        printable_args(*args, **kwargs))
            with debug_indent:
                res = fn(*args, **kwargs)
            debug_print("}} => {}", printable_args(res))
            return res
        if is_parser_trace:
            wrapper.__name__ = mk_name(name)
            return wrapper
        else:
            return fn
    return deco

class InfiniteInput(object):

    len_limit = 1024 * 64

    def __init__(self, src, begin = 0, end = None):
        self.__s = src
        self.__begin = begin
        self.__is_endless = end is None
        if end is None:
            self._end = lambda : len(src)
        elif callable(end):
            self._end = end
        else:
            self._end = lambda: end

    def __get_slice(self, k):
        start, stop = k.start, k.stop
        if not (k.step is None or k.step == 1):
            raise Err("Can't handle step != 1")
        start = self.__begin if start is None else self.__begin + start
        end = self._end if stop is None else self.__begin + stop
        return InfiniteInput(self.__s, start, end)

    def __getitem__(self, i):
        if isinstance(i, slice):
            return self.__get_slice(i)
        end = self._end()
        i = self.__begin + i
        if i < end:
            return self.__s[i]
        elif i > self.len_limit:
            raise Exception("Length limit is reached")
        else:
            return nomatch

    def __str__(self):
        return str(self.__s[self.__begin:self._end()])

    def __repr__(self):
        return ''.join(['"', str(self), '"'])

    def __len__(self):
        return self._end() - self.__begin

    def __iter__(self):
        def gen():
            pos = self.__begin
            while pos != self._end():
                yield self[pos]
                pos += 1
        return gen

    def as_string(self):
        if isinstance(self.__s, str):
            if self.__begin == 0 and self.__is_endless:
                return self.__s
            elif self.__is_endless:
                return self.__s[self.__begin:]
            else:
                return self.__s[self.__begin:self._end()]
        else:
            res = [x for x in self.__s]
            res.append(chr(0))
            return ''.join(res)

def source(src, begin = 0, end = None):
    return InfiniteInput(src, begin, end)

def _match(name, s, conv):
    @parser(name)
    def fn(src):
        v = src[0]
        return (1, conv(v)) if v == s else nomatch
    return fn

def _match_symbol(name, s, conv):
    if isinstance(s, str):
        if len(s) != 1:
            raise Exception("len != 1")
    elif s != nomatch:
        raise Exception("Not a string")
    return _match(name, s, conv)

def _match_string(name, s, conv):
    if not isinstance(s, str):
        raise Exception("Not a string")
    slen = len(s)
    @parser(name)
    def fn(src):
        if len(src) < slen:
            return nomatch
        v = src[0:slen].as_string()
        return (slen, conv(v)) if v == s else nomatch
    return fn

def _match_iterable(name, pat, conv):
    if not is_iterable(pat):
        raise Exception("Don't know what to do with {}".format(seq))

    seq = [x for x in pat] if isinstance(pat, str) else pat
    @parser(name)
    def fn(src):
        v = src[0]
        return (1, conv(v)) if v in seq else nomatch
    return fn

def _match_any(name, tests, conv):
    @parser(name)
    def fn(src):
        for test in tests:
            res = test(src)
            if res == nomatch:
                continue
            return (res[0], conv(res[1]))
        return nomatch
    return fn

def _match_seq(name, tests, conv):
    @parser(name)
    def fn(src):
        total = []
        pos = 0
        for test in tests:
            res = test(src[pos:])
            if res == nomatch:
                return nomatch
            if res[1] != empty:
                total.append(res[1])
            pos += res[0]
        return pos, conv(total)
    return fn

def _one_more(name, test, conv):
    @parser(name)
    def fn(src):
        total = []
        pos = 0
        res = test(src)
        if res == nomatch:
            return res
        while res != nomatch:
            total.append(res[1])
            pos += res[0]
            res = test(src[pos:])
        return pos, conv(total)
    return fn

def _zero_more(name, test, conv):
    @parser(name)
    def fn(src):
        total = []
        pos = 0
        res = test(src)
        while res != nomatch:
            total.append(res[1])
            pos += res[0]
            res = test(src[pos:])
        return pos, conv(total)
    return fn

def _0_1(name, test, conv):
    @parser(name)
    def fn(src):
        pos = 0
        res = test(src)
        return res[0], conv(res[1]) if res != nomatch else (0, empty)
    return fn

def _ne(name, test, conv):
    @parser(name)
    def fn(src):
        res = test(src)
        return (1, conv(src[0])) if res == nomatch else nomatch
    return fn

def is_str(c):
    return isinstance(c, str) or c == nomatch

class ParseInfo(tuple):
    def __new__(cls, *args):
        return tuple.__new__(cls, args)

def __mk_fn_parser(name, rule, action):
    fn, data = rule
    if not is_str(data):
        if is_iterable(data):
            data = [mk_parser(x) for x in data]
        else:
            data = mk_parser(data)
    return fn(name, data, action)

def __extract_rule(entity):
    if isinstance(entity, ParseInfo):
        return entity
    elif is_str(entity):
        return sym(entity)
    else:
        return nomatch

def __extract_rule_action(data, name = "?"):
    res = __extract_rule(data)
    if res != nomatch:
        return name, res, value
    elif is_iterable(data) and len(data) == 2:
        res = __extract_rule(data[0])
        if res != nomatch:
            return name, res, data[1]
    elif callable(data):
        return __extract_rule_action(data(), data.__name__)

    raise Err("Don't know how to extract from {}", data)

def __mk_parser(name, rule, action):
    if isinstance(rule, ParseInfo):
        return __mk_fn_parser(name, rule, action)

    raise Err("Do not know what to do with {}", rule)

def mk_parser(top, name = ""):
    return __mk_parser(*__extract_rule_action(top, name))

def r0_inf(test):
    return ParseInfo(_zero_more, test)
def r0_1(test):
    return ParseInfo(_0_1, test)
def r1_inf(test):
    return ParseInfo(_one_more, test)
def seq(*tests):
    return ParseInfo(_match_seq, tests)
def choice(*tests):
    return ParseInfo(_match_any, tests)
def ne(test):
    return ParseInfo(_ne, test)
def eof():
    return nomatch, ignore
def sym(c): return ParseInfo(_match_symbol, c) \
        if c == nomatch or len(c) == 1 \
        else ParseInfo(_match_iterable, c)
<commit_msg>lookup rule to lookup for expression forward lookup w/o moving pointer<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-

# Copyright (c) 2012 Denis Zalevskiy
# Licensed under MIT License

from cor import *

nomatch = const('nomatch')
empty = const('empty')
end = const('end')

def ignore(*x): return empty
def value(x): return x
def first(x): return x[0]
second = nth(1)
def list2str(x): return ''.join(x)

is_parser_trace = True
debug_indent_level = 0
debug_indent_sym = '  '

def __indent_plus():
    global debug_indent_level
    debug_indent_level += 1

def __indent_minus(*args):
    global debug_indent_level
    debug_indent_level -= 1

debug_indent = Scope(__indent_plus, __indent_minus)

def debug_print(msg, *args, **kwargs):
    global debug_indent_sym, debug_indent_level
    print debug_indent_sym * debug_indent_level, \
        msg.format(*args, **kwargs)

def parser(name):
    def mk_name(name):
        return ''.join(['?', name])
    def deco(fn):
        global is_parser_trace
        fn.__name__ = mk_name(name)
        def wrapper(*args, **kwargs):
            global debug_indent
            debug_print("{}({}) {{", fn.__name__,
                        printable_args(*args, **kwargs))
            with debug_indent:
                res = fn(*args, **kwargs)
            debug_print("}} => {}", printable_args(res))
            return res
        if is_parser_trace:
            wrapper.__name__ = mk_name(name)
            return wrapper
        else:
            return fn
    return deco

class InfiniteInput(object):

    len_limit = 1024 * 64

    def __init__(self, src, begin = 0, end = None):
        self.__s = src
        self.__begin = begin
        self.__is_endless = end is None
        if end is None:
            self._end = lambda : len(src)
        elif callable(end):
            self._end = end
        else:
            self._end = lambda: end

    def __get_slice(self, k):
        start, stop = k.start, k.stop
        if not (k.step is None or k.step == 1):
            raise Err("Can't handle step != 1")
        start = self.__begin if start is None else self.__begin + start
        end = self._end if stop is None else self.__begin + stop
        return InfiniteInput(self.__s, start, end)

    def __getitem__(self, i):
        if isinstance(i, slice):
            return self.__get_slice(i)
        end = self._end()
        i = self.__begin + i
        if i < end:
            return self.__s[i]
        elif i > self.len_limit:
            raise Exception("Length limit is reached")
        else:
            return nomatch

    def __str__(self):
        return str(self.__s[self.__begin:self._end()])

    def __repr__(self):
        return ''.join(['"', str(self), '"'])

    def __len__(self):
        return self._end() - self.__begin

    def __iter__(self):
        def gen():
            pos = self.__begin
            while pos != self._end():
                yield self[pos]
                pos += 1
        return gen

    def as_string(self):
        if isinstance(self.__s, str):
            if self.__begin == 0 and self.__is_endless:
                return self.__s
            elif self.__is_endless:
                return self.__s[self.__begin:]
            else:
                return self.__s[self.__begin:self._end()]
        else:
            res = [x for x in self.__s]
            res.append(chr(0))
            return ''.join(res)

def source(src, begin = 0, end = None):
    return InfiniteInput(src, begin, end)

def _match(name, s, conv):
    @parser(name)
    def fn(src):
        v = src[0]
        return (1, conv(v)) if v == s else nomatch
    return fn

def _match_symbol(name, s, conv):
    if isinstance(s, str):
        if len(s) != 1:
            raise Exception("len != 1")
    elif s != nomatch:
        raise Exception("Not a string")
    return _match(name, s, conv)

def _match_string(name, s, conv):
    if not isinstance(s, str):
        raise Exception("Not a string")
    slen = len(s)
    @parser(name)
    def fn(src):
        if len(src) < slen:
            return nomatch
        v = src[0:slen].as_string()
        return (slen, conv(v)) if v == s else nomatch
    return fn

def _match_iterable(name, pat, conv):
    if not is_iterable(pat):
        raise Exception("Don't know what to do with {}".format(seq))

    seq = [x for x in pat] if isinstance(pat, str) else pat
    @parser(name)
    def fn(src):
        v = src[0]
        return (1, conv(v)) if v in seq else nomatch
    return fn

def _match_any(name, tests, conv):
    @parser(name)
    def fn(src):
        for test in tests:
            res = test(src)
            if res == nomatch:
                continue
            return (res[0], conv(res[1]))
        return nomatch
    return fn

def _match_seq(name, tests, conv):
    @parser(name)
    def fn(src):
        total = []
        pos = 0
        for test in tests:
            res = test(src[pos:])
            if res == nomatch:
                return nomatch
            if res[1] != empty:
                total.append(res[1])
            pos += res[0]
        return pos, conv(total)
    return fn

def _one_more(name, test, conv):
    @parser(name)
    def fn(src):
        total = []
        pos = 0
        res = test(src)
        if res == nomatch:
            return res
        while res != nomatch:
            total.append(res[1])
            pos += res[0]
            res = test(src[pos:])
        return pos, conv(total)
    return fn

def _zero_more(name, test, conv):
    @parser(name)
    def fn(src):
        total = []
        pos = 0
        res = test(src)
        while res != nomatch:
            total.append(res[1])
            pos += res[0]
            res = test(src[pos:])
        return pos, conv(total)
    return fn

def _0_1(name, test, conv):
    @parser(name)
    def fn(src):
        pos = 0
        res = test(src)
        return res[0], conv(res[1]) if res != nomatch else (0, empty)
    return fn

def _ne(name, test, conv):
    @parser(name)
    def fn(src):
        res = test(src)
        return (1, conv(src[0])) if res == nomatch else nomatch
    return fn

def _lookup(name, test, conv):
    @parser(name)
    def fn(src):
        res = test(src)
        return nomatch if res == nomatch else (0, res[1])
    return fn

def is_str(c):
    return isinstance(c, str) or c == nomatch

class ParseInfo(tuple):
    def __new__(cls, *args):
        return tuple.__new__(cls, args)

def __mk_fn_parser(name, rule, action):
    fn, data = rule
    if not is_str(data):
        if isinstance(data, ParseInfo):
            data = mk_parser(data)
        if is_iterable(data):
            data = [mk_parser(x) for x in data]
        else:
            data = mk_parser(data)
    return fn(name, data, action)

def __extract_rule(entity):
    if isinstance(entity, ParseInfo):
        return entity
    elif is_str(entity):
        return sym(entity)
    else:
        return nomatch

def __extract_rule_action(data, name = "?"):
    res = __extract_rule(data)
    if res != nomatch:
        return name, res, value
    elif is_iterable(data) and len(data) == 2:
        res = __extract_rule(data[0])
        if res != nomatch:
            return name, res, data[1]
    elif callable(data):
        return __extract_rule_action(data(), data.__name__)

    raise Err("Don't know how to extract from {}", data)

def __mk_parser(name, rule, action):
    if isinstance(rule, ParseInfo):
        return __mk_fn_parser(name, rule, action)

    raise Err("Do not know what to do with {}", rule)

def mk_parser(top, name = ""):
    return __mk_parser(*__extract_rule_action(top, name))

def r0_inf(test):
    return ParseInfo(_zero_more, test)
def r0_1(test):
    return ParseInfo(_0_1, test)
def r1_inf(test):
    return ParseInfo(_one_more, test)
def seq(*tests):
    return ParseInfo(_match_seq, tests)
def choice(*tests):
    return ParseInfo(_match_any, tests)
def ne(test):
    return ParseInfo(_ne, test)
def eof():
    return nomatch, ignore
def sym(c): return ParseInfo(_match_symbol, c) \
        if c == nomatch or len(c) == 1 \
        else ParseInfo(_match_iterable, c)

def lookup(rule):
    def rule_fn():
        return ParseInfo(_lookup, rule), ignore
    rule_fn.__name__ = '_'.join(['lookup', parser.__name__])
    return rule_fn
<|endoftext|>


<commit_before># cerbero - a multi-platform build system for Open Source software
# Copyright (C) 2012 Andoni Morales Alastruey <ylatuya@gmail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 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
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

import os
import shutil
import tarfile
import tempfile

import cerbero.utils.messages as m
from cerbero.utils import shell, _, replace_prefix, is_text_file
from cerbero.enums import Platform
from cerbero.errors import FatalError, UsageError, EmptyPackageError
from cerbero.packages import PackagerBase, PackageType
from cerbero.tools import strip
from functools import lru_cache

RESTORE_SUFFIX = '.relocation_restore'

class DistTarball(PackagerBase):
    ''' Creates a distribution tarball '''

    def __init__(self, config, package, store):
        PackagerBase.__init__(self, config, package, store)
        self.package = package
        self.prefix = config.prefix
        self.package_prefix = ''
        if self.config.packages_prefix is not None:
            self.package_prefix = '%s-' % self.config.packages_prefix
        self.compress = config.package_tarball_compression
        if self.compress not in ('bz2', 'xz'):
            raise UsageError('Invalid compression type {!r}'.format(self.compress))

    @lru_cache(maxsize=None)
    def _files_list(self, devel=True, force=True, split=True):
        try:
            dist_files = super().files_list(PackageType.RUNTIME, force)
        except EmptyPackageError:
            m.warning(_("The runtime package is empty"))
            dist_files = []

        if devel:
            try:
                devel_files = super().files_list(PackageType.DEVEL, force)
            except EmptyPackageError:
                m.warning(_("The development package is empty"))
                devel_files = []
        else:
            devel_files = []

        if not split:
            dist_files += devel_files

        if not dist_files and not devel_files:
            raise EmptyPackageError(self.package.name)

        return dist_files, devel_files

    def pack(self, output_dir, devel=True, force=False, keep_temp=False,
             split=True, package_prefix='', strip_binaries=False, force_empty=False,
             relocatable=False, lib64_link=False):
        dist_files = []
        devel_files = []
        try:
            dist_files, devel_files = self._files_list(force=force, devel=devel, split=split)
        except EmptyPackageError:
            pass
        filenames = []
        create_tarball_func = self._create_tarball if not strip_binaries else self._create_tarball_stripped
        if dist_files or force_empty:
            runtime = create_tarball_func(output_dir, PackageType.RUNTIME,
                                          dist_files, force, package_prefix,
                                          relocatable, lib64_link)
            filenames.append(runtime)

        if split and devel and (len(devel_files) != 0 or force_empty):
            devel = create_tarball_func(output_dir, PackageType.DEVEL,
                                        devel_files, force, package_prefix,
                                        relocatable, lib64_link)
            filenames.append(devel)
        return filenames

    def get_name(self, package_type, ext=None):
        if ext is None:
            ext = 'tar.' + self.compress

        if self.config.target_platform != Platform.WINDOWS:
            platform = self.config.target_platform
        elif self.config.variants.visualstudio:
            platform = 'msvc'
        else:
            platform = 'mingw'

        # Use _files_list() to just to check whether the package is an empty
        # package or not. In case of any error attempting to collect the files,
        # we assume there are no files needed for the package.
        try:
            self._files_list(force=True, devel=True, split=True)
        except Exception:
            return ""

        # Ensure there are no slashes in package version. e.g.
        # 19+git~origin/master-e65a012bc0001ab7a4e351dbed6af4cc to
        # 19+git~origin@master-e65a012bc0001ab7a4e351dbed6af4cc
        package_version = self.package.version.replace('/', '@')
        return "%s%s-%s-%s-%s%s.%s" % (self.package_prefix, self.package.name, platform,
                                       self.config.target_arch, package_version, package_type, ext)

    def _create_tarball_stripped(self, output_dir, package_type, files, force,
                                 package_prefix, relocatable, lib64_link):
        tmpdir = tempfile.mkdtemp(dir=self.config.home_dir)

        if hasattr(self.package, 'strip_excludes'):
            s = strip.Strip(self.config, self.package.strip_excludes)
        else:
            s = strip.Strip(self.config)

        for f in files:
            orig_file = os.path.join(self.prefix, f)
            tmp_file = os.path.join(tmpdir, f)
            tmp_file_dir = os.path.dirname(tmp_file)
            if not os.path.exists(tmp_file_dir):
                os.makedirs(tmp_file_dir)
            shutil.copy(orig_file, tmp_file, follow_symlinks=False)
            s.strip_file(tmp_file)

        prefix_restore = self.prefix
        self.prefix = tmpdir
        tarball = self._create_tarball(output_dir, package_type,
                                       files, force, package_prefix,
                                       relocatable, lib64_link)
        self.prefix = prefix_restore
        shutil.rmtree(tmpdir)

        return tarball

    def _create_tarball(self, output_dir, package_type, files, force,
                        package_prefix, relocatable, lib64_link):
        filename = os.path.join(output_dir, self.get_name(package_type))
        if os.path.exists(filename):
            if force:
                os.remove(filename)
            else:
                raise UsageError("File %s already exists" % filename)

        tar_files = []
        restore_files = []
        for f in files:
            filepath = os.path.join(self.prefix, f)
            if relocatable and not os.path.islink(filepath):
                if os.path.splitext(f)[1] in ['.la', '.pc'] or ('bin' in os.path.splitext(f)[0] and is_text_file(filepath)):
                    shutil.copy(filepath, filepath + RESTORE_SUFFIX)
                    restore_files.append(filepath)
                    with open(filepath, 'r+') as fo:
                        content = fo.read()
                        content = replace_prefix(self.config.prefix, content, 'CERBERO_PREFIX')
                        fo.seek(0)
                        fo.write(content)
                        fo.truncate()
                        fo.flush()
                        tar_files.append(filepath)
                else:
                    tar_files.append(filepath)
            else:
                tar_files.append(filepath)

        # This link allows to rpm packager to install the libs
        # in lib64 instead of lib without changing where cerbero
        # is installing its build artifacts.
        if lib64_link:
            filepath = os.path.join(self.prefix, 'lib64')
            try:
                os.symlink('lib', filepath)
            except OSError:
                pass
            files.append(filepath)

        if self.config.platform == Platform.WINDOWS:
            self._write_tarfile(filename, package_prefix, tar_files)
        else:
            self._write_tar(filename, package_prefix, tar_files)

        # Restore original files
        for f in restore_files:
            if os.path.isfile(f) and os.path.isfile(f + RESTORE_SUFFIX):
                shutil.copy(f + RESTORE_SUFFIX, f)
                os.remove(f + RESTORE_SUFFIX)

        if lib64_link:
            os.unlink(filepath)

        return filename

    def _write_tarfile(self, filename, package_prefix, files):
        try:
            with tarfile.open(filename, 'w:' + self.compress) as tar:
                for f in files:
                    base_filepath = f.replace(self.prefix, '')
                    base_filepath = base_filepath.lstrip('/').rstrip('\\')
                    tar.add(f, os.path.join(package_prefix, base_filepath))
        except OSError:
            os.replace(filename, filename + '.partial')
            raise

    def _write_tar(self, filename, package_prefix, files):
        tar_cmd = ['tar', '-C', self.prefix, '-cf', filename]
        # convert absolute paths to relative paths to the prefix
        for i, file in enumerate(files):
            if self.prefix in file:
                files[i] = file.replace(self.prefix, '')
                files[i] = files[i].lstrip('/').rstrip('\\')
        if package_prefix:
            # Only transform the files (and not symbolic/hard links)
            tar_cmd += ['--transform', 'flags=r;s|^|{}/|'.format(package_prefix)]
        if self.compress == 'bz2':
            # Use lbzip2 when available for parallel compression
            if shutil.which('lbzip2'):
                tar_cmd += ['--use-compress-program=lbzip2']
            else:
                tar_cmd += ['--bzip2']
        elif self.compress == 'xz':
            tar_cmd += ['--use-compress-program=xz --threads=0']
        try:
            shell.new_call(tar_cmd + files)
        except FatalError:
            os.replace(filename, filename + '.partial')
            raise

class Packager(object):

    def __new__(klass, config, package, store):
        return DistTarball(config, package, store)

def register():
    from cerbero.packages.packager import register_packager
    from cerbero.config import Distro
    register_packager(Distro.NONE, Packager)
    register_packager(Distro.GENTOO, Packager)
<commit_msg>Yet another fix for empty packages<commit_after># cerbero - a multi-platform build system for Open Source software
# Copyright (C) 2012 Andoni Morales Alastruey <ylatuya@gmail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 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
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

import os
import shutil
import tarfile
import tempfile

import cerbero.utils.messages as m
from cerbero.utils import shell, _, replace_prefix, is_text_file
from cerbero.enums import Platform
from cerbero.errors import FatalError, UsageError, EmptyPackageError
from cerbero.packages import PackagerBase, PackageType
from cerbero.tools import strip
from functools import lru_cache

RESTORE_SUFFIX = '.relocation_restore'

class DistTarball(PackagerBase):
    ''' Creates a distribution tarball '''

    def __init__(self, config, package, store):
        PackagerBase.__init__(self, config, package, store)
        self.package = package
        self.prefix = config.prefix
        self.package_prefix = ''
        if self.config.packages_prefix is not None:
            self.package_prefix = '%s-' % self.config.packages_prefix
        self.compress = config.package_tarball_compression
        if self.compress not in ('bz2', 'xz'):
            raise UsageError('Invalid compression type {!r}'.format(self.compress))

    @lru_cache(maxsize=None)
    def _files_list(self, devel=True, force=True, split=True):
        try:
            dist_files = super().files_list(PackageType.RUNTIME, force)
        except EmptyPackageError:
            m.warning(_("The runtime package is empty"))
            dist_files = []

        if devel:
            try:
                devel_files = super().files_list(PackageType.DEVEL, force)
            except EmptyPackageError:
                m.warning(_("The development package is empty"))
                devel_files = []
        else:
            devel_files = []

        if not split:
            dist_files += devel_files

        if not dist_files and not devel_files:
            raise EmptyPackageError(self.package.name)

        return dist_files, devel_files

    def pack(self, output_dir, devel=True, force=False, keep_temp=False,
             split=True, package_prefix='', strip_binaries=False, force_empty=False,
             relocatable=False, lib64_link=False):
        dist_files = []
        devel_files = []
        try:
            dist_files, devel_files = self._files_list(force=force, devel=devel, split=split)
        except EmptyPackageError:
            pass
        filenames = []
        create_tarball_func = self._create_tarball if not strip_binaries else self._create_tarball_stripped
        if dist_files or force_empty:
            runtime = create_tarball_func(output_dir, PackageType.RUNTIME,
                                          dist_files, force, package_prefix,
                                          relocatable, lib64_link)
            filenames.append(runtime)

        if split and devel and (len(devel_files) != 0 or force_empty):
            devel = create_tarball_func(output_dir, PackageType.DEVEL,
                                        devel_files, force, package_prefix,
                                        relocatable, lib64_link)
            filenames.append(devel)
        return filenames

    def get_name(self, package_type, ext=None):
        if ext is None:
            ext = 'tar.' + self.compress

        if self.config.target_platform != Platform.WINDOWS:
            platform = self.config.target_platform
        elif self.config.variants.visualstudio:
            platform = 'msvc'
        else:
            platform = 'mingw'

        # Use [devel_]files_list() just to check whether the package is an empty
        # package or not. In case of any error attempting to collect the files,
        # we assume there are no files needed for the package. We use this approach
        # instead of _files_list() because the latter checks for existing files
        # and throws exceptions in case of empty package.
        try:
            files = []
            if package_type == PackageType.DEVEL:
                files = self.package.devel_files_list()
            elif package_type == PackageType.RUNTIME:
                files = self.package.files_list()

            if len(files) == 0:
                return ""
        except Exception:
            return ""

        # Ensure there are no slashes in package version. e.g.
        # 19+git~origin/master-e65a012bc0001ab7a4e351dbed6af4cc to
        # 19+git~origin@master-e65a012bc0001ab7a4e351dbed6af4cc
        package_version = self.package.version.replace('/', '@')
        return "%s%s-%s-%s-%s%s.%s" % (self.package_prefix, self.package.name, platform,
                                       self.config.target_arch, package_version, package_type, ext)

    def _create_tarball_stripped(self, output_dir, package_type, files, force,
                                 package_prefix, relocatable, lib64_link):
        tmpdir = tempfile.mkdtemp(dir=self.config.home_dir)

        if hasattr(self.package, 'strip_excludes'):
            s = strip.Strip(self.config, self.package.strip_excludes)
        else:
            s = strip.Strip(self.config)

        for f in files:
            orig_file = os.path.join(self.prefix, f)
            tmp_file = os.path.join(tmpdir, f)
            tmp_file_dir = os.path.dirname(tmp_file)
            if not os.path.exists(tmp_file_dir):
                os.makedirs(tmp_file_dir)
            shutil.copy(orig_file, tmp_file, follow_symlinks=False)
            s.strip_file(tmp_file)

        prefix_restore = self.prefix
        self.prefix = tmpdir
        tarball = self._create_tarball(output_dir, package_type,
                                       files, force, package_prefix,
                                       relocatable, lib64_link)
        self.prefix = prefix_restore
        shutil.rmtree(tmpdir)

        return tarball

    def _create_tarball(self, output_dir, package_type, files, force,
                        package_prefix, relocatable, lib64_link):
        filename = os.path.join(output_dir, self.get_name(package_type))
        if os.path.exists(filename):
            if force:
                os.remove(filename)
            else:
                raise UsageError("File %s already exists" % filename)

        tar_files = []
        restore_files = []
        for f in files:
            filepath = os.path.join(self.prefix, f)
            if relocatable and not os.path.islink(filepath):
                if os.path.splitext(f)[1] in ['.la', '.pc'] or ('bin' in os.path.splitext(f)[0] and is_text_file(filepath)):
                    shutil.copy(filepath, filepath + RESTORE_SUFFIX)
                    restore_files.append(filepath)
                    with open(filepath, 'r+') as fo:
                        content = fo.read()
                        content = replace_prefix(self.config.prefix, content, 'CERBERO_PREFIX')
                        fo.seek(0)
                        fo.write(content)
                        fo.truncate()
                        fo.flush()
                        tar_files.append(filepath)
                else:
                    tar_files.append(filepath)
            else:
                tar_files.append(filepath)

        # This link allows to rpm packager to install the libs
        # in lib64 instead of lib without changing where cerbero
        # is installing its build artifacts.
        if lib64_link:
            filepath = os.path.join(self.prefix, 'lib64')
            try:
                os.symlink('lib', filepath)
            except OSError:
                pass
            files.append(filepath)

        if self.config.platform == Platform.WINDOWS:
            self._write_tarfile(filename, package_prefix, tar_files)
        else:
            self._write_tar(filename, package_prefix, tar_files)

        # Restore original files
        for f in restore_files:
            if os.path.isfile(f) and os.path.isfile(f + RESTORE_SUFFIX):
                shutil.copy(f + RESTORE_SUFFIX, f)
                os.remove(f + RESTORE_SUFFIX)

        if lib64_link:
            os.unlink(filepath)

        return filename

    def _write_tarfile(self, filename, package_prefix, files):
        try:
            with tarfile.open(filename, 'w:' + self.compress) as tar:
                for f in files:
                    base_filepath = f.replace(self.prefix, '')
                    base_filepath = base_filepath.lstrip('/').rstrip('\\')
                    tar.add(f, os.path.join(package_prefix, base_filepath))
        except OSError:
            os.replace(filename, filename + '.partial')
            raise

    def _write_tar(self, filename, package_prefix, files):
        tar_cmd = ['tar', '-C', self.prefix, '-cf', filename]
        # convert absolute paths to relative paths to the prefix
        for i, file in enumerate(files):
            if self.prefix in file:
                files[i] = file.replace(self.prefix, '')
                files[i] = files[i].lstrip('/').rstrip('\\')
        if package_prefix:
            # Only transform the files (and not symbolic/hard links)
            tar_cmd += ['--transform', 'flags=r;s|^|{}/|'.format(package_prefix)]
        if self.compress == 'bz2':
            # Use lbzip2 when available for parallel compression
            if shutil.which('lbzip2'):
                tar_cmd += ['--use-compress-program=lbzip2']
            else:
                tar_cmd += ['--bzip2']
        elif self.compress == 'xz':
            tar_cmd += ['--use-compress-program=xz --threads=0']
        try:
            shell.new_call(tar_cmd + files)
        except FatalError:
            os.replace(filename, filename + '.partial')
            raise

class Packager(object):

    def __new__(klass, config, package, store):
        return DistTarball(config, package, store)

def register():
    from cerbero.packages.packager import register_packager
    from cerbero.config import Distro
    register_packager(Distro.NONE, Packager)
    register_packager(Distro.GENTOO, Packager)
<|endoftext|>