<commit_before>import itertools

from launchpadlib.launchpad import Launchpad

PROJECTS = ['fuel', 'mos']
STATUS = ['New', 'Confirmed', 'Triaged', 'In Progress', 'Incomplete']
TRUNC = 0
BASE_URL = 'https://api.launchpad.net/devel/'
CREATED_SINCE = '2014-09-01'
DEBUG = 0
MAX_CHANGES = -1

def make_changes(prj, milestones_map, bug, to_target_milestones):
    dev_focus_series = prj.development_focus
    prj_name = prj.name
    for tgt in to_target_milestones:
        milestone = prj.getMilestone(name=tgt)
        s_milestone = bug.milestone
        s_status = bug.status
        s_importance = bug.importance
        s_assignee = bug.assignee
        if tgt in milestones_map[dev_focus_series.name]:
            # This is real dirty magic. Needs refactoring.
            # LP, if you try to target dev focus series,
            # will move your bug data over new target. So, if you
            # had no-series bug with 5.1.2, and now targeting
            # 6.1.x, then you'll get moved all 5.1.2 data over.
            # To avoid data loss, we are exchanging data, and not
            # creating series if milestone is from current dev series
            if not DEBUG:
                try:
                    bug.milestone = milestone
                    bug.status = "New"
                    bug.lp_save()
                    series = s_milestone.series_target.name
                    target = BASE_URL + prj_name + '/' + series
                    task_link = bug.bug.addTask(target=target)
                    task_link.milestone = s_milestone
                    task_link.status = s_status
                    task_link.importance = s_importance
                    task_link.assignee = s_assignee
                    task_link.lp_save()
                    continue
                except Exception as e:
                    print('Error: {}'.format(e))

        series = milestone.series_target.name
        target = BASE_URL + prj_name + '/' + series
        # It can raise exception - 400, if series already exists
        if not DEBUG:
            try:
                #TODO: if series already targeted, but not milestone,
                # then we will skip it - as addTask will return an
                # exception: series already exists
                task_link = bug.bug.addTask(target=target)
                # Series already changed at this point of time,
                # lp_save() below is for milestone to change
                milestone_target = BASE_URL + prj_name + \
                    '/+milestone/' + tgt
                task_link.milestone = milestone_target
                task_link.assignee = s_assignee
                task_link.lp_save()
            except Exception as e:
                print('Error: {}'.format(e))

def bug_milestones(bug, dev_focus_milestone_name):
    bug_info = ""
    bug_id = bug.bug.id
    bug_mstn = bug.milestone
    # milestone can be None. It can be non-triaged bug
    # Not sure, if other related tasks could have milestone
    milestones = []

    # Special list for milestones which are inconsistent with series
    ml_to_add = []
    if bug_mstn is not None:
        min_milestone_name = bug_mstn.name
        # We don't want to target milestone, which is there
        # even if there is no series associated
        milestones = [bug_mstn.name]
    else:
        min_milestone_name = dev_focus_milestone_name

    bug_info = "** {} ** TOP bug object, milestone: {}\n".format(
        bug_id, bug_mstn)
    for task in bug.related_tasks:
        bug_info += "**** {} ** affects: {}, milestone: {}\n".format(
            bug_id, task.target.name, task.milestone)
        # We are gethering all milestones bug affects
        # We are not interested in collecting series, as we think
        #  that milestone is our primary key for all work with LP.
        #  For instance, we filter search by milestone.
        if task.milestone is None:
            # Apparently affecting only series, no milestone set
            #TODO: As it seems to be impossible to update existing task,
            # for unknown reason, we may want to lp_delete() and create
            # task from scratch. We need to save assignee, etc. though.
            continue
        milestone_name = task.milestone.name
        milestones.append(milestone_name)
        if milestone_name < min_milestone_name:
            # Looking for lowest milestone set, as we don't trust
            # launchpad in sorting of tasks
            min_milestone_name = milestone_name

        if task.milestone.series_target.name != task.target.name:
            # This is inconsistency which can exist in LP. For instance,
            #  your bug can be assigned to 4.1.2 milestone in 6.0.x series
            #  We want to fix that. All attempts to just update series
            #  for existing bug task failed. So we have to remove bug task
            #  and create it again.
            print("%s: INCONSISTENCY DETECTED: series %s, milestone %s."
                  " Deleting... " % (bug_id,
                                     task.target.name, milestone_name))
            if not DEBUG:
                # TODO: we need to save all status, assignee, etc.,
                #  and reapply it after
                task.lp_delete()
            ml_to_add.append(milestone_name)
    return (bug_info, milestones, ml_to_add, min_milestone_name)

def main():
    # lpbugmanage is the app name. Can be anything
    lp = Launchpad.login_with(
        'lpbugmanage', 'production',
        version='devel', credentials_file='credentials.conf',
    )

    changes = 0
    for prj_name in PROJECTS:
        prj = lp.projects[prj_name]
        dev_focus_series = prj.development_focus
        active_milestones = dev_focus_series.active_milestones
        dev_focus_milestone_name = min([m.name for m in active_milestones])
        dev_focus_milestone = prj.getMilestone(name=dev_focus_milestone_name)
        print("Dev focus milestone: %s" % dev_focus_milestone_name)

        older_series = [s for s in prj.series if s.name <= dev_focus_series.name]
        milestones_map = {}
        milestones_active_map = {}
        for s in older_series:
            milestones_active_map[s.name] = [m.name for m in s.active_milestones]
            milestones_map[s.name] = [m.name for m in s.all_milestones]

        # Let's iterate over all milestones
        # Unfortunately, LP doesn't allow to search over list of milestones
        bugs = prj.searchTasks(status=STATUS, created_since=CREATED_SINCE)
        print("%s: amount of bugs found - %d" % (prj_name, len(list(bugs))))
        for (counter, bug) in enumerate(bugs, 1):
            bug_id = bug.bug.id
            print("Processing bug #%s..." % bug_id)
            bug_info, milestones, ml_to_add, min_milestone_name = \
                    bug_milestones(bug, dev_focus_milestone_name)
            if not ml_to_add:
                if min_milestone_name >= dev_focus_milestone_name:
                    # It is whether non-triaged bug,
                    #   or has dev_focus/higher milestone only
                    print("%s: Skipping this bug: non-triaged or"
                          " has dev_focus/higher milestone only" % bug_id)
                    continue

                if not any(len(x) > 3 for x in milestones):
                    # We don't want to any further processing with this bug:
                    # we want to target only bugs from maintenance milestones
                    # and maintenance are in format X.Y.Z, X.Y-updates,
                    # or X.Y.Z-updates, so certainly more than 3 sym
                    print("%s: This bug is not targeting any maintenance milestone,"
                          " skipping." % bug_id)
                    continue

            print("%s: Lowest milestone: %s" % (bug_id, min_milestone_name))
            # This is real hack, but it does its job:
            #  We need 6.0.x as min for any 6.0, 6.0.1, 6.0-updates, 6.0.1-updates
            min_series_name = min_milestone_name[:3] + '.x'

            # Without -updates for now...
            needed_series_names = filter(
                lambda x: x >= min_series_name,
                [s.name for s in older_series if 'updates' not in s.name])
            # Let's check if we have -updates
            milestones_updates = [x for x in milestones if 'updates' in x]
            if milestones_updates:
                series_with_updates = [prj.getMilestone(name=x).series_target.name
                                       for x in milestones_updates]
                min_series_with_updates = min(series_with_updates)
                needed_series_names += filter(
                    lambda x: x >= min_series_with_updates,
                    [s.name for s in older_series if 'updates' in s.name])

            print("%s: Verifying that bug targets series: %s" %
                  (bug_id, needed_series_names))
            to_target_milestones = []
            for s in needed_series_names:
                if not set(milestones_map[s]) & set(milestones):
                    to_target_milestones.append(min(milestones_active_map[s]))

            to_target_milestones += ml_to_add
            if to_target_milestones:
                print bug_info
                to_target_milestones.sort()
                print("%s: ###### targeting to %s" %
                      (bug.bug.id, to_target_milestones))
                ############
                changes += 1
                make_changes(prj, milestones_map, bug, to_target_milestones)

            if counter > TRUNC and TRUNC > 0:
                break
            if changes >= MAX_CHANGES and MAX_CHANGES != -1:
                break
            if counter % 10 == 0:
                print("Processed %d bugs..." % counter)

        # Let's process all High, Critical in current dev milestone
        status = STATUS + ['Fix Committed', 'Fix Released']
        bugs1 = prj.searchTasks(status=status, milestone=dev_focus_milestone,
                                importance=["Critical"],
                                tags=["-devops", "-fuel-devops"],
                                tags_combinator="All",
                                created_since=CREATED_SINCE)
        bugs2 = prj.searchTasks(status=STATUS, milestone=dev_focus_milestone,
                                tags=['customer-found'],
                                created_since=CREATED_SINCE)
        # If current is 6.1.x, then previous is 6.0.x - which we want to target
        prev_series_name = older_series[-2].name
        for bug in itertools.chain(bugs1, bugs2):
            bug_info, milestones, ml_to_add, min_milestone_name = \
                    bug_milestones(bug, dev_focus_milestone_name)
            to_target_milestones = ml_to_add
            if not set(milestones_map[prev_series_name]) & set(milestones):
                to_target_milestones.append(min(milestones_active_map[prev_series_name]))

            if to_target_milestones:
                print bug_info
                to_target_milestones.sort()
                print("%s: ###### targeting to %s" %
                      (bug.bug.id, to_target_milestones))
                ############
                changes += 1
                make_changes(prj, milestones_map, bug, to_target_milestones)

            if changes >= MAX_CHANGES and MAX_CHANGES != -1:
                break

        print("Total changes made: %d" % changes)

if __name__ == "__main__":
    main()
<commit_msg>Added delete exception handling<commit_after>import itertools

from launchpadlib.launchpad import Launchpad

PROJECTS = ['fuel', 'mos']
STATUS = ['New', 'Confirmed', 'Triaged', 'In Progress', 'Incomplete']
TRUNC = 0
BASE_URL = 'https://api.launchpad.net/devel/'
CREATED_SINCE = '2014-09-01'
DEBUG = 0
MAX_CHANGES = -1

def make_changes(prj, milestones_map, bug, to_target_milestones):
    dev_focus_series = prj.development_focus
    prj_name = prj.name
    for tgt in to_target_milestones:
        milestone = prj.getMilestone(name=tgt)
        s_milestone = bug.milestone
        s_status = bug.status
        s_importance = bug.importance
        s_assignee = bug.assignee
        if tgt in milestones_map[dev_focus_series.name]:
            # This is real dirty magic. Needs refactoring.
            # LP, if you try to target dev focus series,
            # will move your bug data over new target. So, if you
            # had no-series bug with 5.1.2, and now targeting
            # 6.1.x, then you'll get moved all 5.1.2 data over.
            # To avoid data loss, we are exchanging data, and not
            # creating series if milestone is from current dev series
            if not DEBUG:
                try:
                    bug.milestone = milestone
                    bug.status = "New"
                    bug.lp_save()
                    series = s_milestone.series_target.name
                    target = BASE_URL + prj_name + '/' + series
                    task_link = bug.bug.addTask(target=target)
                    task_link.milestone = s_milestone
                    task_link.status = s_status
                    task_link.importance = s_importance
                    task_link.assignee = s_assignee
                    task_link.lp_save()
                    continue
                except Exception as e:
                    print('Error: {}'.format(e))

        series = milestone.series_target.name
        target = BASE_URL + prj_name + '/' + series
        # It can raise exception - 400, if series already exists
        if not DEBUG:
            try:
                #TODO: if series already targeted, but not milestone,
                # then we will skip it - as addTask will return an
                # exception: series already exists
                task_link = bug.bug.addTask(target=target)
                # Series already changed at this point of time,
                # lp_save() below is for milestone to change
                milestone_target = BASE_URL + prj_name + \
                    '/+milestone/' + tgt
                task_link.milestone = milestone_target
                task_link.assignee = s_assignee
                task_link.lp_save()
            except Exception as e:
                print('Error: {}'.format(e))

def bug_milestones(bug, dev_focus_milestone_name):
    bug_info = ""
    bug_id = bug.bug.id
    bug_mstn = bug.milestone
    # milestone can be None. It can be non-triaged bug
    # Not sure, if other related tasks could have milestone
    milestones = []

    # Special list for milestones which are inconsistent with series
    ml_to_add = []
    if bug_mstn is not None:
        min_milestone_name = bug_mstn.name
        # We don't want to target milestone, which is there
        # even if there is no series associated
        milestones = [bug_mstn.name]
    else:
        min_milestone_name = dev_focus_milestone_name

    bug_info = "** {} ** TOP bug object, milestone: {}\n".format(
        bug_id, bug_mstn)
    for task in bug.related_tasks:
        bug_info += "**** {} ** affects: {}, milestone: {}\n".format(
            bug_id, task.target.name, task.milestone)
        # We are gethering all milestones bug affects
        # We are not interested in collecting series, as we think
        #  that milestone is our primary key for all work with LP.
        #  For instance, we filter search by milestone.
        if task.milestone is None:
            # Apparently affecting only series, no milestone set
            #TODO: As it seems to be impossible to update existing task,
            # for unknown reason, we may want to lp_delete() and create
            # task from scratch. We need to save assignee, etc. though.
            continue
        milestone_name = task.milestone.name
        milestones.append(milestone_name)
        if milestone_name < min_milestone_name:
            # Looking for lowest milestone set, as we don't trust
            # launchpad in sorting of tasks
            min_milestone_name = milestone_name

        if task.milestone.series_target.name != task.target.name:
            # This is inconsistency which can exist in LP. For instance,
            #  your bug can be assigned to 4.1.2 milestone in 6.0.x series
            #  We want to fix that. All attempts to just update series
            #  for existing bug task failed. So we have to remove bug task
            #  and create it again.
            print("%s: INCONSISTENCY DETECTED: series %s, milestone %s."
                  " Deleting... " % (bug_id,
                                     task.target.name, milestone_name))
            if not DEBUG:
                # TODO: we need to save all status, assignee, etc.,
                #  and reapply it after
                try:
                    task.lp_delete()
                except Exception as e:
                    print('Error: {}'.format(e))
            ml_to_add.append(milestone_name)
    return (bug_info, milestones, ml_to_add, min_milestone_name)

def main():
    # lpbugmanage is the app name. Can be anything
    lp = Launchpad.login_with(
        'lpbugmanage', 'production',
        version='devel', credentials_file='credentials.conf',
    )

    changes = 0
    for prj_name in PROJECTS:
        prj = lp.projects[prj_name]
        dev_focus_series = prj.development_focus
        active_milestones = dev_focus_series.active_milestones
        dev_focus_milestone_name = min([m.name for m in active_milestones])
        dev_focus_milestone = prj.getMilestone(name=dev_focus_milestone_name)
        print("Dev focus milestone: %s" % dev_focus_milestone_name)

        older_series = [s for s in prj.series if s.name <= dev_focus_series.name]
        milestones_map = {}
        milestones_active_map = {}
        for s in older_series:
            milestones_active_map[s.name] = [m.name for m in s.active_milestones]
            milestones_map[s.name] = [m.name for m in s.all_milestones]

        # Let's iterate over all milestones
        # Unfortunately, LP doesn't allow to search over list of milestones
        bugs = prj.searchTasks(status=STATUS, created_since=CREATED_SINCE)
        print("%s: amount of bugs found - %d" % (prj_name, len(list(bugs))))
        for (counter, bug) in enumerate(bugs, 1):
            bug_id = bug.bug.id
            print("Processing bug #%s..." % bug_id)
            bug_info, milestones, ml_to_add, min_milestone_name = \
                    bug_milestones(bug, dev_focus_milestone_name)
            if not ml_to_add:
                if min_milestone_name >= dev_focus_milestone_name:
                    # It is whether non-triaged bug,
                    #   or has dev_focus/higher milestone only
                    print("%s: Skipping this bug: non-triaged or"
                          " has dev_focus/higher milestone only" % bug_id)
                    continue

                if not any(len(x) > 3 for x in milestones):
                    # We don't want to any further processing with this bug:
                    # we want to target only bugs from maintenance milestones
                    # and maintenance are in format X.Y.Z, X.Y-updates,
                    # or X.Y.Z-updates, so certainly more than 3 sym
                    print("%s: This bug is not targeting any maintenance milestone,"
                          " skipping." % bug_id)
                    continue

            print("%s: Lowest milestone: %s" % (bug_id, min_milestone_name))
            # This is real hack, but it does its job:
            #  We need 6.0.x as min for any 6.0, 6.0.1, 6.0-updates, 6.0.1-updates
            min_series_name = min_milestone_name[:3] + '.x'

            # Without -updates for now...
            needed_series_names = filter(
                lambda x: x >= min_series_name,
                [s.name for s in older_series if 'updates' not in s.name])
            # Let's check if we have -updates
            milestones_updates = [x for x in milestones if 'updates' in x]
            if milestones_updates:
                series_with_updates = [prj.getMilestone(name=x).series_target.name
                                       for x in milestones_updates]
                min_series_with_updates = min(series_with_updates)
                needed_series_names += filter(
                    lambda x: x >= min_series_with_updates,
                    [s.name for s in older_series if 'updates' in s.name])

            print("%s: Verifying that bug targets series: %s" %
                  (bug_id, needed_series_names))
            to_target_milestones = []
            for s in needed_series_names:
                if not set(milestones_map[s]) & set(milestones):
                    if s in milestones_active_map and milestones_active_map[s]:
                        to_target_milestones.append(min(milestones_active_map[s]))

            to_target_milestones += ml_to_add
            if to_target_milestones:
                print bug_info
                to_target_milestones.sort()
                print("%s: ###### targeting to %s" %
                      (bug.bug.id, to_target_milestones))
                ############
                changes += 1
                make_changes(prj, milestones_map, bug, to_target_milestones)

            if counter > TRUNC and TRUNC > 0:
                break
            if changes >= MAX_CHANGES and MAX_CHANGES != -1:
                break
            if counter % 10 == 0:
                print("Processed %d bugs..." % counter)

        # Let's process all High, Critical in current dev milestone
        status = STATUS + ['Fix Committed', 'Fix Released']
        bugs1 = prj.searchTasks(status=status, milestone=dev_focus_milestone,
                                importance=["Critical"],
                                tags=["-devops", "-fuel-devops"],
                                tags_combinator="All",
                                created_since=CREATED_SINCE)
        bugs2 = prj.searchTasks(status=STATUS, milestone=dev_focus_milestone,
                                tags=['customer-found'],
                                created_since=CREATED_SINCE)
        # If current is 6.1.x, then previous is 6.0.x - which we want to target
        prev_series_name = older_series[-2].name
        for bug in itertools.chain(bugs1, bugs2):
            bug_info, milestones, ml_to_add, min_milestone_name = \
                    bug_milestones(bug, dev_focus_milestone_name)
            to_target_milestones = ml_to_add
            if not set(milestones_map[prev_series_name]) & set(milestones):
                to_target_milestones.append(min(milestones_active_map[prev_series_name]))

            if to_target_milestones:
                print bug_info
                to_target_milestones.sort()
                print("%s: ###### targeting to %s" %
                      (bug.bug.id, to_target_milestones))
                ############
                changes += 1
                make_changes(prj, milestones_map, bug, to_target_milestones)

            if changes >= MAX_CHANGES and MAX_CHANGES != -1:
                break

        print("Total changes made: %d" % changes)

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


<commit_before># -*- coding: utf-8 -*-
#
# Copyright 2012-2015 Spotify AB
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""
Locking functionality when launching things from the command line.
Uses a pidfile.
This prevents multiple identical workflows to be launched simultaneously.
"""
from __future__ import print_function

import hashlib
import os
import sys
from subprocess import Popen, PIPE

def getpcmd(pid):
    """
    Returns command of process.

    :param pid:
    """
    if os.name == "nt":
        # Use wmic command instead of ps on Windows.
        cmd = 'wmic path win32_process where ProcessID=%s get Commandline' % (pid, )
        with os.popen(cmd, 'r') as p:
            lines = [line for line in p.readlines() if line.strip("\r\n ") != ""]
            if lines:
                _, val = lines
                return val
    elif sys.platform == "darwin":
        # Use pgrep instead of /proc on macOS.
        pidfile = ".%d.pid" % (pid, )
        with open(pidfile, 'w') as f:
            f.write(str(pid))
        try:
            p = Popen(['pgrep', '-lf', '-F', pidfile], stdout=PIPE)
            stdout, _ = p.communicate()
            line = stdout.decode('utf8').strip()
            if line:
                _, scmd = line.split(' ', 1)
                return scmd
        finally:
            os.unlink(pidfile)
    else:
        # Use the /proc filesystem
        # At least on android there have been some issues with not all
        # process infos being readable. In these cases using the `ps` command
        # worked. See the pull request at
        # https://github.com/spotify/luigi/pull/1876
        try:
            with open('/proc/{0}/cmdline'.format(pid), 'r') as fh:
                return fh.read().replace('\0', ' ').rstrip()
        except IOError:
            # the system may not allow reading the command line
            # of a process owned by another user
            pass

    # Fallback instead of None, for e.g. Cygwin where -o is an "unknown option" for the ps command:
    return '[PROCESS_WITH_PID={}]'.format(pid)

def get_info(pid_dir, my_pid=None):
    # Check the name and pid of this process
    if my_pid is None:
        my_pid = os.getpid()

    my_cmd = getpcmd(my_pid)
    cmd_hash = my_cmd.encode('utf8')
    pid_file = os.path.join(pid_dir, hashlib.md5(cmd_hash).hexdigest()) + '.pid'

    return my_pid, my_cmd, pid_file

def acquire_for(pid_dir, num_available=1, kill_signal=None):
    """
    Makes sure the process is only run once at the same time with the same name.

    Notice that we since we check the process name, different parameters to the same
    command can spawn multiple processes at the same time, i.e. running
    "/usr/bin/my_process" does not prevent anyone from launching
    "/usr/bin/my_process --foo bar".
    """

    my_pid, my_cmd, pid_file = get_info(pid_dir)

    # Check if there is a pid file corresponding to this name
    if not os.path.exists(pid_dir):
        os.mkdir(pid_dir)
        os.chmod(pid_dir, 0o777)

    # Let variable "pids" be all pids who exist in the .pid-file who are still
    # about running the same command.
    pids = {pid for pid in _read_pids_file(pid_file) if getpcmd(pid) == my_cmd}

    if kill_signal is not None:
        for pid in pids:
            os.kill(pid, kill_signal)
        print('Sent kill signal to Pids: {}'.format(pids))
        # We allow for the killer to progress, yet we don't want these to stack
        # up! So we only allow it once.
        num_available += 1

    if len(pids) >= num_available:
        # We are already running under a different pid
        print('Pid(s) {} already running'.format(pids))
        if kill_signal is not None:
            print('Note: There have (probably) been 1 other "--take-lock"'
                  ' process which continued to run! Probably no need to run'
                  ' this one as well.')
        return False

    _write_pids_file(pid_file, pids | {my_pid})

    return True

def _read_pids_file(pid_file):
    # First setup a python 2 vs 3 compatibility
    # http://stackoverflow.com/a/21368622/621449
    try:
        FileNotFoundError
    except NameError:
        # Should only happen on python 2
        FileNotFoundError = IOError
    # If the file happen to not exist, simply return
    # an empty set()
    try:
        with open(pid_file, 'r') as f:
            return {int(pid_str.strip()) for pid_str in f if pid_str.strip()}
    except FileNotFoundError:
        return set()

def _write_pids_file(pid_file, pids_set):
    with open(pid_file, 'w') as f:
        f.writelines('{}\n'.format(pid) for pid in pids_set)

    # Make the .pid-file writable by all (when the os allows for it)
    if os.name != 'nt':
        s = os.stat(pid_file)
        if os.getuid() == s.st_uid:
            os.chmod(pid_file, s.st_mode | 0o777)
<commit_msg>Fix decode to utf8 when reading /proc/*/cmdline<commit_after># -*- coding: utf-8 -*-
#
# Copyright 2012-2015 Spotify AB
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""
Locking functionality when launching things from the command line.
Uses a pidfile.
This prevents multiple identical workflows to be launched simultaneously.
"""
from __future__ import print_function

import hashlib
import os
import sys
from subprocess import Popen, PIPE

def getpcmd(pid):
    """
    Returns command of process.

    :param pid:
    """
    if os.name == "nt":
        # Use wmic command instead of ps on Windows.
        cmd = 'wmic path win32_process where ProcessID=%s get Commandline' % (pid, )
        with os.popen(cmd, 'r') as p:
            lines = [line for line in p.readlines() if line.strip("\r\n ") != ""]
            if lines:
                _, val = lines
                return val
    elif sys.platform == "darwin":
        # Use pgrep instead of /proc on macOS.
        pidfile = ".%d.pid" % (pid, )
        with open(pidfile, 'w') as f:
            f.write(str(pid))
        try:
            p = Popen(['pgrep', '-lf', '-F', pidfile], stdout=PIPE)
            stdout, _ = p.communicate()
            line = stdout.decode('utf8').strip()
            if line:
                _, scmd = line.split(' ', 1)
                return scmd
        finally:
            os.unlink(pidfile)
    else:
        # Use the /proc filesystem
        # At least on android there have been some issues with not all
        # process infos being readable. In these cases using the `ps` command
        # worked. See the pull request at
        # https://github.com/spotify/luigi/pull/1876
        try:
            with open('/proc/{0}/cmdline'.format(pid), 'r') as fh:
                return fh.read().replace('\0', ' ').decode('utf8').rstrip()
        except IOError:
            # the system may not allow reading the command line
            # of a process owned by another user
            pass

    # Fallback instead of None, for e.g. Cygwin where -o is an "unknown option" for the ps command:
    return '[PROCESS_WITH_PID={}]'.format(pid)

def get_info(pid_dir, my_pid=None):
    # Check the name and pid of this process
    if my_pid is None:
        my_pid = os.getpid()

    my_cmd = getpcmd(my_pid)
    cmd_hash = my_cmd.encode('utf8')
    pid_file = os.path.join(pid_dir, hashlib.md5(cmd_hash).hexdigest()) + '.pid'

    return my_pid, my_cmd, pid_file

def acquire_for(pid_dir, num_available=1, kill_signal=None):
    """
    Makes sure the process is only run once at the same time with the same name.

    Notice that we since we check the process name, different parameters to the same
    command can spawn multiple processes at the same time, i.e. running
    "/usr/bin/my_process" does not prevent anyone from launching
    "/usr/bin/my_process --foo bar".
    """

    my_pid, my_cmd, pid_file = get_info(pid_dir)

    # Check if there is a pid file corresponding to this name
    if not os.path.exists(pid_dir):
        os.mkdir(pid_dir)
        os.chmod(pid_dir, 0o777)

    # Let variable "pids" be all pids who exist in the .pid-file who are still
    # about running the same command.
    pids = {pid for pid in _read_pids_file(pid_file) if getpcmd(pid) == my_cmd}

    if kill_signal is not None:
        for pid in pids:
            os.kill(pid, kill_signal)
        print('Sent kill signal to Pids: {}'.format(pids))
        # We allow for the killer to progress, yet we don't want these to stack
        # up! So we only allow it once.
        num_available += 1

    if len(pids) >= num_available:
        # We are already running under a different pid
        print('Pid(s) {} already running'.format(pids))
        if kill_signal is not None:
            print('Note: There have (probably) been 1 other "--take-lock"'
                  ' process which continued to run! Probably no need to run'
                  ' this one as well.')
        return False

    _write_pids_file(pid_file, pids | {my_pid})

    return True

def _read_pids_file(pid_file):
    # First setup a python 2 vs 3 compatibility
    # http://stackoverflow.com/a/21368622/621449
    try:
        FileNotFoundError
    except NameError:
        # Should only happen on python 2
        FileNotFoundError = IOError
    # If the file happen to not exist, simply return
    # an empty set()
    try:
        with open(pid_file, 'r') as f:
            return {int(pid_str.strip()) for pid_str in f if pid_str.strip()}
    except FileNotFoundError:
        return set()

def _write_pids_file(pid_file, pids_set):
    with open(pid_file, 'w') as f:
        f.writelines('{}\n'.format(pid) for pid in pids_set)

    # Make the .pid-file writable by all (when the os allows for it)
    if os.name != 'nt':
        s = os.stat(pid_file)
        if os.getuid() == s.st_uid:
            os.chmod(pid_file, s.st_mode | 0o777)
<|endoftext|>


<commit_before>from flask import Flask
from flask import render_template, Response, request, abort
from babel.dates import format_timedelta
import json
import logging
import os

app = Flask(__name__)

logs_location = '/var/log/lumens'

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/logs/')
def logs(log=None):
    logs = []
    if log is None:
        for log in os.listdir(logs_location):
            logs.append(log)
    return render_template('logs.html', logs=logs)

@app.route('/logs/<log>')
def view_log(log=None):
    fo = open('%s/%s' % (logs_location, log), 'r')
    contents = fo.read()
    fo.close()
    return Response(contents, mimetype='text/plain')

@app.route('/toggle', methods=['POST'])
def toggle():
    if request.method == 'POST':
        led = request.form['led']
        logging.getLogger('lumens').debug('toggle switch web %s' % led)
        lumen_control.toggle(led)
    return 'ko'

def start(_lumens):
    global lumen_control
    lumen_control = _lumens

    # app.debug = True
    app.run(host='0.0.0.0', threaded=True)

<commit_msg>adda install script<commit_after>from flask import Flask
from flask import render_template, Response, request
import logging
import os

app = Flask(__name__)

logs_location = '/var/log/lumens'

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/logs/')
def logs(log=None):
    logs = []
    if log is None:
        for log in os.listdir(logs_location):
            logs.append(log)
    return render_template('logs.html', logs=logs)

@app.route('/logs/<log>')
def view_log(log=None):
    fo = open('%s/%s' % (logs_location, log), 'r')
    contents = fo.read()
    fo.close()
    return Response(contents, mimetype='text/plain')

@app.route('/toggle', methods=['POST'])
def toggle():
    if request.method == 'POST':
        led = request.form['led']
        logging.getLogger('lumens').debug('toggle switch web %s' % led)
        lumen_control.toggle(led)
    return 'ko'

def start(_lumens):
    global lumen_control
    lumen_control = _lumens

    # app.debug = True
    app.run(host='0.0.0.0', threaded=True)

<|endoftext|>


<commit_before>
import numpy
from numpy import pi
pc = 3.086e18 # cm
c = 2.99792458e10 # cm/s
lsun = 3.839e33 # erg/s

class luminosity:
    """
    Measures luminosity from an SED following the method of Kauffmann et al 2008

    For frequency, bandwidth, etc. see http://casa.colorado.edu/~ginsbura/filtersets.htm

    Units are CGS

    nu - frequency (assumed Hz)
    wnu - width of frequency bin
    fnu - flux (assumed Jy)
    efnu - flux error
    """

    def __init__(self,nu,fnu,wnu=None,efnu=None,dist_pc=None,npoints=1e5):

        self.nu   = numpy.asarray(nu)
        nusort = numpy.argsort(self.nu)
        self.nu = self.nu[nusort]
        try:
            self.wnu  = numpy.asarray(wnu)[nusort]
        except:
            self.wnu = wnu
        self.fnu  = numpy.asarray(fnu)[nusort]
        try:
            self.efnu = numpy.asarray(efnu)[nusort]
        except:
            self.efnu = efnu
        self.dist_pc = dist_pc
        self.init_interp(npoints)

    def fbol_meas(self):
        """
        Returns the total integrated flux (int[nu fnu dnu]) measured within
        the bands.  Does not interpolate

        The Casoli et al 1986 formula is not used...
        FIR (10^-13 W m^-2) = 1.75 ( F12 / 0.79 + F25/2 + F60/3.9 + F100/9.9 )
        """
        self._intflux = ( self.fnu * self.wnu ).sum()
        return self._intflux

    def lbol_meas(self,dist_pc=None):
        """
        Returned the luminosity within the measured bins.  Does not interpolate.
        A distance must be specified either here or in the initialization
        """

        if dist_pc is not None:
            self.dist_pc = dist_pc
        elif self.dist_pc is None:
            raise ValueError("Must specify distance to compute luminosity")

        lum = 4*pi*(self.dist_pc*pc)**2 * self.fbol_meas() * 1e-23 / lsun

        return lum

    def init_interp(self,npoints):
        """
        initializes the interpolation parameters
        """
        self.interpnu = 10**numpy.linspace(numpy.log10(self.nu[0]),numpy.log10(self.nu[-1]),npoints)
        self.interpfnu = self.interpnu*0.0
        self.addedpoint = False

    def mminterp(self,freq,lowfreq=c/500e-4,alpha=4.0,addpoint=True):
        """
        Creates an interpolated point using an assumed nu^alpha opacity...
        defaults to alpha=4

        Default point location is 500 microns
        """

        if freq is None:
            whpt = numpy.argmin(self.nu)
        else:
            whpt = (self.nu==freq)

        if whpt == numpy.array([]):
            raise ValueError("Couldn't find a data point at that frequency.  Please check your \
                    input frequency, input data, or a floating point match.")

        numm = self.nu[whpt]
        fnumm = self.fnu[whpt]

        userange = (self.interpnu < freq) * (self.interpnu > lowfreq)
        self.interpfnu[userange] = fnumm * (self.interpnu[userange]/numm)**alpha

        if addpoint and not self.addedpoint:
            newfnu = fnumm * (lowfreq/numm)**alpha
            self.fnu = numpy.concatenate((self.fnu,numpy.array([newfnu])))
            self.nu = numpy.concatenate((self.nu,numpy.array([lowfreq])))
            nusort = numpy.argsort(self.nu)
            self.nu = self.nu[nusort]
            self.fnu = self.fnu[nusort]
            self.addedpoint = True

    def fbol_interp(self,mminterp=True,npoints=1e5,addpoint=True,mmfreq=None,extrap=False):
        """
        Interpolates between data points to integrate over SED

        If mminterp is set, will assume a nu^4 power law (opacity lambda^-2)

        Returns int( nuFnu ) in units HzJy

        Extrapolate via a constant line at the low/high frequency data point
        """

        if mminterp:
            self.mminterp(mmfreq,addpoint=addpoint)

        # powerlaw interpolation is done in logspace
        logf = numpy.log10(self.fnu)
        logn = numpy.log10(self.nu)

        # slope = dy/dx
        alpha = ( logf[:-1]-logf[1:] ) / ( logn[:-1]-logn[1:] )

        # evenly spaced sampling in logspace
        newnu  = self.interpnu
        newfnu = self.interpfnu

        # need to loop through data and interpolate
        for ind in numpy.arange(len(logn)-1):
            lownu  = self.nu[ind]
            highnu = self.nu[ind+1]
            userange = (newnu > lownu) * (newnu < highnu)
            nu0 = newnu[userange][0]
            newfnu[userange] = self.fnu[ind] * (newnu[userange]/nu0)**alpha[ind]

        dnu = newnu*0
        dnu[:-1] = newnu[:-1]-newnu[1:]
        dnu[-1] = dnu[-2]
        self.interpdnu = numpy.abs(dnu)

        self.interpnu = newnu
        self.interpfnu = newfnu

        self._fbol_integ = (self.interpdnu*self.interpfnu).sum()

        return self._fbol_integ

    def lbol_interp(self,**kwargs):
        """
        Bolometric luminosity from interpolation in units of solar luminosities
        """

        self._lbol_interp = 4*pi*(self.dist_pc*pc)**2 * self.fbol_interp(**kwargs) * 1e-23 / lsun

        return self._lbol_interp

    """
    Test case:

    nu = c/array([12e-4,25e-4,60e-4,100e-4,.12])
    fnu = [4.97,26.08,66.34,80.04,3.06]
    """

import readcol

def test_case():
    """ A specific test case using the Klein 2005 luminosity computations """

    dtab = readcol.readcol('/Users/adam/agpy/tests/klein2005sourcelist.txt',skipline=33,fsep='|')

    kleinlum = dtab[:,5].astype('float')

    irasfluxes = dtab[:,numpy.array([22,25,28,31])].astype('float')
    dist = dtab[:,3].astype('float')*1000

    mylum = kleinlum*0
    mylum_interp = kleinlum*0
    nu = c*1e4/numpy.array([12.0,25.0,60.0,100.0])
    dnu = numpy.array([1.53e13,5.789e12,3.75e12, 1.114e12])

    mlarr = []

    for ind in xrange(len(mylum)):
        ml = luminosity(nu,irasfluxes[ind],dnu,dist_pc=dist[ind])
        mylum[ind] = ml.lbol_meas()
        mylum_interp[ind] = ml.lbol_interp(addpoint=False)
        mlarr.append(ml)

    return kleinlum,mylum,mylum_interp,mlarr

<commit_msg>Added plotting capability to luminosity.py<commit_after>
import numpy
try:
    import pylab
    pylabok = True
except:
    pylabok = False
    print "Pylab could not be imported; plotting functions will be disabled"
from numpy import pi
pc = 3.086e18 # cm
c = 2.99792458e10 # cm/s
lsun = 3.839e33 # erg/s

class luminosity:
    """
    Measures luminosity from an SED following the method of Kauffmann et al 2008
    http://adsabs.harvard.edu/abs/2008A%26A...487..993K

    For frequency, bandwidth, etc. see http://casa.colorado.edu/~ginsbura/filtersets.htm

    Units are CGS

    nu - frequency (assumed Hz)
    wnu - [optional/required for non-interpolation] width of frequency bin
    fnu - flux (assumed Jy)
    efnu - [optional; currently does nothing] flux error
    """

    def __init__(self,nu,fnu,wnu=None,efnu=None,dist_pc=None,npoints=1e5):

        self.nu   = numpy.asarray(nu)
        nusort = numpy.argsort(self.nu)
        self.nu = self.nu[nusort]
        try:
            self.wnu  = numpy.asarray(wnu)[nusort]
        except:
            self.wnu = wnu
        self.fnu  = numpy.asarray(fnu)[nusort]
        try:
            self.efnu = numpy.asarray(efnu)[nusort]
        except:
            self.efnu = efnu
        self.dist_pc = dist_pc
        self.init_interp(npoints)

    def fbol_meas(self):
        """
        Returns the total integrated flux (int[nu fnu dnu]) measured within
        the bands.  Does not interpolate

        The Casoli et al 1986 formula is not used...
        FIR (10^-13 W m^-2) = 1.75 ( F12 / 0.79 + F25/2 + F60/3.9 + F100/9.9 )
        """
        self._intflux = ( self.fnu * self.wnu ).sum()
        return self._intflux

    def lbol_meas(self,dist_pc=None):
        """
        Returned the luminosity within the measured bins.  Does not interpolate.
        A distance must be specified either here or in the initialization
        """

        if dist_pc is not None:
            self.dist_pc = dist_pc
        elif self.dist_pc is None:
            raise ValueError("Must specify distance to compute luminosity")

        lum = 4*pi*(self.dist_pc*pc)**2 * self.fbol_meas() * 1e-23 / lsun

        return lum

    def init_interp(self,npoints):
        """
        initializes the interpolation parameters
        """
        self.interpnu = 10**numpy.linspace(numpy.log10(self.nu[0]),numpy.log10(self.nu[-1]),npoints)
        self.interpfnu = self.interpnu*0.0
        self.addedpoint = False

    def mminterp(self,freq,lowfreq=c/500e-4,alpha=4.0,addpoint=True):
        """
        Creates an interpolated point using an assumed nu^alpha opacity...
        defaults to alpha=4

        Default point location is 500 microns
        """

        if freq is None:
            whpt = numpy.argmin(self.nu)
        else:
            whpt = (self.nu==freq)

        if whpt == numpy.array([]):
            raise ValueError("Couldn't find a data point at that frequency.  Please check your \
                    input frequency, input data, or a floating point match.")

        numm = self.nu[whpt]
        fnumm = self.fnu[whpt]

        userange = (self.interpnu < freq) * (self.interpnu > lowfreq)
        self.interpfnu[userange] = fnumm * (self.interpnu[userange]/numm)**alpha

        if addpoint and not self.addedpoint:
            newfnu = fnumm * (lowfreq/numm)**alpha
            self.fnu = numpy.concatenate((self.fnu,numpy.array([newfnu])))
            self.nu = numpy.concatenate((self.nu,numpy.array([lowfreq])))
            nusort = numpy.argsort(self.nu)
            self.nu = self.nu[nusort]
            self.fnu = self.fnu[nusort]
            self.addedpoint = True

            if self.efnu is not None:
                self.efnu = numpy.concatenate((self.efnu,numpy.array([0.0])))
                self.efnu = self.efnu[nusort]
            if self.wnu is not None:
                self.wnu = numpy.concatenate((self.wnu,numpy.array([0.0])))
                self.wnu = self.wnu[nusort]

    def fbol_interp(self,mminterp=True,npoints=1e5,addpoint=True,mmfreq=None,extrap=True):
        """
        Interpolates between data points to integrate over SED

        If mminterp is set, will assume a nu^4 power law (opacity lambda^-2)

        Returns int( nuFnu ) in units HzJy

        Extrapolate via a constant line at the low/high frequency data point
        """

        if mminterp:
            self.mminterp(mmfreq,addpoint=addpoint)

        # powerlaw interpolation is done in logspace
        logf = numpy.log10(self.fnu)
        logn = numpy.log10(self.nu)

        # slope = dy/dx
        alpha = ( logf[:-1]-logf[1:] ) / ( logn[:-1]-logn[1:] )

        # evenly spaced sampling in logspace
        newnu  = self.interpnu
        newfnu = self.interpfnu

        # need to loop through data and interpolate
        for ind in numpy.arange(len(logn)-1):
            lownu  = self.nu[ind]
            highnu = self.nu[ind+1]
            userange = (newnu > lownu) * (newnu < highnu)
            nu0 = newnu[userange][0]
            newfnu[userange] = self.fnu[ind] * (newnu[userange]/nu0)**alpha[ind]

        dnu = newnu*0
        dnu[:-1] = newnu[:-1]-newnu[1:]
        dnu[-1] = dnu[-2]

        if extrap:
            # extrapolate 50% from either endpoint
            nulow = newnu.min()/2.0
            nuhigh = newnu.max()*2.0
            dnulow = newnu.min()-nulow
            dnuhigh = newnu.max()-nuhigh
            newnu  = numpy.concatenate( ([nulow],newnu,[nuhigh]) )
            newfnu = numpy.concatenate( ([newfnu[0]],newfnu,[newfnu[-1]]) )
            dnu    = numpy.concatenate( ([dnulow],dnu,[dnuhigh]) )

        self.interpdnu = numpy.abs(dnu)
        self.interpnu = newnu
        self.interpfnu = newfnu

        self._fbol_integ = (self.interpdnu*self.interpfnu).sum()

        return self._fbol_integ

    def lbol_interp(self,**kwargs):
        """
        Bolometric luminosity from interpolation in units of solar luminosities
        """

        self._lbol_interp = 4*pi*(self.dist_pc*pc)**2 * self.fbol_interp(**kwargs) * 1e-23 / lsun

        return self._lbol_interp

    def plotsed(self,loglog=True):
        """ Plots the SED """
        if not pylabok:
            print "pylab was not successfully imported.  Aborting."
            return

        pylab.errorbar(self.nu,self.fnu,xerr=self.wnu,yerr=self.efnu,fmt=None)
        ax = pylab.gca()
        if loglog:
            ax.set_xscale('log')
            ax.set_yscale('log')
        else:
            ax.set_xscale('linear')
            ax.set_yscale('linear')

        return ax

    """
    Test case:

    nu = c/array([12e-4,25e-4,60e-4,100e-4,.12])
    fnu = [4.97,26.08,66.34,80.04,3.06]
    """

import readcol

def test_case():
    """ A specific test case using the Klein 2005 luminosity computations """

    dtab = readcol.readcol('/Users/adam/agpy/tests/klein2005sourcelist.txt',skipline=33,fsep='|')

    kleinlum = dtab[:,5].astype('float')

    irasfluxes = dtab[:,numpy.array([22,25,28,31])].astype('float')
    dist = dtab[:,3].astype('float')*1000

    mylum = kleinlum*0
    mylum_interp = kleinlum*0
    nu = c*1e4/numpy.array([12.0,25.0,60.0,100.0])
    dnu = numpy.array([1.53e13,5.789e12,3.75e12, 1.114e12])

    mlarr = []

    for ind in xrange(len(mylum)):
        ml = luminosity(nu,irasfluxes[ind],dnu,dist_pc=dist[ind])
        mylum[ind] = ml.lbol_meas()
        mylum_interp[ind] = ml.lbol_interp(addpoint=False,extrap=True)
        mlarr.append(ml)

    return kleinlum,mylum,mylum_interp,mlarr

<|endoftext|>


<commit_before>"""
Lists are a bindable containers.

All list classes include an internal BoundCollection (see obervable.py) The
BoundCollections will automatically populate the list with widgets as the
underlying collection changes.

By default, entries will appear as Buttons (the labels will display the string
representation of the underlying objects). However most often users will create
custom widgets -- which can be entire miniature layouts of their own with
layouts and controls-- using custom subclasses of the ItemTemplate class (for an
example of this in action see 'modMgr.py' in the examples)

There are a variety of List classes to handle vertical, horizontal and more
complex layout needs. Lists come with inherent scollbars if their contents are
too large to display.
"""
import maya.cmds as cmds

import mGui.forms as forms
import mGui.observable as observable
import mGui.core.controls as controls
import mGui.core.layouts as layouts
import mGui.events as events
import time

class FormList(object):
    """
    Adds a BoundCollection to a Layout class. Will call the owning class's
    layout() method when the collection changes, and will prune the layouts
    control sets as items are added to or removed from the bound collection.
    """
    SCROLL_WIDTH = 33

    def __init_bound_collection__(self, kwargs):
        """
        initialize the mixin. Call after the layout constructor, eg:

            super(MyBoundFormClass, self).__init__(key, *args, **kwargs)
            self.__init_bound_collection__()

        """
        self.template = kwargs.pop('itemTemplate', ItemTemplate)(self)
        self.sync = kwargs.pop('synchronous', True)
        self.redraw_options = {}

        event_class = events.Event
        collection_class = observable.ImmediateBoundCollection

        if not self.sync:
            event_class = events.MayaEvent
            collection_class = observable.BoundCollection

        self.collection = collection_class()
        self.onWidgetCreated = event_class(type='widget created')
        self.onUpdated = event_class(type='updated')

        self.collection.CollectionChanged += self.redraw  # automatically forward collection changes

    def redraw(self, *args, **kwargs):
        """
        NOTE: depends on the LIST_CLASS being set in the actual class!
        """
        try:
            cmds.waitCursor(st=1)

            self.named_children = {}
            self.controls = []

            seed = int(time.time())

            cmds.setParent(self)
            with self:
                with layouts.ScrollLayout('mGui_scroll_%i' % seed, childResizable=True) as inner_scroll:
                    with self.LIST_CLASS('mGui_list_%i' % seed, **self.redraw_options) as inner_list:
                        for item in self.collection:
                            w = self.template.widget(item)
                            self.widget_added(w)

            cmds.setParent(self)
            cmds.setParent("..")

            # controls only includes 'inner_scroll' for layout
            self.named_children['inner_scroll'] = inner_scroll
            self.named_children['inner_list'] = inner_list
            self.controls = [inner_scroll]

        finally:
            self.layout()
            cmds.waitCursor(st=0)

    def widget_added(self, templated_item):
        """
        by default, raise the NewWidget event
        but can be overridden to handle here instead
        """
        self.onWidgetCreated(item=templated_item)

    def gui_contents(self):
        for item in self.inner_list.controls:
            yield item

    def contents(self):
        for item in self.collection:
            yield item

class VerticalList(forms.FillForm, FormList):
    """
    A vertical list of items with an automatic scrollbar
    """

    LIST_CLASS = forms.VerticalForm

    def __init__(self, key=None, *args, **kwargs):
        self.__init_bound_collection__(kwargs)
        super(VerticalList, self).__init__(key, *args, **kwargs)
        self.redraw()

    def redraw(self, *args, **kwargs):
        super(VerticalList, self).redraw()
        self.inner_list.width = max(self.width - 33, 33)

class HorizontalList(forms.FillForm, FormList):
    """
    A horizontal list of Items with an automatic scrollbar
    """

    LIST_CLASS = forms.HorizontalForm

    def __init__(self, key=None, *args, **kwargs):
        self.__init_bound_collection__(kwargs)
        super(HorizontalList, self).__init__(key, *args, **kwargs)
        self.redraw()

    def redraw(self, *args, **kwargs):
        super(HorizontalList, self).redraw()
        self.inner_list.height = max(self.width - 33, 33)

class ColumnList(forms.FillForm, FormList):
    LIST_CLASS = layouts.ColumnLayout

    def __init__(self, key=None, *args, **kwargs):
        self.__init_bound_collection__(kwargs)
        super(ColumnList, self).__init__(key, *args, **kwargs)
        self.redraw()

    def redraw(self, *args, **kwargs):
        super(ColumnList, self).redraw()
        self.inner_list.width = max(self.width - 33, 33)

class WrapList(forms.FillForm, FormList):
    """
    A flowLayout based list of items with optional wrapping. This will clip if
    the width exceeds the layout width unles 'wrap' is set to true
    """
    LIST_CLASS = layouts.FlowLayout

    def __init__(self, key=None, *args, **kwargs):
        self.wrap = kwargs.pop('wrap', False)
        self.__init_bound_collection__(kwargs)
        self.redraw_options['wrap'] = self.wrap

        super(WrapList, self).__init__(key, *args, **kwargs)
        self.redraw()

    def redraw(self, *args, **kwargs):
        super(WrapList, self).redraw()
        self.inner_list.height = max(self.height - 33, 33)
        self.inner_list.width = max(self.width - 33, 33)

class Templated(object):
    """
    contains the original data item, the widget represents it, and any named event objects it exposes
    """

    def __init__(self, datum, widget, **named_events):
        self.datum = datum
        self.widget = widget
        self.events = named_events

    def get_event(self, key):
        """
        Return the named event, if present
        """
        return self.events.get(key, None)

class ItemTemplate(object):
    """
    Base class for item template classes.

    The job of an itemTemplate is to provide a GUI widget (which can be a single
    control or a layout with other controls) that represents the underying data    item in the bound data collection.

    """

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

    def widget(self, item):
        """
        returns the topmost mGui item of a templated list item, along with any events defined in the widget
        """

        with forms.HorizontalForm() as root:
            r = controls.Button(label=str(item))
        return Templated(item, root, command=r.command)

    def __call__(self, item):
        return self.widget(item)
<commit_msg>lists don't use names to avoid clashes on fast redraws<commit_after>"""
Lists are a bindable containers.

All list classes include an internal BoundCollection (see obervable.py) The
BoundCollections will automatically populate the list with widgets as the
underlying collection changes.

By default, entries will appear as Buttons (the labels will display the string
representation of the underlying objects). However most often users will create
custom widgets -- which can be entire miniature layouts of their own with
layouts and controls-- using custom subclasses of the ItemTemplate class (for an
example of this in action see 'modMgr.py' in the examples)

There are a variety of List classes to handle vertical, horizontal and more
complex layout needs. Lists come with inherent scollbars if their contents are
too large to display.
"""
import maya.cmds as cmds

import mGui.forms as forms
import mGui.observable as observable
import mGui.core.controls as controls
import mGui.core.layouts as layouts
import mGui.events as events
import time

class FormList(object):
    """
    Adds a BoundCollection to a Layout class. Will call the owning class's
    layout() method when the collection changes, and will prune the layouts
    control sets as items are added to or removed from the bound collection.
    """
    SCROLL_WIDTH = 33

    def __init_bound_collection__(self, kwargs):
        """
        initialize the mixin. Call after the layout constructor, eg:

            super(MyBoundFormClass, self).__init__(key, *args, **kwargs)
            self.__init_bound_collection__()

        """
        self.template = kwargs.pop('itemTemplate', ItemTemplate)(self)
        self.sync = kwargs.pop('synchronous', True)
        self.redraw_options = {}

        event_class = events.Event
        collection_class = observable.ImmediateBoundCollection

        if not self.sync:
            event_class = events.MayaEvent
            collection_class = observable.BoundCollection

        self.collection = collection_class()
        self.onWidgetCreated = event_class(type='widget created')
        self.onUpdated = event_class(type='updated')

        self.collection.CollectionChanged += self.redraw  # automatically forward collection changes

    def redraw(self, *args, **kwargs):
        """
        NOTE: depends on the LIST_CLASS being set in the actual class!
        """
        try:
            cmds.waitCursor(st=1)

            self.named_children = {}
            self.controls = []

            seed = int(time.time())

            cmds.setParent(self)
            with self:
                with layouts.ScrollLayout( childResizable=True) as inner_scroll:
                    with self.LIST_CLASS( **self.redraw_options) as inner_list:
                        for item in self.collection:
                            w = self.template.widget(item)
                            self.widget_added(w)

            cmds.setParent(self)
            cmds.setParent("..")

            # controls only includes 'inner_scroll' for layout
            self.named_children['inner_scroll'] = inner_scroll
            self.named_children['inner_list'] = inner_list
            self.controls = [inner_scroll]

        finally:
            self.layout()
            cmds.waitCursor(st=0)

    def widget_added(self, templated_item):
        """
        by default, raise the NewWidget event
        but can be overridden to handle here instead
        """
        self.onWidgetCreated(item=templated_item)

    def gui_contents(self):
        for item in self.inner_list.controls:
            yield item

    def contents(self):
        for item in self.collection:
            yield item

class VerticalList(forms.FillForm, FormList):
    """
    A vertical list of items with an automatic scrollbar
    """

    LIST_CLASS = forms.VerticalForm

    def __init__(self, key=None, *args, **kwargs):
        self.__init_bound_collection__(kwargs)
        super(VerticalList, self).__init__(key, *args, **kwargs)
        self.redraw()

    def redraw(self, *args, **kwargs):
        super(VerticalList, self).redraw()
        self.inner_list.width = max(self.width - 33, 33)

class HorizontalList(forms.FillForm, FormList):
    """
    A horizontal list of Items with an automatic scrollbar
    """

    LIST_CLASS = forms.HorizontalForm

    def __init__(self, key=None, *args, **kwargs):
        self.__init_bound_collection__(kwargs)
        super(HorizontalList, self).__init__(key, *args, **kwargs)
        self.redraw()

    def redraw(self, *args, **kwargs):
        super(HorizontalList, self).redraw()
        self.inner_list.height = max(self.width - 33, 33)

class ColumnList(forms.FillForm, FormList):
    LIST_CLASS = layouts.ColumnLayout

    def __init__(self, key=None, *args, **kwargs):
        self.__init_bound_collection__(kwargs)
        super(ColumnList, self).__init__(key, *args, **kwargs)
        self.redraw()

    def redraw(self, *args, **kwargs):
        super(ColumnList, self).redraw()
        self.inner_list.width = max(self.width - 33, 33)

class WrapList(forms.FillForm, FormList):
    """
    A flowLayout based list of items with optional wrapping. This will clip if
    the width exceeds the layout width unles 'wrap' is set to true
    """
    LIST_CLASS = layouts.FlowLayout

    def __init__(self, key=None, *args, **kwargs):
        self.wrap = kwargs.pop('wrap', False)
        self.__init_bound_collection__(kwargs)
        self.redraw_options['wrap'] = self.wrap

        super(WrapList, self).__init__(key, *args, **kwargs)
        self.redraw()

    def redraw(self, *args, **kwargs):
        super(WrapList, self).redraw()
        self.inner_list.height = max(self.height - 33, 33)
        self.inner_list.width = max(self.width - 33, 33)

class Templated(object):
    """
    contains the original data item, the widget represents it, and any named event objects it exposes
    """

    def __init__(self, datum, widget, **named_events):
        self.datum = datum
        self.widget = widget
        self.events = named_events

    def get_event(self, key):
        """
        Return the named event, if present
        """
        return self.events.get(key, None)

class ItemTemplate(object):
    """
    Base class for item template classes.

    The job of an itemTemplate is to provide a GUI widget (which can be a single
    control or a layout with other controls) that represents the underying data    item in the bound data collection.

    """

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

    def widget(self, item):
        """
        returns the topmost mGui item of a templated list item, along with any events defined in the widget
        """

        with forms.HorizontalForm() as root:
            r = controls.Button(label=str(item))
        return Templated(item, root, command=r.command)

    def __call__(self, item):
        return self.widget(item)
<|endoftext|>


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

"""
Copyright (C) 2017 IBM Corporation

Licensed under the Apache License, Version 2.0 (the “License”);
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an “AS IS” BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

    Contributors:
        * Roberto Oliveira <rdutra@br.ibm.com>
        * Rafael Sene <rpsene@br.ibm.com>
        * Diego Fernandez-Merjildo <merjildo@br.ibm.com>
"""

from clang.cindex import CursorKind

from report_blocker import ReportBlocker

from problem_reporter import ProblemReporter

class Visitor(object):
    """ Class used to visit the translation unit nodes and run checkers """

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

    def visit_nodes(self, node):
        """ Visit all nodes from translation unit and for each node, call all
        activate checkers to seek for problems """
        if node.kind == CursorKind.MACRO_INSTANTIATION:
            ReportBlocker.check_node(node)

        if self.checker.check(node):
            ProblemReporter.report_problem(node,
                                           self.checker.get_problem_msg(),
                                           self.checker.get_problem_type())

        for node in node.get_children():
            self.visit_nodes(node)
<commit_msg>tools-ma : Fix problem msg and type order on visitor<commit_after># -*- coding: utf-8 -*-

"""
Copyright (C) 2017 IBM Corporation

Licensed under the Apache License, Version 2.0 (the “License”);
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an “AS IS” BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

    Contributors:
        * Roberto Oliveira <rdutra@br.ibm.com>
        * Rafael Sene <rpsene@br.ibm.com>
        * Diego Fernandez-Merjildo <merjildo@br.ibm.com>
"""

from clang.cindex import CursorKind

from report_blocker import ReportBlocker

from problem_reporter import ProblemReporter

class Visitor(object):
    """ Class used to visit the translation unit nodes and run checkers """

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

    def visit_nodes(self, node):
        """ Visit all nodes from translation unit and for each node, call all
        activate checkers to seek for problems """
        if node.kind == CursorKind.MACRO_INSTANTIATION:
            ReportBlocker.check_node(node)

        if self.checker.check(node):
            ProblemReporter.report_problem(node,
                                           self.checker.get_problem_type(),
                                           self.checker.get_problem_msg())

        for node in node.get_children():
            self.visit_nodes(node)
<|endoftext|>


<commit_before>#!/usr/bin/env python

# Madeo MUMS Player
# Copyright 2011  Brendan Le Foll -  brendan@fridu.net
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2, as
# published by the Free Software Foundation.
#
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import sys, os

import gobject
gobject.threads_init()
import logging
import gst
import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop
import logging

UPLAYER_BUS_NAME = 'uk.co.madeo.uplayer'
UPLAYER_BUS_PATH = '/uk/co/madeo/uplayer'
LOG_FILENAME = '/tmp/uplayer.log'

logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG)

class GstPlayer:
    STOPPED = 0
    PLAYING = 1
    PAUSED = 2
    BUFFERING = 3
    PREROLLING = 4

    def __init__(self):
        self.status = self.STOPPED
        self.target_status = self.STOPPED

        self._dir = 1
        self._rate = 1.0

        self.c_video = 0
        self.c_audio = 0
        self.c_text = 0
        self.n_video = 0
        self.n_audio = 0
        self.n_text = 0

        self._videosink = None

        self.player = gst.element_factory_make('playbin2', None)

        bus = self.player.get_bus()
        bus.connect('message::eos', self.on_message_eos)
        bus.connect('message::error', self.on_message_error)
        bus.connect('message::state-changed', self.on_message_state_changed)
        bus.connect('message::async-done', self.on_message_async_done)
        bus.add_signal_watch()

#        bus.connect('message::buffering', self.on_message_buffering)
#        bus.connect('message::clock-lost', self.on_message_clock_lost)

    def on_message_async_done(self, bus, message):
        self.n_video = self.player.get_property('n-video')
        self.n_audio = self.player.get_property('n-audio')
        self.n_text = self.player.get_property('n-text')
        logging.debug ("%d video %d audio %d text" % (self.n_video, self.n_audio, self.n_text))
        if self.n_video > 0:
            self.player.set_property("current-video", self.c_video)
        if self.n_audio > 0:
            self.player.set_property("current-audio", self.c_audio)
        if self.n_text > 0:
            self.player.set_property("current-text", self.c_text)
        sink = self.player.get_property('video-sink')
        if sink is not None:
            factory = sink.get_factory()
            if "ismd_vidrend_bin" in factory.get_name():
                print "SMD video sink %s" % sink
                self._videosink = sink
            elif "autovideosink" in factory.get_name():
                print "Found Autovideosink"
                for child in sink.sinks():
                    factory = child.get_factory()
                    if "ismd_vidrend_bin" in factory.get_name():
                        print "SMD video sink %s" % child
                        self._videosink = child

        sink = self.player.get_property('audio-sink')
        if sink is not None:
            factory = sink.get_factory()
            if "ismd_audio_sink" in factory.get_name():
                print "SMD audio sink %s" % sink
            elif "autoaudiosink" in factory.get_name():
                print "Found Autoaudiosink"
                for child in sink.sinks():
                    factory = child.get_factory()
                    if "ismd_audio_sink" in factory.get_name():
                        print "SMD audio sink %s" % child

    def cleanup(self):
        current = self.player.get_state(0)[1]
        if current != gst.STATE_NULL:
            logging.debug ('do_cleanup')
            self.player.set_state(gst.STATE_READY)
            current = self.player.get_state(1000000000)[1]
            logging.debug ('changed state to %s' % current)
            self.player.set_state(gst.STATE_NULL)
            current = self.player.get_state(1000000000)[1]
            logging.debug ('changed state to %s' % current)

    def on_message_eos(self, bus, message):
        send_eos()
        self.playing = False
        self.stop()

    def set_location(self, location):
        if not gst.uri_is_valid(location):
            logging.debug ("Error: Invalid URI: %s\n" % location)
            return False
        self.player.set_property('uri', location)
        return True

    def on_message_error(self, bus, message):
        err, msg = message.parse_error()
        code = message.structure['gerror'].code
        self.stop()
        self.status = self.STOPPED
        self.target_status = self.status
        logging.debug ("Gstreamer %s:%s" % (err, msg))

    def on_message_state_changed(self, bus, message):
        if message.src != self.player:
            return

        old_state, new_state, pending = message.parse_state_changed()
        logging.debug ("old %s current %s pending %s status %s target status %s" % \
            (old_state, new_state, pending, self.status, self.target_status))
        if new_state == gst.STATE_PLAYING:
            if self.status != self.PLAYING:
                self.status = self.PLAYING
                self.playing = True

        elif new_state == gst.STATE_PAUSED:
            if self.status != self.BUFFERING:
                if self.target_status == self.PLAYING:
                    self.player.set_state(gst.STATE_PLAYING)
                else:
                    self.status = self.PAUSED
        elif new_state == gst.STATE_READY:
            if self._videosink is not None:
                del self._videosink
                self._videosink = None

    def toggle_direction(self):
        self._dir = -self._dir
        self.set_rate (abs(self._rate))

    def pause(self):
        self.target_status = self.PAUSED
        self.player.set_state(gst.STATE_PAUSED)
        current = self.player.get_state(0)[1]
        self.playing = False

    def play(self):
        self.target_status = self.PLAYING
        current = self.player.get_state(0)[1]
        if current == gst.STATE_PAUSED:
            self.player.set_state(gst.STATE_PLAYING)
        elif current != gst.STATE_PLAYING :
            self.player.set_state(gst.STATE_PAUSED)
            self.status = self.PREROLLING

    def stop(self):
        self.player.set_state(gst.STATE_READY)
        current = self.player.get_state(0)[1]
        if self.status != self.STOPPED:
            self.status = self.STOPPED
            self.target_status = self.status

    def get_state(self, timeout=1):
        return self.player.get_state(timeout=timeout)

    def is_playing(self):
        return self.playing

    def get_position(self):
        try:
            position, format = self.player.query_position(gst.FORMAT_TIME)
        except:
            position = gst.CLOCK_TIME_NONE

        return position

    def seek(self, location):
        """
        @param location: time to seek to, in nanoseconds
        """
        if self._rate < 0:
            res = self.player.seek (self._rate, gst.FORMAT_TIME,
                gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_KEY_UNIT,
                gst.SEEK_TYPE_SET, 0,
                gst.SEEK_TYPE_SET, location)
        else:
            res = self.player.seek (self._rate, gst.FORMAT_TIME,
                gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_KEY_UNIT,
                gst.SEEK_TYPE_SET, location,
                gst.SEEK_TYPE_SET, -1)

        if not res:
            logging.debug ("seek failed");

    def set_rate(self, rate):
        self.pause()

        self._rate = self._dir * rate
        try:
            position, format = self.player.query_position(gst.FORMAT_TIME)
        except:
            position = gst.CLOCK_TIME_NONE

        if self._rate < 0:
            res = self.player.seek(self._rate, gst.FORMAT_TIME,
                gst.SEEK_FLAG_FLUSH,
                gst.SEEK_TYPE_SET, 0,
                gst.SEEK_TYPE_SET, position)
        else:
            res = self.player.seek(self._rate, gst.FORMAT_TIME,
                gst.SEEK_FLAG_FLUSH,
                gst.SEEK_TYPE_SET, position,
                gst.SEEK_TYPE_SET, -1)

        if res:
            gst.info("rate set to %s" % rate)
        else:
            logging.debug ("failed to change video rate");
        self.play()

    def next_video_stream(self):
        if self.n_video > 0:
            current = (self.c_video + 1) % self.n_video
            if current != self.c_video:
                self.player.set_property("current-video", current)
                self.c_video = current

    def next_audio_stream(self):
        if self.n_audio > 0:
            current = (self.c_audio + 1) % self.n_audio
            if current != self.c_audio:
                self.player.set_property("current-audio", current)
                self.c_audio = current

    def next_text_stream(self):
        if self.n_text > 0:
            current = (self.c_text + 1) % self.n_text
            if current != self.c_text:
                self.player.set_property("current-text", current)
                self.c_text = current

    def set_gdl_plane(self, plane):
        if plane > 0 and plane < 7:
            self._videosink.set_property('gdl-plane', plane)
            return True
        return False

    def set_user_agent(self, user_agent):
        source = self.player.get_property('source')
        try:
            source.set_property("user-agent", user_agent)
        except:
            logging.debug ("failed to set user-agent to %s" % user_agent)
            pass

    def set_rectangle_size(self, x, y, w, h):
        # check we are using ismd sink
        if self._videosink is not None:
            logging.debug ("rectangle size changed to %s %d %d %d %d" % (self._videosink, x, y, w, h))
            self._videosink.set_property ("rectangle", "%d,%d,%d,%d" % (x, y, w, h))
            return True
        return False

class uplayerDBUSService(dbus.service.Object):
    def __init__(self):
        bus_name = dbus.service.BusName(UPLAYER_BUS_NAME, bus=dbus.SessionBus())
        dbus.service.Object.__init__(self, bus_name, UPLAYER_BUS_PATH)
        self.player = GstPlayer()

    @dbus.service.signal(UPLAYER_BUS_NAME)
    def emitEOSSignal(self):
        logging.debug ("EOS signal sent")
        return

    @dbus.service.method(UPLAYER_BUS_NAME,
                         in_signature='s', out_signature='b')
    def set_uri(self, uri):
        return self.player.set_location(uri);

    @dbus.service.method(UPLAYER_BUS_NAME)
    def play(self):
        self.player.play();

    @dbus.service.method(UPLAYER_BUS_NAME)
    def pause(self):
        self.player.pause();

    @dbus.service.method(UPLAYER_BUS_NAME)
    def stop(self):
        self.player.stop();

    @dbus.service.method(UPLAYER_BUS_NAME,
                         in_signature='', out_signature='t')
    def get_position(self):
        return self.player.get_position()

    @dbus.service.method(UPLAYER_BUS_NAME,
                         in_signature='i', out_signature='')
    def seek(self, position):
        self.player.seek(position)

    @dbus.service.method(UPLAYER_BUS_NAME,
                         in_signature='i', out_signature='')
    def set_rate(self, rate):
        self.player.set_rate(rate)

    @dbus.service.method(UPLAYER_BUS_NAME,
                         in_signature='s', out_signature='b')
    def set_user_agent(self, user_agent):
        return self.player.set_user_agent(user_agent)

    @dbus.service.method(UPLAYER_BUS_NAME,
                        in_signature='iiii', out_signature='')
    def set_rectangle_size(self, x, y, w, h):
        self.player.set_rectangle_size(x,y,w,h)

    @dbus.service.method(UPLAYER_BUS_NAME,
                         in_signature='i', out_signature='b')
    def set_gdl_plane(self, gdl_plane):
        return self.player.set_gdl_plane (gdl_plane)

DBusGMainLoop(set_as_default=True)
uplayerService = uplayerDBUSService()
player = GstPlayer()

def send_eos ():
    uplayerService.emitEOSSignal()

logging.debug ("Starting uplayer...")
loop = gobject.MainLoop()
loop.run()
<commit_msg>removed print and debug cleanup<commit_after>#!/usr/bin/env python

# Madeo MUMS Player
# Copyright 2011  Brendan Le Foll -  brendan@fridu.net
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2, as
# published by the Free Software Foundation.
#
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import sys, os

import gobject
gobject.threads_init()
import logging
import gst
import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop
import logging

UPLAYER_BUS_NAME = 'uk.co.madeo.uplayer'
UPLAYER_BUS_PATH = '/uk/co/madeo/uplayer'
LOG_FILENAME = '/tmp/uplayer.log'

logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG)

class GstPlayer:
    STOPPED = 0
    PLAYING = 1
    PAUSED = 2
    BUFFERING = 3
    PREROLLING = 4

    def __init__(self):
        self.status = self.STOPPED
        self.target_status = self.STOPPED

        self._dir = 1
        self._rate = 1.0

        self.c_video = 0
        self.c_audio = 0
        self.c_text = 0
        self.n_video = 0
        self.n_audio = 0
        self.n_text = 0

        self._videosink = None

        self.player = gst.element_factory_make('playbin2', None)

        bus = self.player.get_bus()
        bus.connect('message::eos', self.on_message_eos)
        bus.connect('message::error', self.on_message_error)
        bus.connect('message::state-changed', self.on_message_state_changed)
        bus.connect('message::async-done', self.on_message_async_done)
        bus.add_signal_watch()

    def on_message_async_done(self, bus, message):
        self.n_video = self.player.get_property('n-video')
        self.n_audio = self.player.get_property('n-audio')
        self.n_text = self.player.get_property('n-text')
        logging.debug ("%d video %d audio %d text" % (self.n_video, self.n_audio, self.n_text))
        if self.n_video > 0:
            self.player.set_property("current-video", self.c_video)
        if self.n_audio > 0:
            self.player.set_property("current-audio", self.c_audio)
        if self.n_text > 0:
            self.player.set_property("current-text", self.c_text)
        sink = self.player.get_property('video-sink')
        if sink is not None:
            factory = sink.get_factory()
            if "ismd_vidrend_bin" in factory.get_name():
                logging.debug("using SMD video sink %s" % sink)
                self._videosink = sink
            elif "autovideosink" in factory.get_name():
                logging.debug("using Autovideosink")
                for child in sink.sinks():
                    factory = child.get_factory()
                    if "ismd_vidrend_bin" in factory.get_name():
                        logging.debug("SMD video sink %s" % child)
                        self._videosink = child

        sink = self.player.get_property('audio-sink')
        if sink is not None:
            factory = sink.get_factory()
            if "ismd_audio_sink" in factory.get_name():
                logging.debug("Using SMD audio sink %s" % sink)
            elif "autoaudiosink" in factory.get_name():
                logging.debug("Using Autoaudiosink")
                for child in sink.sinks():
                    factory = child.get_factory()
                    if "ismd_audio_sink" in factory.get_name():
                        logging.debug("SMD audio sink %s" % child)

    def cleanup(self):
        current = self.player.get_state(0)[1]
        if current != gst.STATE_NULL:
            logging.debug ('do_cleanup')
            self.player.set_state(gst.STATE_READY)
            current = self.player.get_state(1000000000)[1]
            logging.debug ('changed state to %s' % current)
            self.player.set_state(gst.STATE_NULL)
            current = self.player.get_state(1000000000)[1]
            logging.debug ('changed state to %s' % current)

    def on_message_eos(self, bus, message):
        send_eos()
        self.playing = False
        self.stop()

    def set_location(self, location):
        if not gst.uri_is_valid(location):
            logging.debug ("Error: Invalid URI: %s\n" % location)
            return False
        self.player.set_property('uri', location)
        return True

    def on_message_error(self, bus, message):
        err, msg = message.parse_error()
        code = message.structure['gerror'].code
        self.stop()
        self.status = self.STOPPED
        self.target_status = self.status
        logging.debug ("Gstreamer %s:%s" % (err, msg))

    def on_message_state_changed(self, bus, message):
        if message.src != self.player:
            return

        old_state, new_state, pending = message.parse_state_changed()
        logging.debug ("old %s current %s pending %s status %s target status %s" % \
            (old_state, new_state, pending, self.status, self.target_status))
        if new_state == gst.STATE_PLAYING:
            if self.status != self.PLAYING:
                self.status = self.PLAYING
                self.playing = True

        elif new_state == gst.STATE_PAUSED:
            if self.status != self.BUFFERING:
                if self.target_status == self.PLAYING:
                    self.player.set_state(gst.STATE_PLAYING)
                else:
                    self.status = self.PAUSED
        elif new_state == gst.STATE_READY:
            if self._videosink is not None:
                del self._videosink
                self._videosink = None

    def toggle_direction(self):
        self._dir = -self._dir
        self.set_rate (abs(self._rate))

    def pause(self):
        self.target_status = self.PAUSED
        self.player.set_state(gst.STATE_PAUSED)
        current = self.player.get_state(0)[1]
        self.playing = False

    def play(self):
        self.target_status = self.PLAYING
        current = self.player.get_state(0)[1]
        if current == gst.STATE_PAUSED:
            self.player.set_state(gst.STATE_PLAYING)
        elif current != gst.STATE_PLAYING :
            self.player.set_state(gst.STATE_PAUSED)
            self.status = self.PREROLLING

    def stop(self):
        self.player.set_state(gst.STATE_READY)
        current = self.player.get_state(0)[1]
        if self.status != self.STOPPED:
            self.status = self.STOPPED
            self.target_status = self.status

    def get_state(self, timeout=1):
        return self.player.get_state(timeout=timeout)

    def is_playing(self):
        return self.playing

    def get_position(self):
        try:
            position, format = self.player.query_position(gst.FORMAT_TIME)
        except:
            position = gst.CLOCK_TIME_NONE

        return position

    def seek(self, location):
        """
        @param location: time to seek to, in nanoseconds
        """
        if self._rate < 0:
            res = self.player.seek (self._rate, gst.FORMAT_TIME,
                gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_KEY_UNIT,
                gst.SEEK_TYPE_SET, 0,
                gst.SEEK_TYPE_SET, location)
        else:
            res = self.player.seek (self._rate, gst.FORMAT_TIME,
                gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_KEY_UNIT,
                gst.SEEK_TYPE_SET, location,
                gst.SEEK_TYPE_SET, -1)

        if not res:
            logging.debug ("seek failed");

    def set_rate(self, rate):
        self.pause()

        self._rate = self._dir * rate
        try:
            position, format = self.player.query_position(gst.FORMAT_TIME)
        except:
            position = gst.CLOCK_TIME_NONE

        if self._rate < 0:
            res = self.player.seek(self._rate, gst.FORMAT_TIME,
                gst.SEEK_FLAG_FLUSH,
                gst.SEEK_TYPE_SET, 0,
                gst.SEEK_TYPE_SET, position)
        else:
            res = self.player.seek(self._rate, gst.FORMAT_TIME,
                gst.SEEK_FLAG_FLUSH,
                gst.SEEK_TYPE_SET, position,
                gst.SEEK_TYPE_SET, -1)

        if res:
            gst.info("rate set to %s" % rate)
        else:
            logging.debug ("failed to change video rate");
        self.play()

    def next_video_stream(self):
        if self.n_video > 0:
            current = (self.c_video + 1) % self.n_video
            if current != self.c_video:
                self.player.set_property("current-video", current)
                self.c_video = current

    def next_audio_stream(self):
        if self.n_audio > 0:
            current = (self.c_audio + 1) % self.n_audio
            if current != self.c_audio:
                self.player.set_property("current-audio", current)
                self.c_audio = current

    def next_text_stream(self):
        if self.n_text > 0:
            current = (self.c_text + 1) % self.n_text
            if current != self.c_text:
                self.player.set_property("current-text", current)
                self.c_text = current

    def set_gdl_plane(self, plane):
        if plane > 0 and plane < 7:
            self._videosink.set_property('gdl-plane', plane)
            return True
        return False

    def set_user_agent(self, user_agent):
        source = self.player.get_property('source')
        try:
            source.set_property("user-agent", user_agent)
        except:
            logging.debug ("failed to set user-agent to %s" % user_agent)
            pass

    def set_rectangle_size(self, x, y, w, h):
        # check we are using ismd sink
        if self._videosink is not None:
            logging.debug ("rectangle size changed to %s %d %d %d %d" % (self._videosink, x, y, w, h))
            self._videosink.set_property ("rectangle", "%d,%d,%d,%d" % (x, y, w, h))
            return True
        return False

class uplayerDBUSService(dbus.service.Object):
    def __init__(self):
        bus_name = dbus.service.BusName(UPLAYER_BUS_NAME, bus=dbus.SessionBus())
        dbus.service.Object.__init__(self, bus_name, UPLAYER_BUS_PATH)
        self.player = GstPlayer()

    @dbus.service.signal(UPLAYER_BUS_NAME)
    def emitEOSSignal(self):
        logging.debug ("EOS signal sent")
        return

    @dbus.service.method(UPLAYER_BUS_NAME,
                         in_signature='s', out_signature='b')
    def set_uri(self, uri):
        return self.player.set_location(uri);

    @dbus.service.method(UPLAYER_BUS_NAME)
    def play(self):
        self.player.play();

    @dbus.service.method(UPLAYER_BUS_NAME)
    def pause(self):
        self.player.pause();

    @dbus.service.method(UPLAYER_BUS_NAME)
    def stop(self):
        self.player.stop();

    @dbus.service.method(UPLAYER_BUS_NAME,
                         in_signature='', out_signature='t')
    def get_position(self):
        return self.player.get_position()

    @dbus.service.method(UPLAYER_BUS_NAME,
                         in_signature='i', out_signature='')
    def seek(self, position):
        self.player.seek(position)

    @dbus.service.method(UPLAYER_BUS_NAME,
                         in_signature='i', out_signature='')
    def set_rate(self, rate):
        self.player.set_rate(rate)

    @dbus.service.method(UPLAYER_BUS_NAME,
                         in_signature='s', out_signature='b')
    def set_user_agent(self, user_agent):
        return self.player.set_user_agent(user_agent)

    @dbus.service.method(UPLAYER_BUS_NAME,
                        in_signature='iiii', out_signature='')
    def set_rectangle_size(self, x, y, w, h):
        self.player.set_rectangle_size(x,y,w,h)

    @dbus.service.method(UPLAYER_BUS_NAME,
                         in_signature='i', out_signature='b')
    def set_gdl_plane(self, gdl_plane):
        return self.player.set_gdl_plane (gdl_plane)

DBusGMainLoop(set_as_default=True)
uplayerService = uplayerDBUSService()
player = GstPlayer()

def send_eos ():
    uplayerService.emitEOSSignal()

logging.debug ("Starting uplayer...")
loop = gobject.MainLoop()
loop.run()
<|endoftext|>