<commit_before>import random
from collections import OrderedDict
from copy import deepcopy
import gym
from gym_minigrid.roomgrid import RoomGrid
from gym_minigrid.minigrid import LockedDoor
from .verifier import *

class RejectSampling(Exception):
    """
    Exception used for rejection sampling
    """

    pass

class RoomGridLevel(RoomGrid):
    """
    Base for levels based on RoomGrid
    A level, given a random seed, generates missions generated from
    one or more patterns. Levels should produce a family of missions
    of approximately similar difficulty.
    """

    def __init__(
        self,
        room_size=8,
        **kwargs
    ):
        super().__init__(
            room_size=room_size,
            **kwargs
        )

    def reset(self, **kwargs):
        obs = super().reset(**kwargs)

        # Recreate the verifier
        self.instrs.reset_verifier(self)

        # Compute the time step limit based on the maze size and instructions
        nav_time_room = self.room_size ** 2
        nav_time_maze = nav_time_room * self.num_rows * self.num_cols
        num_navs = self.num_navs_needed(self.instrs)
        self.max_steps = num_navs * nav_time_maze

        return obs

    def step(self, action):
        obs, reward, done, info = super().step(action)

        # If we drop an object, we need to update its position in the environment
        if action == self.actions.drop:
            self.update_objs_poss()

        # If we've successfully completed the mission
        status = self.instrs.verify(action)

        if status is 'success':
            done = True
            reward = self._reward()
        elif status is 'failure':
            done = True
            reward = 0

        return obs, reward, done, info

    def update_objs_poss(self, instr=None):
        if instr is None:
            instr = self.instrs
        if isinstance(instr, BeforeInstr) or isinstance(instr, AndInstr) or isinstance(instr, AfterInstr):
            self.update_objs_poss(instr.instr_a)
            self.update_objs_poss(instr.instr_b)
        else:
            instr.update_objs_poss()

    def _gen_grid(self, width, height):
        # We catch RecursionError to deal with rare cases where
        # rejection sampling gets stuck in an infinite loop
        while True:
            try:
                super()._gen_grid(width, height)

                # Generate the mission
                self.gen_mission()

                # Validate the instructions
                self.validate_instrs(self.instrs)

            except RecursionError as error:
                print('Timeout during mission generation:', error)
                continue

            except RejectSampling as error:
                #print('Sampling rejected:', error)
                continue

            break

        # Generate the surface form for the instructions
        self.surface = self.instrs.surface(self)
        self.mission = self.surface

    def validate_instrs(self, instr):
        """
        Perform some validation on the generated instructions
        """
        # Gather the colors of locked doors
        if self.unblocking:
            self.colors_of_locked_doors = []
            for i in range(self.num_rows):
                for j in range(self.num_cols):
                    room = self.get_room(i, j)
                    for door in room.doors:
                        if door and isinstance(door, LockedDoor):
                            self.colors_of_locked_doors.append(door.color)

        if isinstance(instr, PutNextInstr):
            # Resolve the objects referenced by the instruction
            instr.reset_verifier(self)

            # Check that the objects are not already next to each other
            if instr.objs_next():
                raise RejectSampling('objs already next to each other')

            # Check that we are not asking to move an object next to itself
            move = instr.desc_move
            fixed = instr.desc_fixed
            if len(move.obj_set) == 1 and len(fixed.obj_set) == 1:
                if move.obj_set[0] is fixed.obj_set[0]:
                    raise RejectSampling('cannot move an object next to itself')

        if isinstance(instr, ActionInstr):
            # TODO: either relax this a bit or make the bot handle this super corner-y scenarios
            # Check that the instruction doesn't involve a key that matches the color of a locked door
            potential_objects = ('desc', 'desc_move', 'desc_fixed')
            for attr in potential_objects:
                if hasattr(instr, attr):
                    obj = getattr(instr, attr)
                    if obj.type == 'key' and obj.color in self.colors_of_locked_doors:
                        raise RejectSampling('cannot do anything with/to a key that can be used to open a door')
            return

        if isinstance(instr, SeqInstr):
            self.validate_instrs(instr.instr_a)
            self.validate_instrs(instr.instr_b)
            return

        assert False, "unhandled instruction type"

    def gen_mission(self):
        """
        Generate a mission (instructions and matching environment)
        Derived level classes should implement this method
        """
        raise NotImplementedError

    @property
    def level_name(self):
        return self.__class__.level_name

    @property
    def gym_id(self):
        return self.__class__.gym_id

    def num_navs_needed(self, instr):
        """
        Compute the maximum number of navigations needed to perform
        a simple or complex instruction
        """

        if isinstance(instr, PutNextInstr):
            return 2

        if isinstance(instr, ActionInstr):
            return 1

        if isinstance(instr, SeqInstr):
            na = self.num_navs_needed(instr.instr_a)
            nb = self.num_navs_needed(instr.instr_b)
            return na + nb

    def open_all_doors(self):
        """
        Open all the doors in the maze
        """

        for i in range(self.num_rows):
            for j in range(self.num_cols):
                room = self.get_room(i, j)
                for door in room.doors:
                    if door:
                        door.is_open = True

    def check_objs_reachable(self, raise_exc=True):
        """
        Check that all objects are reachable from the agent's starting
        position without requiring any other object to be moved
        (without unblocking)
        """

        # Reachable positions
        reachable = set()

        # Work list
        stack = [self.start_pos]

        while len(stack) > 0:
            i, j = stack.pop()

            if i < 0 or i >= self.grid.width or j < 0 or j >= self.grid.height:
                continue

            if (i, j) in reachable:
                continue

            # This position is reachable
            reachable.add((i, j))

            cell = self.grid.get(i, j)

            # If there is something other than a door in this cell, it
            # blocks reachability
            if cell and cell.type is not 'door':
                continue

            # Visit the horizontal and vertical neighbors
            stack.append((i+1, j))
            stack.append((i-1, j))
            stack.append((i, j+1))
            stack.append((i, j-1))

        # Check that all objects are reachable
        for i in range(self.grid.width):
            for j in range(self.grid.height):
                cell = self.grid.get(i, j)

                if not cell or cell.type is 'wall':
                    continue

                if (i, j) not in reachable:
                    if not raise_exc:
                        return False
                    raise RejectSampling('unreachable object at ' + str((i, j)))

        # All objects reachable
        return True

class LevelGen(RoomGridLevel):
    """
    Level generator which attempts to produce every possible sentence in
    the baby language as an instruction.
    """

    def __init__(
        self,
        room_size=8,
        num_rows=3,
        num_cols=3,
        num_dists=18,
        locked_room_prob=0.5,
        locations=True,
        unblocking=True,
        implicit_unlock=True,
        action_kinds=['goto', 'pickup', 'open', 'putnext'],
        instr_kinds=['action', 'and', 'seq'],
        seed=None
    ):
        self.num_dists = num_dists
        self.locked_room_prob = locked_room_prob
        self.locations = locations
        self.unblocking = unblocking
        self.implicit_unlock = implicit_unlock
        self.action_kinds = action_kinds
        self.instr_kinds = instr_kinds

        self.locked_room = None

        super().__init__(
            room_size=room_size,
            num_rows=num_rows,
            num_cols=num_cols,
            seed=seed
        )

    def gen_mission(self):
        self.place_agent()

        if self._rand_float(0, 1) < self.locked_room_prob:
            self.add_locked_room()

        self.connect_all()

        self.add_distractors(num_distractors=self.num_dists, all_unique=False)

        # If no unblocking required, make sure all objects are
        # reachable without unblocking
        if not self.unblocking:
            self.check_objs_reachable()

        # Generate random instructions
        self.instrs = self.rand_instr(
            action_kinds=self.action_kinds,
            instr_kinds=self.instr_kinds
        )

    def add_locked_room(self):
        start_room = self.room_from_pos(*self.start_pos)

        # Until we've successfully added a locked room
        while True:
            i = self._rand_int(0, self.num_cols)
            j = self._rand_int(0, self.num_rows)
            door_idx = self._rand_int(0, 4)
            self.locked_room = self.get_room(i, j)

            # Don't lock the room the agent starts in
            if self.locked_room is start_room:
                continue

            # Don't add a locked door in an external wall
            if self.locked_room.neighbors[door_idx] is None:
                continue

            door, _ = self.add_door(
                i, j,
                door_idx,
                locked=True
            )

            # Done adding locked room
            break

        # Until we find a room to put the key
        while True:
            i = self._rand_int(0, self.num_cols)
            j = self._rand_int(0, self.num_rows)
            key_room = self.get_room(i, j)

            if key_room is self.locked_room:
                continue

            self.add_object(i, j, 'key', door.color)
            break

    def rand_obj(self, types=OBJ_TYPES, colors=COLOR_NAMES, max_tries=100):
        """
        Generate a random object descriptor
        """

        num_tries = 0

        # Keep trying until we find a matching object
        while True:
            if num_tries > max_tries:
                raise RecursionError('failed to find suitable object')
            num_tries += 1

            color = self._rand_elem([None, *colors])
            type = self._rand_elem(types)

            loc = None
            if self.locations and self._rand_bool():
                loc = self._rand_elem(LOC_NAMES)

            desc = ObjDesc(type, color, loc)

            # Find all objects matching the descriptor
            objs, poss = desc.find_matching_objs(self)

            # The description must match at least one object
            if len(objs) == 0:
                continue

            # If no implicit unlocking is required
            if not self.implicit_unlock and self.locked_room:
                # Check that at least one object is not in the locked room
                pos_not_locked = list(filter(
                    lambda p: not self.locked_room.pos_inside(*p),
                    poss
                ))

                if len(pos_not_locked) == 0:
                    continue

            # Found a valid object description
            return desc

    def rand_instr(
        self,
        action_kinds,
        instr_kinds,
        depth=0
    ):
        """
        Generate random instructions
        """

        kind = self._rand_elem(instr_kinds)

        if kind is 'action':
            action = self._rand_elem(action_kinds)

            if action is 'goto':
                return GoToInstr(self.rand_obj())
            elif action is 'pickup':
                return PickupInstr(self.rand_obj(types=OBJ_TYPES_NOT_DOOR))
            elif action is 'open':
                return OpenInstr(self.rand_obj(types=['door']))
            elif action is 'putnext':
                return PutNextInstr(
                    self.rand_obj(types=OBJ_TYPES_NOT_DOOR),
                    self.rand_obj()
                )

            assert False

        elif kind is 'and':
            instr_a = self.rand_instr(
                action_kinds=action_kinds,
                instr_kinds=['action'],
                depth=depth+1
            )
            instr_b = self.rand_instr(
                action_kinds=action_kinds,
                instr_kinds=['action'],
                depth=depth+1
            )
            return AndInstr(instr_a, instr_b)

        elif kind is 'seq':
            instr_a = self.rand_instr(
                action_kinds=action_kinds,
                instr_kinds=['action', 'and'],
                depth=depth+1
            )
            instr_b = self.rand_instr(
                action_kinds=action_kinds,
                instr_kinds=['action', 'and'],
                depth=depth+1
            )

            kind = self._rand_elem(['before', 'after'])

            if kind is 'before':
                return BeforeInstr(instr_a, instr_b)
            elif kind is 'after':
                return AfterInstr(instr_a, instr_b)

            assert False

        assert False

# Dictionary of levels, indexed by name, lexically sorted
level_dict = OrderedDict()

def register_levels(module_name, globals):
    """
    Register OpenAI gym environments for all levels in a file
    """

    # Iterate through global names
    for global_name in sorted(list(globals.keys())):
        if not global_name.startswith('Level_'):
            continue

        level_name = global_name.split('Level_')[-1]
        level_class = globals[global_name]

        # Register the levels with OpenAI Gym
        gym_id = 'BabyAI-%s-v0' % (level_name)
        entry_point = '%s:%s' % (module_name, global_name)
        gym.envs.registration.register(
            id=gym_id,
            entry_point=entry_point,
        )

        # Add the level to the dictionary
        level_dict[level_name] = level_class

        # Store the name and gym id on the level class
        level_class.level_name = level_name
        level_class.gym_id = gym_id

def test():
    for idx, level_name in enumerate(level_dict.keys()):
        print('Level %s (%d/%d)' % (level_name, idx+1, len(level_dict)))

        level = level_dict[level_name]

        # Run the mission for a few episodes
        rng = random.Random(0)
        num_episodes = 0
        for i in range(0, 15):
            mission = level(seed=i)

            # Check that the surface form was generated
            assert isinstance(mission.surface, str)
            assert len(mission.surface) > 0
            obs = mission.reset()
            assert obs['mission'] == mission.surface

            # Reduce max_steps because otherwise tests take too long
            mission.max_steps = min(mission.max_steps, 200)

            # Check for some known invalid patterns in the surface form
            import re
            surface = mission.surface
            assert not re.match(r".*pick up the [^ ]*door.*", surface), surface

            while True:
                action = rng.randint(0, mission.action_space.n - 1)
                obs, reward, done, info = mission.step(action)
                if done:
                    obs = mission.reset()
                    break

            num_episodes += 1

        # The same seed should always yield the same mission
        m0 = level(seed=0)
        m1 = level(seed=0)
        grid1 = m0.unwrapped.grid
        grid2 = m1.unwrapped.grid
        assert grid1 == grid2
        assert m0.surface == m1.surface

    # Check that gym environment names were registered correctly
    gym.make('BabyAI-1RoomS8-v0')
    gym.make('BabyAI-BossLevel-v0')
<commit_msg>Some levels don't have the unblocking attribute. Fix that in the validation.<commit_after>import random
from collections import OrderedDict
from copy import deepcopy
import gym
from gym_minigrid.roomgrid import RoomGrid
from gym_minigrid.minigrid import LockedDoor
from .verifier import *

class RejectSampling(Exception):
    """
    Exception used for rejection sampling
    """

    pass

class RoomGridLevel(RoomGrid):
    """
    Base for levels based on RoomGrid
    A level, given a random seed, generates missions generated from
    one or more patterns. Levels should produce a family of missions
    of approximately similar difficulty.
    """

    def __init__(
        self,
        room_size=8,
        **kwargs
    ):
        super().__init__(
            room_size=room_size,
            **kwargs
        )

    def reset(self, **kwargs):
        obs = super().reset(**kwargs)

        # Recreate the verifier
        self.instrs.reset_verifier(self)

        # Compute the time step limit based on the maze size and instructions
        nav_time_room = self.room_size ** 2
        nav_time_maze = nav_time_room * self.num_rows * self.num_cols
        num_navs = self.num_navs_needed(self.instrs)
        self.max_steps = num_navs * nav_time_maze

        return obs

    def step(self, action):
        obs, reward, done, info = super().step(action)

        # If we drop an object, we need to update its position in the environment
        if action == self.actions.drop:
            self.update_objs_poss()

        # If we've successfully completed the mission
        status = self.instrs.verify(action)

        if status is 'success':
            done = True
            reward = self._reward()
        elif status is 'failure':
            done = True
            reward = 0

        return obs, reward, done, info

    def update_objs_poss(self, instr=None):
        if instr is None:
            instr = self.instrs
        if isinstance(instr, BeforeInstr) or isinstance(instr, AndInstr) or isinstance(instr, AfterInstr):
            self.update_objs_poss(instr.instr_a)
            self.update_objs_poss(instr.instr_b)
        else:
            instr.update_objs_poss()

    def _gen_grid(self, width, height):
        # We catch RecursionError to deal with rare cases where
        # rejection sampling gets stuck in an infinite loop
        while True:
            try:
                super()._gen_grid(width, height)

                # Generate the mission
                self.gen_mission()

                # Validate the instructions
                self.validate_instrs(self.instrs)

            except RecursionError as error:
                print('Timeout during mission generation:', error)
                continue

            except RejectSampling as error:
                #print('Sampling rejected:', error)
                continue

            break

        # Generate the surface form for the instructions
        self.surface = self.instrs.surface(self)
        self.mission = self.surface

    def validate_instrs(self, instr):
        """
        Perform some validation on the generated instructions
        """
        # Gather the colors of locked doors
        if hasattr(self, 'unblocking') and self.unblocking:
            self.colors_of_locked_doors = []
            for i in range(self.num_rows):
                for j in range(self.num_cols):
                    room = self.get_room(i, j)
                    for door in room.doors:
                        if door and isinstance(door, LockedDoor):
                            self.colors_of_locked_doors.append(door.color)

        if isinstance(instr, PutNextInstr):
            # Resolve the objects referenced by the instruction
            instr.reset_verifier(self)

            # Check that the objects are not already next to each other
            if instr.objs_next():
                raise RejectSampling('objs already next to each other')

            # Check that we are not asking to move an object next to itself
            move = instr.desc_move
            fixed = instr.desc_fixed
            if len(move.obj_set) == 1 and len(fixed.obj_set) == 1:
                if move.obj_set[0] is fixed.obj_set[0]:
                    raise RejectSampling('cannot move an object next to itself')

        if isinstance(instr, ActionInstr):
            if not hasattr(self, 'unblocking') or not self.unblocking:
                return
            # TODO: either relax this a bit or make the bot handle this super corner-y scenarios
            # Check that the instruction doesn't involve a key that matches the color of a locked door
            potential_objects = ('desc', 'desc_move', 'desc_fixed')
            for attr in potential_objects:
                if hasattr(instr, attr):
                    obj = getattr(instr, attr)
                    if obj.type == 'key' and obj.color in self.colors_of_locked_doors:
                        raise RejectSampling('cannot do anything with/to a key that can be used to open a door')
            return

        if isinstance(instr, SeqInstr):
            self.validate_instrs(instr.instr_a)
            self.validate_instrs(instr.instr_b)
            return

        assert False, "unhandled instruction type"

    def gen_mission(self):
        """
        Generate a mission (instructions and matching environment)
        Derived level classes should implement this method
        """
        raise NotImplementedError

    @property
    def level_name(self):
        return self.__class__.level_name

    @property
    def gym_id(self):
        return self.__class__.gym_id

    def num_navs_needed(self, instr):
        """
        Compute the maximum number of navigations needed to perform
        a simple or complex instruction
        """

        if isinstance(instr, PutNextInstr):
            return 2

        if isinstance(instr, ActionInstr):
            return 1

        if isinstance(instr, SeqInstr):
            na = self.num_navs_needed(instr.instr_a)
            nb = self.num_navs_needed(instr.instr_b)
            return na + nb

    def open_all_doors(self):
        """
        Open all the doors in the maze
        """

        for i in range(self.num_rows):
            for j in range(self.num_cols):
                room = self.get_room(i, j)
                for door in room.doors:
                    if door:
                        door.is_open = True

    def check_objs_reachable(self, raise_exc=True):
        """
        Check that all objects are reachable from the agent's starting
        position without requiring any other object to be moved
        (without unblocking)
        """

        # Reachable positions
        reachable = set()

        # Work list
        stack = [self.start_pos]

        while len(stack) > 0:
            i, j = stack.pop()

            if i < 0 or i >= self.grid.width or j < 0 or j >= self.grid.height:
                continue

            if (i, j) in reachable:
                continue

            # This position is reachable
            reachable.add((i, j))

            cell = self.grid.get(i, j)

            # If there is something other than a door in this cell, it
            # blocks reachability
            if cell and cell.type is not 'door':
                continue

            # Visit the horizontal and vertical neighbors
            stack.append((i+1, j))
            stack.append((i-1, j))
            stack.append((i, j+1))
            stack.append((i, j-1))

        # Check that all objects are reachable
        for i in range(self.grid.width):
            for j in range(self.grid.height):
                cell = self.grid.get(i, j)

                if not cell or cell.type is 'wall':
                    continue

                if (i, j) not in reachable:
                    if not raise_exc:
                        return False
                    raise RejectSampling('unreachable object at ' + str((i, j)))

        # All objects reachable
        return True

class LevelGen(RoomGridLevel):
    """
    Level generator which attempts to produce every possible sentence in
    the baby language as an instruction.
    """

    def __init__(
        self,
        room_size=8,
        num_rows=3,
        num_cols=3,
        num_dists=18,
        locked_room_prob=0.5,
        locations=True,
        unblocking=True,
        implicit_unlock=True,
        action_kinds=['goto', 'pickup', 'open', 'putnext'],
        instr_kinds=['action', 'and', 'seq'],
        seed=None
    ):
        self.num_dists = num_dists
        self.locked_room_prob = locked_room_prob
        self.locations = locations
        self.unblocking = unblocking
        self.implicit_unlock = implicit_unlock
        self.action_kinds = action_kinds
        self.instr_kinds = instr_kinds

        self.locked_room = None

        super().__init__(
            room_size=room_size,
            num_rows=num_rows,
            num_cols=num_cols,
            seed=seed
        )

    def gen_mission(self):
        self.place_agent()

        if self._rand_float(0, 1) < self.locked_room_prob:
            self.add_locked_room()

        self.connect_all()

        self.add_distractors(num_distractors=self.num_dists, all_unique=False)

        # If no unblocking required, make sure all objects are
        # reachable without unblocking
        if not self.unblocking:
            self.check_objs_reachable()

        # Generate random instructions
        self.instrs = self.rand_instr(
            action_kinds=self.action_kinds,
            instr_kinds=self.instr_kinds
        )

    def add_locked_room(self):
        start_room = self.room_from_pos(*self.start_pos)

        # Until we've successfully added a locked room
        while True:
            i = self._rand_int(0, self.num_cols)
            j = self._rand_int(0, self.num_rows)
            door_idx = self._rand_int(0, 4)
            self.locked_room = self.get_room(i, j)

            # Don't lock the room the agent starts in
            if self.locked_room is start_room:
                continue

            # Don't add a locked door in an external wall
            if self.locked_room.neighbors[door_idx] is None:
                continue

            door, _ = self.add_door(
                i, j,
                door_idx,
                locked=True
            )

            # Done adding locked room
            break

        # Until we find a room to put the key
        while True:
            i = self._rand_int(0, self.num_cols)
            j = self._rand_int(0, self.num_rows)
            key_room = self.get_room(i, j)

            if key_room is self.locked_room:
                continue

            self.add_object(i, j, 'key', door.color)
            break

    def rand_obj(self, types=OBJ_TYPES, colors=COLOR_NAMES, max_tries=100):
        """
        Generate a random object descriptor
        """

        num_tries = 0

        # Keep trying until we find a matching object
        while True:
            if num_tries > max_tries:
                raise RecursionError('failed to find suitable object')
            num_tries += 1

            color = self._rand_elem([None, *colors])
            type = self._rand_elem(types)

            loc = None
            if self.locations and self._rand_bool():
                loc = self._rand_elem(LOC_NAMES)

            desc = ObjDesc(type, color, loc)

            # Find all objects matching the descriptor
            objs, poss = desc.find_matching_objs(self)

            # The description must match at least one object
            if len(objs) == 0:
                continue

            # If no implicit unlocking is required
            if not self.implicit_unlock and self.locked_room:
                # Check that at least one object is not in the locked room
                pos_not_locked = list(filter(
                    lambda p: not self.locked_room.pos_inside(*p),
                    poss
                ))

                if len(pos_not_locked) == 0:
                    continue

            # Found a valid object description
            return desc

    def rand_instr(
        self,
        action_kinds,
        instr_kinds,
        depth=0
    ):
        """
        Generate random instructions
        """

        kind = self._rand_elem(instr_kinds)

        if kind is 'action':
            action = self._rand_elem(action_kinds)

            if action is 'goto':
                return GoToInstr(self.rand_obj())
            elif action is 'pickup':
                return PickupInstr(self.rand_obj(types=OBJ_TYPES_NOT_DOOR))
            elif action is 'open':
                return OpenInstr(self.rand_obj(types=['door']))
            elif action is 'putnext':
                return PutNextInstr(
                    self.rand_obj(types=OBJ_TYPES_NOT_DOOR),
                    self.rand_obj()
                )

            assert False

        elif kind is 'and':
            instr_a = self.rand_instr(
                action_kinds=action_kinds,
                instr_kinds=['action'],
                depth=depth+1
            )
            instr_b = self.rand_instr(
                action_kinds=action_kinds,
                instr_kinds=['action'],
                depth=depth+1
            )
            return AndInstr(instr_a, instr_b)

        elif kind is 'seq':
            instr_a = self.rand_instr(
                action_kinds=action_kinds,
                instr_kinds=['action', 'and'],
                depth=depth+1
            )
            instr_b = self.rand_instr(
                action_kinds=action_kinds,
                instr_kinds=['action', 'and'],
                depth=depth+1
            )

            kind = self._rand_elem(['before', 'after'])

            if kind is 'before':
                return BeforeInstr(instr_a, instr_b)
            elif kind is 'after':
                return AfterInstr(instr_a, instr_b)

            assert False

        assert False

# Dictionary of levels, indexed by name, lexically sorted
level_dict = OrderedDict()

def register_levels(module_name, globals):
    """
    Register OpenAI gym environments for all levels in a file
    """

    # Iterate through global names
    for global_name in sorted(list(globals.keys())):
        if not global_name.startswith('Level_'):
            continue

        level_name = global_name.split('Level_')[-1]
        level_class = globals[global_name]

        # Register the levels with OpenAI Gym
        gym_id = 'BabyAI-%s-v0' % (level_name)
        entry_point = '%s:%s' % (module_name, global_name)
        gym.envs.registration.register(
            id=gym_id,
            entry_point=entry_point,
        )

        # Add the level to the dictionary
        level_dict[level_name] = level_class

        # Store the name and gym id on the level class
        level_class.level_name = level_name
        level_class.gym_id = gym_id

def test():
    for idx, level_name in enumerate(level_dict.keys()):
        print('Level %s (%d/%d)' % (level_name, idx+1, len(level_dict)))

        level = level_dict[level_name]

        # Run the mission for a few episodes
        rng = random.Random(0)
        num_episodes = 0
        for i in range(0, 15):
            mission = level(seed=i)

            # Check that the surface form was generated
            assert isinstance(mission.surface, str)
            assert len(mission.surface) > 0
            obs = mission.reset()
            assert obs['mission'] == mission.surface

            # Reduce max_steps because otherwise tests take too long
            mission.max_steps = min(mission.max_steps, 200)

            # Check for some known invalid patterns in the surface form
            import re
            surface = mission.surface
            assert not re.match(r".*pick up the [^ ]*door.*", surface), surface

            while True:
                action = rng.randint(0, mission.action_space.n - 1)
                obs, reward, done, info = mission.step(action)
                if done:
                    obs = mission.reset()
                    break

            num_episodes += 1

        # The same seed should always yield the same mission
        m0 = level(seed=0)
        m1 = level(seed=0)
        grid1 = m0.unwrapped.grid
        grid2 = m1.unwrapped.grid
        assert grid1 == grid2
        assert m0.surface == m1.surface

    # Check that gym environment names were registered correctly
    gym.make('BabyAI-1RoomS8-v0')
    gym.make('BabyAI-BossLevel-v0')
<|endoftext|>


<commit_before>import math

class cached_property(object):  # noqa
    """ A property that is only computed once per instance and then replaces
        itself with an ordinary attribute. Deleting the attribute resets the
        property.
    """

    def __init__(self, func):
        self.func = func
        self.__doc__ = func.__doc__
        self.__name__ = func.__name__
        self.__module__ = func.__module__

    def __set__(self, obj, value):
        obj.__dict__[self.__name__] = value

    def __get__(self, obj, type=None):
        if obj is None:
            return self

        try:
            return obj.__dict__[self.__name__]
        except KeyError:
            pass

        value = self.func(obj)
        obj.__dict__[self.__name__] = value
        return value

class Point(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    @classmethod
    def is_collinear(cls, points, error=1E-6):
        points = list(set(points))
        if len(points) == 0:
            return False

        if len(points) <= 2:
            return True  # two points always form a line

        p1 = points.pop()
        p2 = points.pop()
        delta_a = p2 - p1

        for point in points:
            delta_b = point - p1
            determinant = (delta_a.x * delta_b.y) - (delta_a.y * delta_b.x)
            if abs(determinant) > error:
                return False

        return True

    def __neg__(self):
        return self * -1

    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

    def __sub__(self, other):
        return Point(self.x - other.x, self.y - other.y)

    def __mul__(self, other):
        return Point(other * self.x, other * self.y)

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

    def __hash__(self):
        return hash((self.x, self.y))

    def __iter__(self):
        return iter((self.x, self.y))

    def __repr__(self):
        return 'Point(%s, %s)' % (self.x, self.y)

class Line(object):
    def __init__(self, *points):
        if len(points) != 2:
            raise ValueError('a line must have two points')
        self.points = points

    @cached_property
    def length(self):
        return math.sqrt(sum([delta ** 2 for delta in self.delta]))

    @cached_property
    def midpoint(self):
        return (self.points[0] + self.points[1]) * 0.5

    @cached_property
    def delta(self):
        return self.points[0] - self.points[1]

    def perpendicular_line(self, point):
        endpoint = Point(point.x - self.delta.y, point.y + self.delta.x)
        return Line(point, endpoint)

    def perpendicular_bisector(self):
        return self.perpendicular_line(self.midpoint)

    def intersection(self, other):
        # http://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line
        x1, y1 = self.points[0]
        x2, y2 = self.points[1]
        x3, y3 = other.points[0]
        x4, y4 = other.points[1]

        det_a = (x1 * y2) - (y1 * x2)
        det_b = (x3 * y4) - (y3 * x4)

        denominator = ((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4))
        x = (det_a * (x3 - x4)) - ((x1 - x2) * det_b)
        y = (det_a * (y3 - y4)) - ((y1 - y2) * det_b)

        return Point(x / denominator, y / denominator)

    def __repr__(self):
        return 'Line(%s, %s)' % self.points

class Circle(object):
    def __init__(self, *vertices):
        if len(vertices) != 3:
            raise ValueError('a circle must have three vertices')

        if Point.is_collinear(vertices):
            raise ValueError('vertices are collinear')

        self.vertices = vertices

    @cached_property
    def center(self):
        a = Line(self.vertices[0], self.vertices[1]).perpendicular_bisector()
        b = Line(self.vertices[1], self.vertices[2]).perpendicular_bisector()
        return a.intersection(b)

    @cached_property
    def radius(self):
        return Line(self.center, self.vertices[0]).length

    def __repr__(self):
        return 'Circle(%s, %s, %s)' % self.vertices

if __name__ == '__main__':
    circle = Circle(Point(1, 0), Point(0, 1), Point(-1, 0))
    assert circle.center == Point(0, 0)
    assert circle.radius == 1

    circle = Circle(Point(1, -1), Point(0, 0), Point(-1, -1))
    assert circle.center == Point(0, -1)
    assert circle.radius == 1

    circle = Circle(Point(2.5, -2.5), Point(0, 0), Point(-2.5, -2.5))
    assert circle.center == Point(0, -2.5)
    assert circle.radius == 2.5

    # Test horizonatal line
    circle = Circle(Point(1, 0), Point(-1, 0), Point(0, 1))
    assert circle.center == Point(0, 0)
    assert circle.radius == 1

    # Test vertical line
    circle = Circle(Point(0, -1), Point(0, 1), Point(1, 0))
    assert circle.center == Point(0, 0)
    assert circle.radius == 1

    # Test collinear
    try:
        Circle(Point(0, -1), Point(0, 0), Point(0, 1))
        raise Exception('expect ValueError for collinear points')
    except ValueError:
        pass

    try:
        Circle(Point(0, -1), Point(0, 1), Point(0, 0))
        raise Exception('expect ValueError for collinear points')
    except ValueError:
        pass

    try:
        Circle(Point(0, 0), Point(0, 0), Point(0, 1))
        raise Exception('expect ValueError for collinear points')
    except ValueError:
        pass

    try:
        Circle(Point(0, 0), Point(0, 0), Point(0, 0))
        raise Exception('expect ValueError for collinear points')
    except ValueError:
        pass
<commit_msg>Add diameter property and to_polygon method.<commit_after>import math

class cached_property(object):  # noqa
    """ A property that is only computed once per instance and then replaces
        itself with an ordinary attribute. Deleting the attribute resets the
        property.
    """

    def __init__(self, func):
        self.func = func
        self.__doc__ = func.__doc__
        self.__name__ = func.__name__
        self.__module__ = func.__module__

    def __set__(self, obj, value):
        obj.__dict__[self.__name__] = value

    def __get__(self, obj, type=None):
        if obj is None:
            return self

        try:
            return obj.__dict__[self.__name__]
        except KeyError:
            pass

        value = self.func(obj)
        obj.__dict__[self.__name__] = value
        return value

class Point(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    @classmethod
    def is_collinear(cls, points, error=1E-6):
        points = list(set(points))
        if len(points) == 0:
            return False

        if len(points) <= 2:
            return True  # two points always form a line

        p1 = points.pop()
        p2 = points.pop()
        delta_a = p2 - p1

        for point in points:
            delta_b = point - p1
            determinant = (delta_a.x * delta_b.y) - (delta_a.y * delta_b.x)
            if abs(determinant) > error:
                return False

        return True

    def __neg__(self):
        return self * -1

    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

    def __sub__(self, other):
        return Point(self.x - other.x, self.y - other.y)

    def __mul__(self, other):
        return Point(other * self.x, other * self.y)

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

    def __hash__(self):
        return hash((self.x, self.y))

    def __iter__(self):
        return iter((self.x, self.y))

    def __repr__(self):
        return 'Point(%s, %s)' % (self.x, self.y)

class Line(object):
    def __init__(self, *points):
        if len(points) != 2:
            raise ValueError('a line must have two points')
        self.points = points

    @cached_property
    def length(self):
        return math.sqrt(sum([delta ** 2 for delta in self.delta]))

    @cached_property
    def midpoint(self):
        return (self.points[0] + self.points[1]) * 0.5

    @cached_property
    def delta(self):
        return self.points[0] - self.points[1]

    def perpendicular_line(self, point):
        endpoint = Point(point.x - self.delta.y, point.y + self.delta.x)
        return Line(point, endpoint)

    def perpendicular_bisector(self):
        return self.perpendicular_line(self.midpoint)

    def intersection(self, other):
        # http://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line
        x1, y1 = self.points[0]
        x2, y2 = self.points[1]
        x3, y3 = other.points[0]
        x4, y4 = other.points[1]

        det_a = (x1 * y2) - (y1 * x2)
        det_b = (x3 * y4) - (y3 * x4)

        denominator = ((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4))
        x = (det_a * (x3 - x4)) - ((x1 - x2) * det_b)
        y = (det_a * (y3 - y4)) - ((y1 - y2) * det_b)

        return Point(x / denominator, y / denominator)

    def __repr__(self):
        return 'Line(%s, %s)' % self.points

class Circle(object):
    def __init__(self, *vertices):
        if len(vertices) != 3:
            raise ValueError('a circle must have three vertices')

        if Point.is_collinear(vertices):
            raise ValueError('vertices are collinear')

        self.vertices = vertices

    @cached_property
    def center(self):
        a = Line(self.vertices[0], self.vertices[1]).perpendicular_bisector()
        b = Line(self.vertices[1], self.vertices[2]).perpendicular_bisector()
        return a.intersection(b)

    @cached_property
    def radius(self):
        return Line(self.center, self.vertices[0]).length

    @cached_property
    def diameter(self):
        return 2 * self.radius

    def point_at(self, theta):
        return Point(
            self.radius * math.cos(theta) + self.center.x,
            self.radius * math.sin(theta) + self.center.y
        )

    def to_polygon(self, segments=64):
        thetas = [(2 * math.pi) / segments * i for i in xrange(segments)]
        return [self.point_at(theta) for theta in thetas]

    def __repr__(self):
        return 'Circle(%s, %s, %s)' % self.vertices

if __name__ == '__main__':
    circle = Circle(Point(1, 0), Point(0, 1), Point(-1, 0))
    assert circle.center == Point(0, 0)
    assert circle.radius == 1

    circle = Circle(Point(1, -1), Point(0, 0), Point(-1, -1))
    assert circle.center == Point(0, -1)
    assert circle.radius == 1

    circle = Circle(Point(2.5, -2.5), Point(0, 0), Point(-2.5, -2.5))
    assert circle.center == Point(0, -2.5)
    assert circle.radius == 2.5

    # Test horizonatal line
    circle = Circle(Point(1, 0), Point(-1, 0), Point(0, 1))
    assert circle.center == Point(0, 0)
    assert circle.radius == 1

    # Test vertical line
    circle = Circle(Point(0, -1), Point(0, 1), Point(1, 0))
    assert circle.center == Point(0, 0)
    assert circle.radius == 1

    # Test collinear
    try:
        Circle(Point(0, -1), Point(0, 0), Point(0, 1))
        raise Exception('expect ValueError for collinear points')
    except ValueError:
        pass

    try:
        Circle(Point(0, -1), Point(0, 1), Point(0, 0))
        raise Exception('expect ValueError for collinear points')
    except ValueError:
        pass

    try:
        Circle(Point(0, 0), Point(0, 0), Point(0, 1))
        raise Exception('expect ValueError for collinear points')
    except ValueError:
        pass

    try:
        Circle(Point(0, 0), Point(0, 0), Point(0, 0))
        raise Exception('expect ValueError for collinear points')
    except ValueError:
        pass
<|endoftext|>


<commit_before>"""Collection of tools for using PBS, a job scheduler for high-performance
computing environments. The command is usually `qsub <options>` on most
systems.
"""
import random
import string
from string import Template
from subprocess import run, CalledProcessError, PIPE
from datetime import datetime as d
import platform
import getpass
import os
import contextlib

class Qsubutils:
    """Create a pbs job and submit it using qsub.

    This class also provides functionality for creating multiple pbs jobs that
    by creating chunks of lists for each python script and job.
    """
    def __init__(self, default=True):
        """UNLESS A WINDOWS MACHINE HAS PBS. IT LIKELY WONT"""
        if "windows" in platform.system().lower():
            raise ImportError("QsubUtils is only supported on linux/osx.")

        self.default = default

    def basejobids(self):
        """"Create base job attributes."""
        base_id = self.randomid()
        self.base_id = base_id
        base = "submit_{0}".format(self.base_id)

        return base_id, base

    @classmethod
    def import_temp(cls, filepath):
        """Import the script or file that you need a template of and that has
        temp strings.
        """
        file_temp = open(filepath, 'r')
        file_str = file_temp.read()
        file_temp.close()

        file_temp = Template(file_str)
        return file_temp

    @classmethod
    def file2str(cls, filename):
        """Turn the contents of a file (python file) into a string."""
        file_temp = open(filename, 'r')
        file_str = file_temp.read()
        return file_str

    @staticmethod
    def randomid(length=5):
        """Generate a random ID of 5 characters to append to qsub job name."""
        return ''.join(random.sample(
            string.ascii_letters + string.digits, length))

    @staticmethod
    def writecodefile(filename, code, language):
        """Create a python file and write the code to it."""
        if language == 'python':
            with open(filename + '.py', 'w') as pyfile:
                pyfile.write(code)
                pyfile.close()

        elif language == 'bash':
            with open(filename + '.sh', 'w') as bashfile:
                bashfile.write(code)
                bashfile.close()

        elif language == 'R' or 'r':
            with open(filename + '.R', 'w') as rfile:
                rfile.write(code)
                rfile.close()
        else:
            raise NotImplementedError('%s is unsupported.' % language)

    def _checkjobstatus(self):
        raise NotImplementedError
#        with contextlib.suppress(OSError):
#            cmd = 'qstat'  # this is the command
#            cmd_status = run([cmd], shell=True)  # must = TRUE
#            if cmd_status == 0:  # Command was successful.
#                print('Job submitted.')
#            else:  # Unsuccessful. Stdout will be '1'.
#                print("PBS job not submitted.")

    @classmethod
    def _cleanup(cls, base):
        os.remove(base + '.pbs')
        os.remove(base + '.py')

    def pbs_dict(self, default=True, author='', email='', description='', project='', select='1',
                 jobname='', script_name='', logname='', outfile='', errfile='', python='python3',
                 gigabytes='6gb', cput='75:00:00', walltime='75:00:00'):
        """Add PBS script attributes."""

        # TODO simplify this function. Add configuration script.

        # Date format. Used to add as a date
        format1 = '%a %b %d %I:%M:%S %p %Y'

        if self.default == default:
            _, baseid = self.basejobids()
            author = getpass.getuser().upper()
            email = 'n/a'
            description = 'This is a default pbs job.'
            project = 'Datasnakes-Orthologs'
            select = '3'
            jobname = 'orthoevol'
            script_name = script_name
            outfile = outfile
            errfile = errfile
            logname = 'ortho-evol.{}'.format(self.randomid(length=3))

        # Fill in the pbs script attributes
        job_attributes = {
            'author': author,
            'description': description,
            'date': d.now().strftime(format1),
            'PBS_JOBID': '${PBS_JOBID}',
            'PBS_O_WORKDIR': '${PBS_O_WORKDIR}',
            'proj_name': project,
            'select': int(select),
            'memgb': gigabytes,
            'cput': cput,
            'wt': walltime,
            'job_name': jobname,
            'outfile': outfile,
            'errfile': errfile,
            'script': script_name,
            'log_name': logname.format(self.randomid()),
            'cmd': python + " " + script_name + ".py",
            'email': email
            }

        return job_attributes

    def submitjob(self, code, language='python', default=True, prefix=None):
        """Creates and submit a qsub job. Also uses python code."""
        # TIP If python is in your environment as only 'python' update that.
        # TODO-SDH add a default parameter or custom parameter
        # If default, a python file will be created from code that is used.
        if self.default == default and language == 'python':
            baseid, base = self.basejobids()
            if prefix is not None:
                base = prefix + '_' + base
            self.writecodefile(filename=base, code=code, language=language)
            outfile = 'orthoevol_{}.out'.format(baseid)
            errfile = 'orthoevol_{}.err'.format(baseid)
            # Create the pbs script from the template or dict
            pbstemp = self.import_temp('temp.pbs')

            script_name = base.format(baseid)

            attributes = self.pbs_dict(outfile=outfile,
                                       errfile=errfile,
                                       script_name=script_name)

            with open(base + '.pbs', 'w') as pbsfile:
                pbsfile.write(pbstemp.substitute(attributes))
                pbsfile.close()
        else:
            raise NotImplementedError('Custom qsub jobs are forbidden.')
            # TODO Improve custom job creation
#            pbstemp = self.import_temp('temp.pbs')
#            with open(base + '.pbs', 'w') as pbsfile:
#                pbsfile.write(pbstemp.substitute(self.pbs_dict))
#                pbsfile.close()

        with contextlib.suppress(CalledProcessError):
            cmd = ['qsub ' + base + '.pbs']  # this is the command
            # Shell MUST be True
            cmd_status = run(cmd, stdout=PIPE, stderr=PIPE, shell=True)

            if cmd_status.returncode == 0:  # Command was successful.
                print('Job submitted.\n')
                # TODO add a check to for job errors or check for error file.

            else:  # Unsuccessful. Stdout will be '1'
                print("PBS job not submitted.")
                self._cleanup(base=base)
<commit_msg>Removed basejobids() from pbs_dict function<commit_after>"""Collection of tools for using PBS, a job scheduler for high-performance
computing environments. The command is usually `qsub <options>` on most
systems.
"""
import random
import string
from string import Template
from subprocess import run, CalledProcessError, PIPE
from datetime import datetime as d
import platform
import getpass
import os
import contextlib

class Qsubutils:
    """Create a pbs job and submit it using qsub.

    This class also provides functionality for creating multiple pbs jobs that
    by creating chunks of lists for each python script and job.
    """
    def __init__(self, default=True):
        """UNLESS A WINDOWS MACHINE HAS PBS. IT LIKELY WONT"""
        if "windows" in platform.system().lower():
            raise ImportError("QsubUtils is only supported on linux/osx.")

        self.default = default

    def basejobids(self):
        """"Create base job attributes."""
        base_id = self.randomid()
        self.base_id = base_id
        base = "submit_{0}".format(self.base_id)

        return base_id, base

    @classmethod
    def import_temp(cls, filepath):
        """Import the script or file that you need a template of and that has
        temp strings.
        """
        file_temp = open(filepath, 'r')
        file_str = file_temp.read()
        file_temp.close()

        file_temp = Template(file_str)
        return file_temp

    @classmethod
    def file2str(cls, filename):
        """Turn the contents of a file (python file) into a string."""
        file_temp = open(filename, 'r')
        file_str = file_temp.read()
        return file_str

    @staticmethod
    def randomid(length=5):
        """Generate a random ID of 5 characters to append to qsub job name."""
        return ''.join(random.sample(
            string.ascii_letters + string.digits, length))

    @staticmethod
    def writecodefile(filename, code, language):
        """Create a python file and write the code to it."""
        if language == 'python':
            with open(filename + '.py', 'w') as pyfile:
                pyfile.write(code)
                pyfile.close()

        elif language == 'bash':
            with open(filename + '.sh', 'w') as bashfile:
                bashfile.write(code)
                bashfile.close()

        elif language == 'R' or 'r':
            with open(filename + '.R', 'w') as rfile:
                rfile.write(code)
                rfile.close()
        else:
            raise NotImplementedError('%s is unsupported.' % language)

    def _checkjobstatus(self):
        raise NotImplementedError
#        with contextlib.suppress(OSError):
#            cmd = 'qstat'  # this is the command
#            cmd_status = run([cmd], shell=True)  # must = TRUE
#            if cmd_status == 0:  # Command was successful.
#                print('Job submitted.')
#            else:  # Unsuccessful. Stdout will be '1'.
#                print("PBS job not submitted.")

    @classmethod
    def _cleanup(cls, base):
        os.remove(base + '.pbs')
        os.remove(base + '.py')

    def pbs_dict(self, default=True, author='', email='', description='', project='', select='1',
                 jobname='', script_name='', logname='', outfile='', errfile='', python='python3',
                 gigabytes='6gb', cput='75:00:00', walltime='75:00:00'):
        """Add PBS script attributes."""

        # TODO simplify this function. Add configuration script.

        # Date format. Used to add as a date
        format1 = '%a %b %d %I:%M:%S %p %Y'

        if self.default == default:
            author = getpass.getuser().upper()
            email = 'n/a'
            description = 'This is a default pbs job.'
            project = 'Datasnakes-Orthologs'
            select = '3'
            jobname = 'orthoevol'
            script_name = script_name
            outfile = outfile
            errfile = errfile
            logname = 'ortho-evol.{}'.format(self.randomid(length=3))

        # Fill in the pbs script attributes
        job_attributes = {
            'author': author,
            'description': description,
            'date': d.now().strftime(format1),
            'PBS_JOBID': '${PBS_JOBID}',
            'PBS_O_WORKDIR': '${PBS_O_WORKDIR}',
            'proj_name': project,
            'select': int(select),
            'memgb': gigabytes,
            'cput': cput,
            'wt': walltime,
            'job_name': jobname,
            'outfile': outfile,
            'errfile': errfile,
            'script': script_name,
            'log_name': logname.format(self.randomid()),
            'cmd': python + " " + script_name + ".py",
            'email': email
            }

        return job_attributes

    def submitjob(self, code, language='python', default=True, prefix=None):
        """Creates and submit a qsub job. Also uses python code."""
        # TIP If python is in your environment as only 'python' update that.
        # TODO-SDH add a default parameter or custom parameter
        # If default, a python file will be created from code that is used.
        if self.default == default and language == 'python':
            baseid, base = self.basejobids()
            if prefix is not None:
                base = prefix + '_' + base
            self.writecodefile(filename=base, code=code, language=language)
            outfile = 'orthoevol_{}.out'.format(baseid)
            errfile = 'orthoevol_{}.err'.format(baseid)
            # Create the pbs script from the template or dict
            pbstemp = self.import_temp('temp.pbs')

            script_name = base.format(baseid)

            attributes = self.pbs_dict(outfile=outfile,
                                       errfile=errfile,
                                       script_name=script_name)

            with open(base + '.pbs', 'w') as pbsfile:
                pbsfile.write(pbstemp.substitute(attributes))
                pbsfile.close()
        else:
            raise NotImplementedError('Custom qsub jobs are forbidden.')
            # TODO Improve custom job creation
#            pbstemp = self.import_temp('temp.pbs')
#            with open(base + '.pbs', 'w') as pbsfile:
#                pbsfile.write(pbstemp.substitute(self.pbs_dict))
#                pbsfile.close()

        with contextlib.suppress(CalledProcessError):
            cmd = ['qsub ' + base + '.pbs']  # this is the command
            # Shell MUST be True
            cmd_status = run(cmd, stdout=PIPE, stderr=PIPE, shell=True)

            if cmd_status.returncode == 0:  # Command was successful.
                print('Job submitted.\n')
                # TODO add a check to for job errors or check for error file.

            else:  # Unsuccessful. Stdout will be '1'
                print("PBS job not submitted.")
                self._cleanup(base=base)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from .core import *

__version__ = '0.0.7'
<commit_msg>Bump version to 0.0.8<commit_after># -*- coding: utf-8 -*-
from .core import *

__version__ = '0.0.8'
<|endoftext|>


<commit_before>from django.conf import settings
from django.urls import include, re_path
from django.contrib import admin
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.urls import path
from django.views.generic import TemplateView
from django.views.static import serve as static_serve
from website.views import IndexView, AcceptTosRedirectView, AboutView, AdminView, AcceptTosView, RulesView, \
    RulesDetailView, IntranetView
from userprofile.views import TermsOfServiceCreateView, TermsOfServiceView, MostRecentTermsOfServiceView
from userprofile.views import ProfileListView
from django.contrib.auth.decorators import permission_required
from ckeditor_uploader import views as ck_upload_views
from rest_framework import routers
from reservations import views as reservation_views
from inventory import views as inventory_views

handler404 = 'website.views.handler404'
handler500 = 'website.views.handler500'

# Add rest framework urls
router = routers.DefaultRouter()
router.register(r'reservations', reservation_views.ReservationsViewSet)

urlpatterns = [
    path('', IndexView.as_view(), name='index'),
    path('admin/', admin.site.urls),
    path('robots.txt', TemplateView.as_view(template_name='website/robots.txt', content_type='text/plain')),
    path('tos/', MostRecentTermsOfServiceView.as_view(), name='tos'),
    path('tos/returning-user/', AcceptTosView.as_view(), name='tos-returningls'),
    path('tos/accept/', AcceptTosRedirectView.as_view(), name='tos-accept'),
    path('tos/create/', TermsOfServiceCreateView.as_view(), name='tos-create'),
    path('tos/create/<int:pk>/', TermsOfServiceCreateView.as_view(), name='tos-create-id'),
    path('tos/<int:pk>/', TermsOfServiceView.as_view(), name='tos-details'),
    path('news/', include('news.urls')),
    path('events/', include('news.event_urls')),
    path('ckeditor/', include('ckeditor_uploader.urls')),
    path('ckeditor/upload', permission_required('news.add_article')(ck_upload_views.upload), name='ckeditor_upload'),
    path('ckeditor/browse', permission_required('news.add_article')(ck_upload_views.browse), name='ckeditor_browse'),
    path('authentication/', include('authentication.urls', namespace='auth')),
    path('door/', include('door.urls')),
    path('opptak/', include('applications.urls'), name='opptak'),
    path('files/', include('files.urls')),
    path('about/', AboutView.as_view(), name='about'),
    path('rules/', RulesView.as_view(), name='rules'),
    path('rules/<int:pk>/', RuleDetailsView.as_view(), name='rule_details'),
    path('s/', include('django.contrib.flatpages.urls')),
    path('profile/', include('userprofile.urls')),
    path('reservations/', include('reservations.urls')),
    path('members/', ProfileListView.as_view(), name='member-list'),
    path('admin-panel/', AdminView.as_view(), name='admin'),
    path('feide/', include('social_django.urls', namespace='social')),
    path('api/', include(router.urls)),
    path('api/inventory/', inventory_views.InventoryListAPIView.as_view(), name='inventory-api'),
    path('inventory/', include('inventory.urls')),
    path('vaktliste/', include('watchlist.urls')),
    path('intranet/', IntranetView.as_view(), name='intranet'),
]

admin.site.site_header = "Adminpanel for Viktige Folk"
admin.site.site_title = "Admin hackerspace-ntnu.no"
admin.site.index_title = "Vennligst ikke ødelegg noe"
if settings.DEBUG:
    urlpatterns += staticfiles_urlpatterns()
    urlpatterns += [
        re_path(r'^media/(?P<path>.*)$', static_serve,
                {'document_root': settings.MEDIA_ROOT}),
    ]
    admin.site.index_title = "Velkommen tilbake, Mester"
<commit_msg>fix botched rebase<commit_after>from django.conf import settings
from django.urls import include, re_path
from django.contrib import admin
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.urls import path
from django.views.generic import TemplateView
from django.views.static import serve as static_serve
from website.views import IndexView, AcceptTosRedirectView, AboutView, AdminView, AcceptTosView, RulesView, \
    RuleDetailsView, IntranetView
from userprofile.views import TermsOfServiceCreateView, TermsOfServiceView, MostRecentTermsOfServiceView
from userprofile.views import ProfileListView
from django.contrib.auth.decorators import permission_required
from ckeditor_uploader import views as ck_upload_views
from rest_framework import routers
from reservations import views as reservation_views
from inventory import views as inventory_views

handler404 = 'website.views.handler404'
handler500 = 'website.views.handler500'

# Add rest framework urls
router = routers.DefaultRouter()
router.register(r'reservations', reservation_views.ReservationsViewSet)

urlpatterns = [
    path('', IndexView.as_view(), name='index'),
    path('admin/', admin.site.urls),
    path('robots.txt', TemplateView.as_view(template_name='website/robots.txt', content_type='text/plain')),
    path('tos/', MostRecentTermsOfServiceView.as_view(), name='tos'),
    path('tos/returning-user/', AcceptTosView.as_view(), name='tos-returningls'),
    path('tos/accept/', AcceptTosRedirectView.as_view(), name='tos-accept'),
    path('tos/create/', TermsOfServiceCreateView.as_view(), name='tos-create'),
    path('tos/create/<int:pk>/', TermsOfServiceCreateView.as_view(), name='tos-create-id'),
    path('tos/<int:pk>/', TermsOfServiceView.as_view(), name='tos-details'),
    path('news/', include('news.urls')),
    path('events/', include('news.event_urls')),
    path('ckeditor/', include('ckeditor_uploader.urls')),
    path('ckeditor/upload', permission_required('news.add_article')(ck_upload_views.upload), name='ckeditor_upload'),
    path('ckeditor/browse', permission_required('news.add_article')(ck_upload_views.browse), name='ckeditor_browse'),
    path('authentication/', include('authentication.urls', namespace='auth')),
    path('door/', include('door.urls')),
    path('opptak/', include('applications.urls'), name='opptak'),
    path('files/', include('files.urls')),
    path('about/', AboutView.as_view(), name='about'),
    path('rules/', RulesView.as_view(), name='rules'),
    path('rules/<int:pk>/', RuleDetailsView.as_view(), name='rule_details'),
    path('s/', include('django.contrib.flatpages.urls')),
    path('profile/', include('userprofile.urls')),
    path('reservations/', include('reservations.urls')),
    path('members/', ProfileListView.as_view(), name='member-list'),
    path('admin-panel/', AdminView.as_view(), name='admin'),
    path('feide/', include('social_django.urls', namespace='social')),
    path('api/', include(router.urls)),
    path('api/inventory/', inventory_views.InventoryListAPIView.as_view(), name='inventory-api'),
    path('inventory/', include('inventory.urls')),
    path('vaktliste/', include('watchlist.urls')),
    path('intranet/', IntranetView.as_view(), name='intranet'),
]

admin.site.site_header = "Adminpanel for Viktige Folk"
admin.site.site_title = "Admin hackerspace-ntnu.no"
admin.site.index_title = "Vennligst ikke ødelegg noe"
if settings.DEBUG:
    urlpatterns += staticfiles_urlpatterns()
    urlpatterns += [
        re_path(r'^media/(?P<path>.*)$', static_serve,
                {'document_root': settings.MEDIA_ROOT}),
    ]
    admin.site.index_title = "Velkommen tilbake, Mester"
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (C) 2017-2020 GEM Foundation
#
# OpenQuake is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OpenQuake 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with OpenQuake. If not, see <http://www.gnu.org/licenses/>.
from openquake.baselib import performance, sap
from openquake.calculators.extract import Extractor, WebExtractor

# `oq extract` is tested in the demos
@sap.script
def extract(what, calc_id=-1, webapi=True, local=False):
    """
    Extract an output from the datastore and save it into an .hdf5 file.
    By default uses the WebAPI, otherwise the extraction is done locally.
    """
    with performance.Monitor('extract', measuremem=True) as mon:
        if local:
            obj = WebExtractor(calc_id, 'http://localhost:8800', '').get(what)
        elif webapi:
            obj = WebExtractor(calc_id).get(what)
        else:
            obj = Extractor(calc_id).get(what)
        w = what.replace('/', '-').replace('?', '-')
        if not obj.shape:  # is a dictionary of arrays
            fname = '%s_%d.txt' % (w, calc_id)
            open(fname, 'w').write(obj.toml())
        else:  # a regular ArrayWrapper
            fname = '%s_%d.hdf5' % (w, calc_id)
            obj.save(fname)
        print('Saved', fname)
    if mon.duration > 1:
        print(mon)

extract.arg('what', 'string specifying what to export')
extract.arg('calc_id', 'number of the calculation', type=int)
extract.flg('webapi', 'if passed, use the (possibly remote) WebAPI')
extract.flg('local', 'if passed, use the local WebAPI')
<commit_msg>Revert "Let the oq extract command use the latest calc_id by default"<commit_after># -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (C) 2017-2020 GEM Foundation
#
# OpenQuake is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OpenQuake 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with OpenQuake. If not, see <http://www.gnu.org/licenses/>.
from openquake.baselib import performance, sap
from openquake.calculators.extract import Extractor, WebExtractor

# `oq extract` is tested in the demos
@sap.script
def extract(what, calc_id, webapi=True, local=False):
    """
    Extract an output from the datastore and save it into an .hdf5 file.
    By default uses the WebAPI, otherwise the extraction is done locally.
    """
    with performance.Monitor('extract', measuremem=True) as mon:
        if local:
            obj = WebExtractor(calc_id, 'http://localhost:8800', '').get(what)
        elif webapi:
            obj = WebExtractor(calc_id).get(what)
        else:
            obj = Extractor(calc_id).get(what)
        w = what.replace('/', '-').replace('?', '-')
        if not obj.shape:  # is a dictionary of arrays
            fname = '%s_%d.txt' % (w, calc_id)
            open(fname, 'w').write(obj.toml())
        else:  # a regular ArrayWrapper
            fname = '%s_%d.hdf5' % (w, calc_id)
            obj.save(fname)
        print('Saved', fname)
    if mon.duration > 1:
        print(mon)

extract.arg('what', 'string specifying what to export')
extract.arg('calc_id', 'number of the calculation', type=int)
extract.flg('webapi', 'if passed, use the (possibly remote) WebAPI')
extract.flg('local', 'if passed, use the local WebAPI')
<|endoftext|>


<commit_before>"""
This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test".

Replace this with more appropriate tests for your application.
"""

from django.test import TestCase

class SimpleTest(TestCase):
    def test_basic_addition(self):
        """
        Tests that 1 + 1 always equals 2.
        """
        self.assertEqual(1 + 1, 2)
<commit_msg>add tests.py<commit_after># -*- coding:utf-8 -*-
"""
# Author: Pegasus Wang (pegasuswang@qq.com, http://ningning.today)
# Created Time : Tue Mar  3 19:44:02 2015

# File Name: tests.py
# Description:

"""
import requests
import codecs

f = codecs.open(u'post.xml', u'r', u'utf-8')
content = u''.join(f.readlines())
f.close()

res = requests.post(u'http://2.pegasuswang.sinaapp.com/wechat/', data=content.encode(u'utf-8'))
print res.text
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (C) 2017-2020 GEM Foundation
#
# OpenQuake is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OpenQuake 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with OpenQuake. If not, see <http://www.gnu.org/licenses/>.
from openquake.baselib import performance, sap
from openquake.calculators.extract import Extractor, WebExtractor

# `oq extract` is tested in the demos
@sap.script
def extract(what, calc_id, webapi=True, local=False):
    """
    Extract an output from the datastore and save it into an .hdf5 file.
    By default uses the WebAPI, otherwise the extraction is done locally.
    """
    with performance.Monitor('extract', measuremem=True) as mon:
        if local:
            obj = WebExtractor(calc_id, 'http://localhost:8800', '').get(what)
        elif webapi:
            obj = WebExtractor(calc_id).get(what)
        else:
            obj = Extractor(calc_id).get(what)
        w = what.replace('/', '-').replace('?', '-')
        if not obj.shape:  # is a dictionary of arrays
            fname = '%s_%d.txt' % (w, calc_id)
            open(fname, 'w').write(obj.toml())
        else:  # a regular ArrayWrapper
            fname = '%s_%d.hdf5' % (w, calc_id)
            obj.save(fname)
        print('Saved', fname)
    if mon.duration > 1:
        print(mon)

extract.arg('what', 'string specifying what to export')
extract.arg('calc_id', 'number of the calculation', type=int)
extract.flg('webapi', 'if passed, use the (possibly remote) WebAPI')
extract.flg('local', 'if passed, use the local WebAPI')
<commit_msg>Revert "Revert "Let the oq extract command use the latest calc_id by default""<commit_after># -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (C) 2017-2020 GEM Foundation
#
# OpenQuake is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OpenQuake 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with OpenQuake. If not, see <http://www.gnu.org/licenses/>.
from openquake.baselib import performance, sap
from openquake.calculators.extract import Extractor, WebExtractor

# `oq extract` is tested in the demos
@sap.script
def extract(what, calc_id=-1, webapi=True, local=False):
    """
    Extract an output from the datastore and save it into an .hdf5 file.
    By default uses the WebAPI, otherwise the extraction is done locally.
    """
    with performance.Monitor('extract', measuremem=True) as mon:
        if local:
            obj = WebExtractor(calc_id, 'http://localhost:8800', '').get(what)
        elif webapi:
            obj = WebExtractor(calc_id).get(what)
        else:
            obj = Extractor(calc_id).get(what)
        w = what.replace('/', '-').replace('?', '-')
        if not obj.shape:  # is a dictionary of arrays
            fname = '%s_%d.txt' % (w, calc_id)
            open(fname, 'w').write(obj.toml())
        else:  # a regular ArrayWrapper
            fname = '%s_%d.hdf5' % (w, calc_id)
            obj.save(fname)
        print('Saved', fname)
    if mon.duration > 1:
        print(mon)

extract.arg('what', 'string specifying what to export')
extract.arg('calc_id', 'number of the calculation', type=int)
extract.flg('webapi', 'if passed, use the (possibly remote) WebAPI')
extract.flg('local', 'if passed, use the local WebAPI')
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program 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 Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import pooler
import wizard
from osv import osv, fields

class base_module_upgrade(osv.osv_memory):
    """ Module Upgrade """

    _name = "base.module.upgrade"
    _description = "Module Upgrade"

    _columns = {
        'module_info': fields.text('Modules to update',readonly=True),
    }

    def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
        """ Changes the view dynamically
         @param self: The object pointer.
         @param cr: A database cursor
         @param uid: ID of the user currently logged in
         @param context: A standard dictionary
         @return: New arch of view.
        """
        res = super(base_module_upgrade, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar,submenu=False)
        record_id = context and context.get('active_id', False) or False
        active_model = context.get('active_model')
        if (not record_id) or (not active_model):
            return res

        ids = self.get_module_list(cr, uid, context=context)
        if not ids:
            res['arch'] = '''<form string="Apply Scheduled Upgrades">
                                <separator string="System update completed" colspan="4"/>
                                <label align="0.0" string="The selected modules have been updated / installed !" colspan="4"/>
                                <label align="0.0" string="We suggest to reload the menu tab to see the new menus (Ctrl+T then Ctrl+R)." colspan="4"/>
                                 <separator string="" colspan="4"/>
                                <newline/>
                                <button special="cancel" string="Close" icon="gtk-cancel"/>
                                <button name="config" string="Start configuration" type="object" icon="gtk-ok"/>
                             </form>'''

        return res

    def get_module_list(self, cr, uid, context=None):
        mod_obj = self.pool.get('ir.module.module')
        ids = mod_obj.search(cr, uid, [
            ('state', 'in', ['to upgrade', 'to remove', 'to install'])])
        return ids

    def default_get(self, cr, uid, fields, context=None):
        """
        This function checks for precondition before wizard executes
        @param self: The object pointer
        @param cr: the current row, from the database cursor,
        @param uid: the current user’s ID for security checks,
        @param fields: List of fields for default value
        @param context: A standard dictionary for contextual values
        """
        mod_obj = self.pool.get('ir.module.module')
        ids = self.get_module_list(cr, uid, context=context)
        res = mod_obj.read(cr, uid, ids, ['name','state'], context)
        return {'module_info': '\n'.join(map(lambda x: x['name']+' : '+x['state'], res))}

    def upgrade_module(self, cr, uid, ids, context=None):
        pool = pooler.get_pool(cr.dbname)
        mod_obj = self.pool.get('ir.module.module')
        data_obj = self.pool.get('ir.model.data')
        ids = mod_obj.search(cr, uid, [('state', 'in', ['to upgrade', 'to remove', 'to install'])])
        unmet_packages = []
        mod_dep_obj = pool.get('ir.module.module.dependency')
        for mod in mod_obj.browse(cr, uid, ids):
            depends_mod_ids = mod_dep_obj.search(cr, uid, [('module_id', '=', mod.id)])
            for dep_mod in mod_dep_obj.browse(cr, uid, depends_mod_ids):
                if dep_mod.state in ('unknown','uninstalled'):
                    unmet_packages.append(dep_mod.name)
        if len(unmet_packages):
            raise osv.except_osv(_('Unmet dependency !'), _('Following modules are not installed or unknown: %s') % ('\n\n' + '\n'.join(unmet_packages)))
        mod_obj.download(cr, uid, ids, context=context)
        cr.commit()
        _, pool = pooler.restart_pool(cr.dbname, update_module=True)

        id2 = data_obj._get_id(cr, uid, 'base', 'view_base_module_upgrade_install')
        if id2:
            id2 = data_obj.browse(cr, uid, id2, context=context).res_id

        return {
                'view_type': 'form',
                'view_mode': 'form',
                'res_model': 'base.module.upgrade',
                'views': [(id2, 'form')],
                'view_id': False,
                'type': 'ir.actions.act_window',
                'target': 'new',
            }

    def config(self, cr, uid, ids, context=None):
        return self.pool.get('res.config').next(cr, uid, [], context=context)

base_module_upgrade()
<commit_msg>[FIX] base: missing import _() in base_module_upgrade<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program 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 Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import pooler
from osv import osv, fields
from tools.translate import _

class base_module_upgrade(osv.osv_memory):
    """ Module Upgrade """

    _name = "base.module.upgrade"
    _description = "Module Upgrade"

    _columns = {
        'module_info': fields.text('Modules to update',readonly=True),
    }

    def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
        """ Changes the view dynamically
         @param self: The object pointer.
         @param cr: A database cursor
         @param uid: ID of the user currently logged in
         @param context: A standard dictionary
         @return: New arch of view.
        """
        res = super(base_module_upgrade, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar,submenu=False)
        record_id = context and context.get('active_id', False) or False
        active_model = context.get('active_model')
        if (not record_id) or (not active_model):
            return res

        ids = self.get_module_list(cr, uid, context=context)
        if not ids:
            res['arch'] = '''<form string="Apply Scheduled Upgrades">
                                <separator string="System update completed" colspan="4"/>
                                <label align="0.0" string="The selected modules have been updated / installed !" colspan="4"/>
                                <label align="0.0" string="We suggest to reload the menu tab to see the new menus (Ctrl+T then Ctrl+R)." colspan="4"/>
                                 <separator string="" colspan="4"/>
                                <newline/>
                                <button special="cancel" string="Close" icon="gtk-cancel"/>
                                <button name="config" string="Start configuration" type="object" icon="gtk-ok"/>
                             </form>'''

        return res

    def get_module_list(self, cr, uid, context=None):
        mod_obj = self.pool.get('ir.module.module')
        ids = mod_obj.search(cr, uid, [
            ('state', 'in', ['to upgrade', 'to remove', 'to install'])])
        return ids

    def default_get(self, cr, uid, fields, context=None):
        """
        This function checks for precondition before wizard executes
        @param self: The object pointer
        @param cr: the current row, from the database cursor,
        @param uid: the current user’s ID for security checks,
        @param fields: List of fields for default value
        @param context: A standard dictionary for contextual values
        """
        mod_obj = self.pool.get('ir.module.module')
        ids = self.get_module_list(cr, uid, context=context)
        res = mod_obj.read(cr, uid, ids, ['name','state'], context)
        return {'module_info': '\n'.join(map(lambda x: x['name']+' : '+x['state'], res))}

    def upgrade_module(self, cr, uid, ids, context=None):
        pool = pooler.get_pool(cr.dbname)
        mod_obj = self.pool.get('ir.module.module')
        data_obj = self.pool.get('ir.model.data')
        ids = mod_obj.search(cr, uid, [('state', 'in', ['to upgrade', 'to remove', 'to install'])])
        unmet_packages = []
        mod_dep_obj = pool.get('ir.module.module.dependency')
        for mod in mod_obj.browse(cr, uid, ids):
            depends_mod_ids = mod_dep_obj.search(cr, uid, [('module_id', '=', mod.id)])
            for dep_mod in mod_dep_obj.browse(cr, uid, depends_mod_ids):
                if dep_mod.state in ('unknown','uninstalled'):
                    unmet_packages.append(dep_mod.name)
        if len(unmet_packages):
            raise osv.except_osv(_('Unmet dependency !'), _('Following modules are not installed or unknown: %s') % ('\n\n' + '\n'.join(unmet_packages)))
        mod_obj.download(cr, uid, ids, context=context)
        cr.commit()
        _, pool = pooler.restart_pool(cr.dbname, update_module=True)

        id2 = data_obj._get_id(cr, uid, 'base', 'view_base_module_upgrade_install')
        if id2:
            id2 = data_obj.browse(cr, uid, id2, context=context).res_id

        return {
                'view_type': 'form',
                'view_mode': 'form',
                'res_model': 'base.module.upgrade',
                'views': [(id2, 'form')],
                'view_id': False,
                'type': 'ir.actions.act_window',
                'target': 'new',
            }

    def config(self, cr, uid, ids, context=None):
        return self.pool.get('res.config').next(cr, uid, [], context=context)

base_module_upgrade()
<|endoftext|>


<commit_before>import os
import time
import socket
import sys
import sqlite3 as lite
from twisted.internet import defer, reactor
from twisted.internet.protocol import ServerFactory, ClientFactory, Protocol
from twisted.protocols.basic import LineReceiver, NetstringReceiver
from twisted.protocols import basic

clients = []

class BARServerProtocol(NetstringReceiver):

    def connectionMade(self):
        clients.append(self)
        self.sendString("=== BAR Server ===")

    def stringReceived(self, data):
        if data[:9] == "BROADCAST":
            self.broadcast(data)
        elif data[:4] == "QUIT":
            self.close_connection()
        else:
            self.sendString("I can break rules too.")

    def broadcast(self, data):
        if len(data) <= 11:
            self.sendString("Ok, but where's the message to broadcast?")
        else:
            message = data[10:]
	    print "Starting broadcast from: " + self.transport.getPeer().host
            for client in clients:
		if self.transport.getPeer().host != client.transport.getPeer().host:
                	client.sendString(message)
            self.sendString("OK")

    def close_connection(self):
        self.transport.loseConnection()

    def connectionLost(self, reason):
        clients.remove(self)

class BARServerFactory(ServerFactory):
    protocol = BARServerProtocol

def server_main():
    factory = BARServerFactory()
    port = reactor.listenTCP(231, factory,
                             #interface=socket.gethostbyaddr(socket.gethostbyname(socket.gethostname()))[2][0])
                            interface='192.168.1.2')
    print 'Serving on %s.' % (port.getHost())
    reactor.run()

if __name__ == '__main__':
    server_main()
<commit_msg>Grab public ip.<commit_after>import os
import time
import socket
import sys
import urllib2
import sqlite3 as lite
from twisted.internet import defer, reactor
from twisted.internet.protocol import ServerFactory, ClientFactory, Protocol
from twisted.protocols.basic import LineReceiver, NetstringReceiver
from twisted.protocols import basic

clients = []

class BARServerProtocol(NetstringReceiver):

    def connectionMade(self):
        clients.append(self)
        self.sendString("=== BAR Server ===")

    def stringReceived(self, data):
        if data[:9] == "BROADCAST":
            self.broadcast(data)
        elif data[:4] == "QUIT":
            self.close_connection()
        else:
            self.sendString("I can break rules too.")

    def broadcast(self, data):
        if len(data) <= 11:
            self.sendString("Ok, but where's the message to broadcast?")
        else:
            message = data[10:]
	    print "Starting broadcast from: " + self.transport.getPeer().host
            for client in clients:
		if self.transport.getPeer().host != client.transport.getPeer().host:
                	client.sendString(message)
            self.sendString("OK")

    def close_connection(self):
        self.transport.loseConnection()

    def connectionLost(self, reason):
        clients.remove(self)

class BARServerFactory(ServerFactory):
    protocol = BARServerProtocol

def server_main():
    factory = BARServerFactory()
    port = reactor.listenTCP(231, factory,
                             #interface=socket.gethostbyaddr(socket.gethostbyname(socket.gethostname()))[2][0])
                            interface=urllib2.urlopen('http://ip.42.pl/raw').read())
    print 'Serving on %s.' % (port.getHost())
    reactor.run()

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


<commit_before>"""
Wextracto is a library for extracting data from web resources.

:copyright: (c) 2012-2015

"""

__version__ = '0.7.3'  # pragma: no cover
<commit_msg>Bump version<commit_after>"""
Wextracto is a library for extracting data from web resources.

:copyright: (c) 2012-2015

"""

__version__ = '0.7.4'  # pragma: no cover
<|endoftext|>