<commit_before># Copyright (C) 2007, Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

import gtk
import gobject
import hippo

from sugar.graphics.toolbutton import ToolButton
from sugar.graphics import style

class Toolbox(gtk.VBox):
    __gtype_name__ = 'SugarToolbox'

    __gsignals__ = {
        'current-toolbar-changed': (gobject.SIGNAL_RUN_FIRST,
                                    gobject.TYPE_NONE,
                                    ([int]))
    }

    def __init__(self):
        gtk.VBox.__init__(self)

        self._notebook = gtk.Notebook()
        self._notebook.set_tab_pos(gtk.POS_BOTTOM)
        self._notebook.set_show_border(False)
        self._notebook.set_show_tabs(False)
        self._notebook.props.tab_vborder = style.TOOLBOX_TAB_VBORDER
        self._notebook.props.tab_hborder = style.TOOLBOX_TAB_HBORDER
        self.pack_start(self._notebook)
        self._notebook.show()

        # FIXME improve gtk.Notebook and do this in the theme
        self._separator = hippo.Canvas()
        box = hippo.CanvasBox(
                    border_color=style.COLOR_BUTTON_GREY.get_int(),
                    background_color=style.COLOR_PANEL_GREY.get_int(),
                    box_height=style.TOOLBOX_SEPARATOR_HEIGHT,
                    border_bottom=style.LINE_WIDTH)
        self._separator.set_root(box)
        self.pack_start(self._separator, False)

        self._notebook.connect('notify::page', self._notify_page_cb)

    def _notify_page_cb(self, notebook, pspec):
        self.emit('current-toolbar-changed', notebook.props.page)

    def add_toolbar(self, name, toolbar):
        label = gtk.Label(name)
        label.set_size_request(style.TOOLBOX_TAB_LABEL_WIDTH, -1)
        label.set_alignment(0.0, 0.5)

        event_box = gtk.EventBox()

        alignment = gtk.Alignment(0.0, 0.0, 1.0, 1.0)
        alignment.set_padding(0, 0, style.TOOLBOX_HORIZONTAL_PADDING,
                              style.TOOLBOX_HORIZONTAL_PADDING)

        alignment.add(toolbar)
        event_box.add(alignment)
        alignment.show()
        event_box.show()

        self._notebook.append_page(event_box, label)

        if self._notebook.get_n_pages() > 1:
            self._notebook.set_show_tabs(True)
            self._separator.show()

    def remove_toolbar(self, index):
        self._notebook.remove_page(index)

        if self._notebook.get_n_pages() < 2:
            self._notebook.set_show_tabs(False)
            self._separator.hide()

    def set_current_toolbar(self, index):
        self._notebook.set_current_page(index)
<commit_msg>Add getter for the current toolbar in Toolbox.<commit_after># Copyright (C) 2007, Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

import gtk
import gobject
import hippo

from sugar.graphics.toolbutton import ToolButton
from sugar.graphics import style

class Toolbox(gtk.VBox):
    __gtype_name__ = 'SugarToolbox'

    __gsignals__ = {
        'current-toolbar-changed': (gobject.SIGNAL_RUN_FIRST,
                                    gobject.TYPE_NONE,
                                    ([int]))
    }

    def __init__(self):
        gtk.VBox.__init__(self)

        self._notebook = gtk.Notebook()
        self._notebook.set_tab_pos(gtk.POS_BOTTOM)
        self._notebook.set_show_border(False)
        self._notebook.set_show_tabs(False)
        self._notebook.props.tab_vborder = style.TOOLBOX_TAB_VBORDER
        self._notebook.props.tab_hborder = style.TOOLBOX_TAB_HBORDER
        self.pack_start(self._notebook)
        self._notebook.show()

        # FIXME improve gtk.Notebook and do this in the theme
        self._separator = hippo.Canvas()
        box = hippo.CanvasBox(
                    border_color=style.COLOR_BUTTON_GREY.get_int(),
                    background_color=style.COLOR_PANEL_GREY.get_int(),
                    box_height=style.TOOLBOX_SEPARATOR_HEIGHT,
                    border_bottom=style.LINE_WIDTH)
        self._separator.set_root(box)
        self.pack_start(self._separator, False)

        self._notebook.connect('notify::page', self._notify_page_cb)

    def _notify_page_cb(self, notebook, pspec):
        self.emit('current-toolbar-changed', notebook.props.page)

    def add_toolbar(self, name, toolbar):
        label = gtk.Label(name)
        label.set_size_request(style.TOOLBOX_TAB_LABEL_WIDTH, -1)
        label.set_alignment(0.0, 0.5)

        event_box = gtk.EventBox()

        alignment = gtk.Alignment(0.0, 0.0, 1.0, 1.0)
        alignment.set_padding(0, 0, style.TOOLBOX_HORIZONTAL_PADDING,
                              style.TOOLBOX_HORIZONTAL_PADDING)

        alignment.add(toolbar)
        event_box.add(alignment)
        alignment.show()
        event_box.show()

        self._notebook.append_page(event_box, label)

        if self._notebook.get_n_pages() > 1:
            self._notebook.set_show_tabs(True)
            self._separator.show()

    def remove_toolbar(self, index):
        self._notebook.remove_page(index)

        if self._notebook.get_n_pages() < 2:
            self._notebook.set_show_tabs(False)
            self._separator.hide()

    def set_current_toolbar(self, index):
        self._notebook.set_current_page(index)

    def get_current_toolbar(self):
        return self._notebook.get_current_page()

    current_toolbar = property(get_current_toolbar, set_current_toolbar)

<|endoftext|>


<commit_before>#!/usr/bin/env python3
#
# Copyright 2016 Red Hat, Inc.
#
# Authors:
#     Fam Zheng <famz@redhat.com>
#
# This work is licensed under the MIT License.  Please see the LICENSE file or
# http://opensource.org/licenses/MIT.

from django.conf.urls import url
from django.http import HttpResponse, HttpResponseForbidden, Http404, \
                        HttpResponseRedirect
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.template import Template, Context
from mod import PatchewModule
import time
import smtplib
import email
import traceback
import math
from api.views import APILoginRequiredView
from api.models import Message, Project
from api.search import SearchEngine
from event import emit_event, declare_event
from schema import *

_instance = None

TESTING_SCRIPT_DEFAULT = """#!/bin/bash
# Testing script will be invoked under the git checkout with
# HEAD pointing to a commit that has the patches applied on top of "base"
# branch
exit 0
"""

class TestingModule(PatchewModule):
    """Testing module"""

    name = "testing"

    test_schema = \
        ArraySchema("{name}", "Test", desc="Test spec",
                    members=[
                        BooleanSchema("enabled", "Enabled",
                                      desc="Whether this test is enabled",
                                      default=True),
                        StringSchema("users", "Users",
                                     desc="List of allowed users to run this test"),
                        StringSchema("testers", "Testers",
                                     desc="List of allowed testers to run this test"),
                        StringSchema("requirements", "Requirements",
                                     desc="List of requirements of the test"),
                        IntegerSchema("timeout", "Timeout",
                                      default=3600,
                                      desc="Timeout for the test"),
                        StringSchema("script", "Test script",
                                     desc="The testing script",
                                     default=TESTING_SCRIPT_DEFAULT,
                                     multiline=True,
                                     required=True),
                    ])

    requirement_schema = \
        ArraySchema("{name}", "Requirement", desc="Test requirement spec",
                    members=[
                        StringSchema("script", "Probe script",
                                     desc="The probing script for this requirement",
                                     default="#!/bin/bash\ntrue",
                                     multiline=True,
                                     required=True),
                    ])

    project_property_schema = \
        ArraySchema("testing", desc="Configuration for testing module",
                    members=[
                        MapSchema("tests", "Tests",
                                   desc="Testing specs",
                                   item=test_schema),
                        MapSchema("requirements", "Requirements",
                                   desc="Requirement specs",
                                   item=requirement_schema),
                   ])

    def __init__(self):
        global _instance
        assert _instance == None
        _instance = self
        declare_event("TestingReport",
                      user="the user's name that runs this tester",
                      tester="the name of the tester",
                      obj="the object (series or project) which the test is for",
                      passed="True if the test is passed",
                      test="test name",
                      log="test log")

    def remove_testing_properties(self, obj):
        for k in list(obj.get_properties().keys()):
            if k == "testing.started" or \
               k == "testing.start-time" or \
               k == "testing.failed" or \
               k == "testing.done" or \
               k == "testing.tested-head" or \
               k.startswith("testing.report.") or \
               k.startswith("testing.log."):
                obj.set_property(k, None)

    def www_view_testing_reset(self, request, project_or_series):
        if not request.user.is_authenticated():
            return HttpResponseForbidden()
        if request.GET.get("type") == "project":
            obj = Project.objects.filter(name=project_or_series).first()
            if not obj.maintained_by(request.user):
                raise PermissionDenied()
        else:
            obj = Message.objects.find_series(project_or_series)
        if not obj:
            raise Http404("Not found: " + project_or_series)
        self.remove_testing_properties(obj)
        return HttpResponseRedirect(request.META.get('HTTP_REFERER'))

    def www_url_hook(self, urlpatterns):
        urlpatterns.append(url(r"^testing-reset/(?P<project_or_series>.*)/",
                               self.www_view_testing_reset,
                               name="testing-reset"))

    def add_test_report(self, user, project, tester, test, head, base, identity, passed, log):
        # Find a project or series depending on the test type and assign it to obj
        if identity["type"] == "project":
            obj = Project.objects.get(name=project)
            is_proj_report = True
            project = obj.name
        elif identity["type"] == "series":
            message_id = identity["message-id"]
            obj = Message.objects.find_series(message_id, project)
            if not obj:
                raise Exception("Series doesn't exist")
            is_proj_report = False
            project = obj.project.name
        obj.set_property("testing.report." + test,
                         {"passed": passed,
                          "user": user.username,
                          "tester": tester or user.username,
                         })
        obj.set_property("testing.log." + test, log)
        if not passed:
            obj.set_property("testing.failed", True)
        reports = [x for x in obj.get_properties() if x.startswith("testing.report.")]
        done_tests = set([x[len("testing.report."):] for x in reports])
        all_tests = set([k for k, v in self.get_tests(obj).items() if v["enabled"]])
        if all_tests.issubset(done_tests):
            obj.set_property("testing.done", True)
        if all_tests.issubset(done_tests):
            obj.set_property("testing.tested-head", head)
        emit_event("TestingReport", tester=tester, user=user.username,
                    obj=obj, passed=passed, test=test, log=log)

    def get_tests(self, obj):
        ret = {}
        for k, v in obj.get_properties().items():
            if not k.startswith("testing.tests."):
                continue
            tn = k[len("testing.tests."):]
            if "." not in tn:
                continue
            an = tn[tn.find(".") + 1:]
            tn = tn[:tn.find(".")]
            ret.setdefault(tn, {})
            ret[tn][an] = v
            ret[tn]["name"] = tn
        return ret

    def prepare_testing_report(self, obj):
        for pn, p in obj.get_properties().items():
            if not pn.startswith("testing.report."):
                continue
            tn = pn[len("testing.report."):]
            log = obj.get_property("testing.log." + tn)
            failed = not p["passed"]
            passed_str = "failed" if failed else "passed"
            obj.extra_info.append({"title": "Test %s: %s" % (passed_str, tn),
                                  "class": 'danger' if failed else 'success',
                                  "content": '<pre>%s</pre>' % log})

    def prepare_message_hook(self, request, message):
        if not message.is_series_head:
            return
        self.prepare_testing_report(message)

        if message.project.maintained_by(request.user) \
                and message.get_property("testing.started"):
            url = reverse("testing-reset",
                          kwargs={"project_or_series": message.message_id})
            url += "?type=message"
            message.extra_ops.append({"url": url,
                                      "title": "Reset testing states",
                                     })

        if message.get_property("testing.failed"):
            message.status_tags.append({
                "title": "Testing failed",
                "url": reverse("series_detail",
                                kwargs={"project": message.project.name,
                                        "message_id":message.message_id}),
                "type": "danger",
                "char": "T",
                })
        elif message.get_property("testing.done"):
            message.status_tags.append({
                "title": "Testing passed",
                "url": reverse("series_detail",
                                kwargs={"project": message.project.name,
                                        "message_id":message.message_id}),
                "type": "success",
                "char": "T",
                })

    def _testers_info(self, project):
        at = []
        for k, v in project.get_properties().items():
            prefix = "testing.check_in."
            if not k.startswith(prefix):
                continue
            age = time.time() - v
            if age > 10 * 60:
                continue
            tn = k[len(prefix):]
            at.append("%s (%dmin)" % (tn, math.ceil(age / 60)))
        if not at:
            return
        return "Active testers: " + ", ".join(at)

    def prepare_project_hook(self, request, project):
        if not project.maintained_by(request.user):
            return
        project.extra_info.append({"title": "Testing configuration",
                                   "class": "info",
                                   "content": self.build_config_html(request,
                                                                     project)})
        ti = self._testers_info(project)
        if ti:
            project.extra_headers.append(ti)
        self.prepare_testing_report(project)

        if project.maintained_by(request.user) \
                and project.get_property("testing.started"):
            url = reverse("testing-reset",
                          kwargs={"project_or_series": project.name})
            url += "?type=project"
            project.extra_ops.append({"url": url,
                                      "title": "Reset testing states"})

    def get_capability_probes(self, project):
        ret = {}
        for k, v in project.get_properties().items():
            prefix = "testing.requirements."
            if not k.startswith(prefix):
                continue
            name = k[len(prefix):]
            name = name[:name.find(".")]
            ret[name] = v
        return ret

    def tester_check_in(self, project, tester):
        assert project
        assert tester
        po = Project.objects.filter(name=project).first()
        if not po:
            return
        po.set_property('testing.check_in.' + tester, time.time())

class TestingGetView(APILoginRequiredView):
    name = "testing-get"
    allowed_groups = ["testers"]

    def _generate_test_data(self, project, repo, head, base, identity, test):
        r = {"project": project,
             "repo": repo,
             "head": head,
             "base": base,
             "test": test,
             "identity": identity
             }
        return r

    def _generate_series_test_data(self, s, test):
        return self._generate_test_data(project=s.project.name,
                                        repo=s.get_property("git.repo"),
                                        head=s.get_property("git.tag"),
                                        base=s.get_property("git.base"),
                                        identity={
                                            "type": "series",
                                            "message-id": s.message_id,
                                            "subject": s.subject,
                                        },
                                        test=test)

    def _generate_project_test_data(self, project, repo, head, base, test):
        return self._generate_test_data(project=project,
                                        repo=repo, head=head, base=base,
                                        identity={
                                            "type": "project",
                                            "head": head,
                                        },
                                        test=test)

    def _find_applicable_test(self, user, project, tester, capabilities, obj):
        all_tests = set([k for k, v in _instance.get_tests(obj).items() if v["enabled"]])
        done_tests = set()
        for tn, t in _instance.get_tests(project).items():
            if not t.get("enabled"):
                continue
            all_tests.add(tn)
            if obj.get_property("testing.report." + tn):
                done_tests.add(tn)
                continue
            if "tester" in t and tester != t["tester"]:
                continue
            if "user" in t and user.username != t["user"]:
                continue
            # TODO: group?
            ok = True
            reqs = t.get("requirements", "")
            for r in [x.strip() for x in reqs.split(",")]:
                if r not in capabilities:
                    ok = False
                    break
            if not ok:
                continue
            return t
        if len(all_tests) and all_tests.issubset(done_tests):
            obj.set_property("testing.done", True)

    def _find_project_test(self, request, po, tester, capabilities):
        head = po.get_property("git.head")
        repo = po.git
        tested = po.get_property("testing.tested-head")
        if not head or not repo:
            return
        test = self._find_applicable_test(request.user, po,
                                          tester, capabilities, po)
        if not test:
            return
        td = self._generate_project_test_data(po.name, repo, head, tested, test)
        return po, td

    def _find_series_test(self, request, po, tester, capabilities):
        se = SearchEngine()
        q = se.search_series("is:applied", "not:old", "not:tested",
                             "project:" + po.name)
        candidate = None
        for s in q:
            test = self._find_applicable_test(request.user, po,
                                              tester, capabilities, s)
            if not test:
                continue
            if not s.get_property("testing.started"):
                candidate = s, test
                break
            # Pick one series that started test the earliest
            if not candidate or \
                    s.get_property("testing.start-time") < \
                    candidate[0].get_property("testing.start-time"):
                candidate = s, test
        if not candidate:
            return None
        return candidate[0], \
               self._generate_series_test_data(candidate[0], candidate[1])

    def handle(self, request, project, tester, capabilities):
        # Try project head test first
        _instance.tester_check_in(project, tester or request.user.username)
        po = Project.objects.get(name=project)
        candidate = self._find_project_test(request, po, tester, capabilities)
        if not candidate:
            candidate = self._find_series_test(request, po, tester, capabilities)
        if not candidate:
            return
        obj, test_data = candidate
        obj.set_property("testing.started", True)
        obj.set_property("testing.start-time", time.time())
        return test_data

class TestingReportView(APILoginRequiredView):
    name = "testing-report"
    allowed_groups = ["testers"]

    def handle(self, request, tester, project, test, head, base, passed, log, identity):
        _instance.tester_check_in(project, tester or request.user.username)
        _instance.add_test_report(request.user, project, tester,
                                  test, head, base, identity, passed, log)

class TestingCapabilitiesView(APILoginRequiredView):
    name = "testing-capabilities"
    allowed_groups = ["testers"]

    def handle(self, request, tester, project):
        _instance.tester_check_in(project, tester or request.user.username)
        po = Project.objects.filter(name=project).first()
        if not po:
            raise Http404("Project '%s' not found" % project)
        probes = _instance.get_capability_probes(po)
        return probes

class UntestView(APILoginRequiredView):
    name = "untest"
    allowed_groups = ["testers"]

    def handle(self, request, terms):
        se = SearchEngine()
        q = se.search_series(*terms)
        for s in q:
            _instance.remove_testing_properties(s)
<commit_msg>testing: Fix capability filtering<commit_after>#!/usr/bin/env python3
#
# Copyright 2016 Red Hat, Inc.
#
# Authors:
#     Fam Zheng <famz@redhat.com>
#
# This work is licensed under the MIT License.  Please see the LICENSE file or
# http://opensource.org/licenses/MIT.

from django.conf.urls import url
from django.http import HttpResponse, HttpResponseForbidden, Http404, \
                        HttpResponseRedirect
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.template import Template, Context
from mod import PatchewModule
import time
import smtplib
import email
import traceback
import math
from api.views import APILoginRequiredView
from api.models import Message, Project
from api.search import SearchEngine
from event import emit_event, declare_event
from schema import *

_instance = None

TESTING_SCRIPT_DEFAULT = """#!/bin/bash
# Testing script will be invoked under the git checkout with
# HEAD pointing to a commit that has the patches applied on top of "base"
# branch
exit 0
"""

class TestingModule(PatchewModule):
    """Testing module"""

    name = "testing"

    test_schema = \
        ArraySchema("{name}", "Test", desc="Test spec",
                    members=[
                        BooleanSchema("enabled", "Enabled",
                                      desc="Whether this test is enabled",
                                      default=True),
                        StringSchema("users", "Users",
                                     desc="List of allowed users to run this test"),
                        StringSchema("testers", "Testers",
                                     desc="List of allowed testers to run this test"),
                        StringSchema("requirements", "Requirements",
                                     desc="List of requirements of the test"),
                        IntegerSchema("timeout", "Timeout",
                                      default=3600,
                                      desc="Timeout for the test"),
                        StringSchema("script", "Test script",
                                     desc="The testing script",
                                     default=TESTING_SCRIPT_DEFAULT,
                                     multiline=True,
                                     required=True),
                    ])

    requirement_schema = \
        ArraySchema("{name}", "Requirement", desc="Test requirement spec",
                    members=[
                        StringSchema("script", "Probe script",
                                     desc="The probing script for this requirement",
                                     default="#!/bin/bash\ntrue",
                                     multiline=True,
                                     required=True),
                    ])

    project_property_schema = \
        ArraySchema("testing", desc="Configuration for testing module",
                    members=[
                        MapSchema("tests", "Tests",
                                   desc="Testing specs",
                                   item=test_schema),
                        MapSchema("requirements", "Requirements",
                                   desc="Requirement specs",
                                   item=requirement_schema),
                   ])

    def __init__(self):
        global _instance
        assert _instance == None
        _instance = self
        declare_event("TestingReport",
                      user="the user's name that runs this tester",
                      tester="the name of the tester",
                      obj="the object (series or project) which the test is for",
                      passed="True if the test is passed",
                      test="test name",
                      log="test log")

    def remove_testing_properties(self, obj):
        for k in list(obj.get_properties().keys()):
            if k == "testing.started" or \
               k == "testing.start-time" or \
               k == "testing.failed" or \
               k == "testing.done" or \
               k == "testing.tested-head" or \
               k.startswith("testing.report.") or \
               k.startswith("testing.log."):
                obj.set_property(k, None)

    def www_view_testing_reset(self, request, project_or_series):
        if not request.user.is_authenticated():
            return HttpResponseForbidden()
        if request.GET.get("type") == "project":
            obj = Project.objects.filter(name=project_or_series).first()
            if not obj.maintained_by(request.user):
                raise PermissionDenied()
        else:
            obj = Message.objects.find_series(project_or_series)
        if not obj:
            raise Http404("Not found: " + project_or_series)
        self.remove_testing_properties(obj)
        return HttpResponseRedirect(request.META.get('HTTP_REFERER'))

    def www_url_hook(self, urlpatterns):
        urlpatterns.append(url(r"^testing-reset/(?P<project_or_series>.*)/",
                               self.www_view_testing_reset,
                               name="testing-reset"))

    def add_test_report(self, user, project, tester, test, head, base, identity, passed, log):
        # Find a project or series depending on the test type and assign it to obj
        if identity["type"] == "project":
            obj = Project.objects.get(name=project)
            is_proj_report = True
            project = obj.name
        elif identity["type"] == "series":
            message_id = identity["message-id"]
            obj = Message.objects.find_series(message_id, project)
            if not obj:
                raise Exception("Series doesn't exist")
            is_proj_report = False
            project = obj.project.name
        obj.set_property("testing.report." + test,
                         {"passed": passed,
                          "user": user.username,
                          "tester": tester or user.username,
                         })
        obj.set_property("testing.log." + test, log)
        if not passed:
            obj.set_property("testing.failed", True)
        reports = [x for x in obj.get_properties() if x.startswith("testing.report.")]
        done_tests = set([x[len("testing.report."):] for x in reports])
        all_tests = set([k for k, v in self.get_tests(obj).items() if v["enabled"]])
        if all_tests.issubset(done_tests):
            obj.set_property("testing.done", True)
        if all_tests.issubset(done_tests):
            obj.set_property("testing.tested-head", head)
        emit_event("TestingReport", tester=tester, user=user.username,
                    obj=obj, passed=passed, test=test, log=log)

    def get_tests(self, obj):
        ret = {}
        for k, v in obj.get_properties().items():
            if not k.startswith("testing.tests."):
                continue
            tn = k[len("testing.tests."):]
            if "." not in tn:
                continue
            an = tn[tn.find(".") + 1:]
            tn = tn[:tn.find(".")]
            ret.setdefault(tn, {})
            ret[tn][an] = v
            ret[tn]["name"] = tn
        return ret

    def prepare_testing_report(self, obj):
        for pn, p in obj.get_properties().items():
            if not pn.startswith("testing.report."):
                continue
            tn = pn[len("testing.report."):]
            log = obj.get_property("testing.log." + tn)
            failed = not p["passed"]
            passed_str = "failed" if failed else "passed"
            obj.extra_info.append({"title": "Test %s: %s" % (passed_str, tn),
                                  "class": 'danger' if failed else 'success',
                                  "content": '<pre>%s</pre>' % log})

    def prepare_message_hook(self, request, message):
        if not message.is_series_head:
            return
        self.prepare_testing_report(message)

        if message.project.maintained_by(request.user) \
                and message.get_property("testing.started"):
            url = reverse("testing-reset",
                          kwargs={"project_or_series": message.message_id})
            url += "?type=message"
            message.extra_ops.append({"url": url,
                                      "title": "Reset testing states",
                                     })

        if message.get_property("testing.failed"):
            message.status_tags.append({
                "title": "Testing failed",
                "url": reverse("series_detail",
                                kwargs={"project": message.project.name,
                                        "message_id":message.message_id}),
                "type": "danger",
                "char": "T",
                })
        elif message.get_property("testing.done"):
            message.status_tags.append({
                "title": "Testing passed",
                "url": reverse("series_detail",
                                kwargs={"project": message.project.name,
                                        "message_id":message.message_id}),
                "type": "success",
                "char": "T",
                })

    def _testers_info(self, project):
        at = []
        for k, v in project.get_properties().items():
            prefix = "testing.check_in."
            if not k.startswith(prefix):
                continue
            age = time.time() - v
            if age > 10 * 60:
                continue
            tn = k[len(prefix):]
            at.append("%s (%dmin)" % (tn, math.ceil(age / 60)))
        if not at:
            return
        return "Active testers: " + ", ".join(at)

    def prepare_project_hook(self, request, project):
        if not project.maintained_by(request.user):
            return
        project.extra_info.append({"title": "Testing configuration",
                                   "class": "info",
                                   "content": self.build_config_html(request,
                                                                     project)})
        ti = self._testers_info(project)
        if ti:
            project.extra_headers.append(ti)
        self.prepare_testing_report(project)

        if project.maintained_by(request.user) \
                and project.get_property("testing.started"):
            url = reverse("testing-reset",
                          kwargs={"project_or_series": project.name})
            url += "?type=project"
            project.extra_ops.append({"url": url,
                                      "title": "Reset testing states"})

    def get_capability_probes(self, project):
        ret = {}
        for k, v in project.get_properties().items():
            prefix = "testing.requirements."
            if not k.startswith(prefix):
                continue
            name = k[len(prefix):]
            name = name[:name.find(".")]
            ret[name] = v
        return ret

    def tester_check_in(self, project, tester):
        assert project
        assert tester
        po = Project.objects.filter(name=project).first()
        if not po:
            return
        po.set_property('testing.check_in.' + tester, time.time())

class TestingGetView(APILoginRequiredView):
    name = "testing-get"
    allowed_groups = ["testers"]

    def _generate_test_data(self, project, repo, head, base, identity, test):
        r = {"project": project,
             "repo": repo,
             "head": head,
             "base": base,
             "test": test,
             "identity": identity
             }
        return r

    def _generate_series_test_data(self, s, test):
        return self._generate_test_data(project=s.project.name,
                                        repo=s.get_property("git.repo"),
                                        head=s.get_property("git.tag"),
                                        base=s.get_property("git.base"),
                                        identity={
                                            "type": "series",
                                            "message-id": s.message_id,
                                            "subject": s.subject,
                                        },
                                        test=test)

    def _generate_project_test_data(self, project, repo, head, base, test):
        return self._generate_test_data(project=project,
                                        repo=repo, head=head, base=base,
                                        identity={
                                            "type": "project",
                                            "head": head,
                                        },
                                        test=test)

    def _find_applicable_test(self, user, project, tester, capabilities, obj):
        all_tests = set([k for k, v in _instance.get_tests(obj).items() if v["enabled"]])
        done_tests = set()
        for tn, t in _instance.get_tests(project).items():
            if not t.get("enabled"):
                continue
            all_tests.add(tn)
            if obj.get_property("testing.report." + tn):
                done_tests.add(tn)
                continue
            if "tester" in t and tester != t["tester"]:
                continue
            if "user" in t and user.username != t["user"]:
                continue
            # TODO: group?
            ok = True
            reqs = t.get("requirements", "")
            for r in [x.strip() for x in reqs.split(",") if x]:
                if r not in capabilities:
                    ok = False
                    break
            if not ok:
                continue
            return t
        if len(all_tests) and all_tests.issubset(done_tests):
            obj.set_property("testing.done", True)

    def _find_project_test(self, request, po, tester, capabilities):
        head = po.get_property("git.head")
        repo = po.git
        tested = po.get_property("testing.tested-head")
        if not head or not repo:
            return
        test = self._find_applicable_test(request.user, po,
                                          tester, capabilities, po)
        if not test:
            return
        td = self._generate_project_test_data(po.name, repo, head, tested, test)
        return po, td

    def _find_series_test(self, request, po, tester, capabilities):
        se = SearchEngine()
        q = se.search_series("is:applied", "not:old", "not:tested",
                             "project:" + po.name)
        candidate = None
        for s in q:
            test = self._find_applicable_test(request.user, po,
                                              tester, capabilities, s)
            if not test:
                continue
            if not s.get_property("testing.started"):
                candidate = s, test
                break
            # Pick one series that started test the earliest
            if not candidate or \
                    s.get_property("testing.start-time") < \
                    candidate[0].get_property("testing.start-time"):
                candidate = s, test
        if not candidate:
            return None
        return candidate[0], \
               self._generate_series_test_data(candidate[0], candidate[1])

    def handle(self, request, project, tester, capabilities):
        # Try project head test first
        _instance.tester_check_in(project, tester or request.user.username)
        po = Project.objects.get(name=project)
        candidate = self._find_project_test(request, po, tester, capabilities)
        if not candidate:
            candidate = self._find_series_test(request, po, tester, capabilities)
        if not candidate:
            return
        obj, test_data = candidate
        obj.set_property("testing.started", True)
        obj.set_property("testing.start-time", time.time())
        return test_data

class TestingReportView(APILoginRequiredView):
    name = "testing-report"
    allowed_groups = ["testers"]

    def handle(self, request, tester, project, test, head, base, passed, log, identity):
        _instance.tester_check_in(project, tester or request.user.username)
        _instance.add_test_report(request.user, project, tester,
                                  test, head, base, identity, passed, log)

class TestingCapabilitiesView(APILoginRequiredView):
    name = "testing-capabilities"
    allowed_groups = ["testers"]

    def handle(self, request, tester, project):
        _instance.tester_check_in(project, tester or request.user.username)
        po = Project.objects.filter(name=project).first()
        if not po:
            raise Http404("Project '%s' not found" % project)
        probes = _instance.get_capability_probes(po)
        return probes

class UntestView(APILoginRequiredView):
    name = "untest"
    allowed_groups = ["testers"]

    def handle(self, request, terms):
        se = SearchEngine()
        q = se.search_series(*terms)
        for s in q:
            _instance.remove_testing_properties(s)
<|endoftext|>


<commit_before>import os

from lcp.settings.base import *  # noqa

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
<commit_msg>Set temporary ALLOWED_HOSTS for Vagrant testing.<commit_after>import os

from lcp.settings.base import *  # noqa

# FIXME: The wildcard is only here while testing on Vagrant.
# Host header checking fails without it.
ALLOWED_HOSTS = ['*']

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
<|endoftext|>


<commit_before>"""

LDAP Groups v4 - A python/django Active Directory group management abstraction
    that uses python-ldap as a backend for cross-platform compatability.

Dependencies:
    python3-ldap>=0.9.6

ldap-groups is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

ldap-groups is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser Public License for more details.

You should have received a copy of the GNU Lesser Public License
along with ldap-groups. If not, see <http://www.gnu.org/licenses/>.

.. moduleauthor:: Alex Kavanaugh <kavanaugh.development@outlook.com>

"""

from .groups import ADGroup

#
# Version Classification
# Major Updates, Minor Updates, Revision/Bugfix Updates
#
VERSION = ("4", "2", "0")
__version__ = ".".join(VERSION)
<commit_msg>Update __init__.py<commit_after>"""

LDAP Groups v4 - A python/django Active Directory group management abstraction
    that uses python-ldap as a backend for cross-platform compatability.

Dependencies:
    python3-ldap>=0.9.6

ldap-groups is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

ldap-groups is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser Public License for more details.

You should have received a copy of the GNU Lesser Public License
along with ldap-groups. If not, see <http://www.gnu.org/licenses/>.

.. moduleauthor:: Alex Kavanaugh <kavanaugh.development@outlook.com>

"""

from .groups import ADGroup

#
# Version Classification
# Major Updates, Minor Updates, Revision/Bugfix Updates
#
VERSION = ("4", "2", "1")
__version__ = ".".join(VERSION)
<|endoftext|>


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

from pyqtgraph.Qt import QtGui

from .plot_widget import PlotWidget
from .plot_widget import RollingPlot
from .slider_widget import SliderWidget
from PyQt4.QtCore import SIGNAL, pyqtSignal
import numpy as np

class LidarWidget(QtGui.QWidget):
    def __init__(self, spectrum_widget):
        super(LidarWidget, self).__init__()
        self.spectrum_widget = spectrum_widget
        self.driver = spectrum_widget.driver

        self.layout = QtGui.QVBoxLayout()
        self.lidar_layout = QtGui.QVBoxLayout()

        self.slider_fmin = SliderWidget(name='Minimum frequency (MHz) : ',
                                   max_slider=self.driver.sampling.fs/2*1e-6)
        self.slider_fmax = SliderWidget(name='Maximum frequency (MHz) : ',
                                   max_slider=self.driver.sampling.fs/2*1e-6)

        self.velocity_label = QtGui.QLabel()
        self.velocity_label.setText('Velocity (m/s) : '+"{:.2f}".format(0))

        self.velocity_plot_button = QtGui.QPushButton('Velocity')
        self.velocity_plot_button.setStyleSheet('QPushButton {color: blue;}')
        self.velocity_plot_button.setCheckable(True)

        self.lidar_layout.addWidget(self.slider_fmin)
        self.lidar_layout.addWidget(self.slider_fmax)
        self.lidar_layout.addWidget(self.velocity_label)
        self.lidar_layout.addWidget(self.velocity_plot_button)

        self.lidar_box = QtGui.QGroupBox("Lidar")
        self.lidar_box.setLayout(self.lidar_layout)

        self.layout.addWidget(self.lidar_box)
        self.setLayout(self.layout)

        self.velocity_plot_button.clicked.connect(self.swap_plots)
        self.is_velocity_plot = False

        self.rolling_plot = RollingPlot()
        self.rolling_plot.getPlotItem().getAxis('bottom').setLabel('Time')
        self.rolling_plot.getPlotItem().getAxis('left').setLabel('Velocity', units='m/s')
        self.rolling_plot.set_axis()

        self.velocity = 0

        self.connect(self.slider_fmin, SIGNAL("value(float)"), self.change_fmin)
        self.connect(self.slider_fmax, SIGNAL("value(float)"), self.change_fmax)

    def update(self, spectrum):
        self.velocity = self.driver.get_peak_values() * self.driver.sampling.df * 1e-6 * 1.29
        self.velocity_label.setText('Velocity (m/s) : '+"{:.2f}".
                                    format(np.mean(self.velocity))
                                   )
        self.rolling_plot.update(self.velocity)

    def swap_plots(self):
        if self.is_velocity_plot:  # switch to spectrum plot
            self.is_velocity_plot = False
            self.velocity_plot_button.setText('Velocity')
            self.spectrum_widget.set_plot_widget(self.spectrum_widget.spectrum_plot_widget)
        else:  # switch to velocity plot
            self.is_velocity_plot = True
            self.velocity_plot_button.setText('Spectrum')
            self.spectrum_widget.set_plot_widget(self.rolling_plot)
            self.rolling_plot.set_axis()

        self.spectrum_widget.plot_widget.getPlotItem().enableAutoRange()
        self.spectrum_widget.plot_widget.set_axis()

    def change_fmin(self, value):
        self.driver.set_address_range(np.uint32(value*1e6/self.driver.sampling.df),
                                      np.uint32(self.slider_fmax.value*1e6/self.driver.sampling.df))

    def change_fmax(self, value):
        self.driver.set_address_range(np.uint32(self.slider_fmin.value*1e6/self.driver.sampling.df),
                                      np.uint32(value*1e6/self.driver.sampling.df))
<commit_msg>clean lidar_widget<commit_after># -*- coding: utf-8 -*-

from pyqtgraph.Qt import QtGui

from .plot_widget import PlotWidget
from .plot_widget import RollingPlot
from .slider_widget import SliderWidget
from PyQt4.QtCore import SIGNAL, pyqtSignal
import numpy as np
import collections

class LidarWidget(QtGui.QWidget):
    def __init__(self, spectrum_widget):
        super(LidarWidget, self).__init__()
        self.spectrum_widget = spectrum_widget
        self.driver = spectrum_widget.driver

        self.layout = QtGui.QVBoxLayout()
        self.lidar_layout = QtGui.QVBoxLayout()
        self.slider_layout = QtGui.QGridLayout()

        self.slider_dict = collections.OrderedDict()
        self.slider_dict['f_min'] = SliderWidget(name='Min frequency (MHz) : ',
                                                 max_slider=self.driver.sampling.fs/2*1e-6)
        self.slider_dict['f_max'] = SliderWidget(name='Max frequency (MHz) : ',
                                                 max_slider=self.driver.sampling.fs/2*1e-6)

        for i, (name, slider) in enumerate(self.slider_dict.items()):
            self.slider_layout.addWidget(slider.label, i, 0)
            self.slider_layout.addWidget(slider.spin, i, 1)
            self.slider_layout.addWidget(slider.slider, i, 2)

        self.velocity_label = QtGui.QLabel()
        self.velocity_label.setText('Velocity (m/s) : '+"{:.2f}".format(0))

        self.velocity_plot_button = QtGui.QPushButton('Velocity')
        self.velocity_plot_button.setStyleSheet('QPushButton {color: blue;}')
        self.velocity_plot_button.setCheckable(True)

        self.lidar_layout.addLayout(self.slider_layout)
        self.lidar_layout.addWidget(self.velocity_label)
        self.lidar_layout.addWidget(self.velocity_plot_button)

        self.lidar_box = QtGui.QGroupBox("Lidar")
        self.lidar_box.setLayout(self.lidar_layout)

        self.layout.addWidget(self.lidar_box)
        self.setLayout(self.layout)

        self.velocity_plot_button.clicked.connect(self.swap_plots)
        self.is_velocity_plot = False

        self.rolling_plot = RollingPlot()
        self.rolling_plot.getPlotItem().getAxis('bottom').setLabel('Time')
        self.rolling_plot.getPlotItem().getAxis('left').setLabel('Velocity', units='m/s')
        self.rolling_plot.set_axis()

        self.velocity = 0

        self.connect(self.slider_dict['f_min'], SIGNAL("value(float)"), self.change_fmin)
        self.connect(self.slider_dict['f_max'], SIGNAL("value(float)"), self.change_fmax)

    def update(self, spectrum):
        self.velocity = self.driver.get_peak_values() * self.driver.sampling.df * 1e-6 * 1.29
        self.velocity_label.setText('Velocity (m/s) : '+"{:.2f}".format(np.mean(self.velocity))                                  )
        self.rolling_plot.update(self.velocity)

    def swap_plots(self):
        if self.is_velocity_plot:  # switch to spectrum plot
            self.is_velocity_plot = False
            self.velocity_plot_button.setText('Velocity')
            self.spectrum_widget.set_plot_widget(self.spectrum_widget.spectrum_plot_widget)
        else:  # switch to velocity plot
            self.is_velocity_plot = True
            self.velocity_plot_button.setText('Spectrum')
            self.spectrum_widget.set_plot_widget(self.rolling_plot)
            self.rolling_plot.set_axis()

        self.spectrum_widget.plot_widget.getPlotItem().enableAutoRange()
        self.spectrum_widget.plot_widget.set_axis()

    def change_fmin(self, value):
        self.driver.set_address_range(np.uint32(value*1e6/self.driver.sampling.df),
                                      np.uint32(self.slider_fmax.value*1e6/self.driver.sampling.df))

    def change_fmax(self, value):
        self.driver.set_address_range(np.uint32(self.slider_fmin.value*1e6/self.driver.sampling.df),
                                      np.uint32(value*1e6/self.driver.sampling.df))
<|endoftext|>


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

import configparser
import os
import logging
import facebook
from linkedin import linkedin
from twitter import *
from html.parser import HTMLParser
import telepot
# sudo pip install buffpy version does not work
# Better use:
# git clone https://github.com/vtemian/buffpy.git
# cd buffpy
# sudo python setup.py install
from buffpy.api import API
from buffpy.managers.profiles import Profiles
from buffpy.managers.updates import Update

def connectBuffer():
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssBuffer')])

    clientId = config.get("appKeys", "client_id")
    clientSecret = config.get("appKeys", "client_secret")
    redirectUrl = config.get("appKeys", "redirect_uri")
    accessToken = config.get("appKeys", "access_token")

    # instantiate the api object
    api = API(client_id=clientId,
              client_secret=clientSecret,
              access_token=accessToken)

    logging.debug(api.info)

    return(api)

def connectTwitter(twitterAC):
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssTwitter')])

    CONSUMER_KEY = config.get("appKeys", "CONSUMER_KEY")
    CONSUMER_SECRET = config.get("appKeys", "CONSUMER_SECRET")
    TOKEN_KEY = config.get(twitterAC, "TOKEN_KEY")
    TOKEN_SECRET = config.get(twitterAC, "TOKEN_SECRET")

    try:
        authentication = OAuth(
                    TOKEN_KEY,
                    TOKEN_SECRET,
                    CONSUMER_KEY,
                    CONSUMER_SECRET)
        t = Twitter(auth=authentication)
    except:
        print("Twitter authentication failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(t)

def connectFacebook(fbPage):
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssFacebook')])

    try:
        oauth_access_token = config.get("Facebook", "oauth_access_token")

        graph = facebook.GraphAPI(oauth_access_token, version='2.7')
        pages = graph.get_connections("me", "accounts")

        for i in range(len(pages['data'])):
            if (pages['data'][i]['name'] == fbPage):
                print("\tWriting in... ", pages['data'][i]['name'], "\n")
                graph2 = facebook.GraphAPI(pages['data'][i]['access_token'])
    except:
        print("Facebook authentication failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(pages['data'][i]['access_token'], pages['data'][i]['id'])

def connectLinkedin():
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssLinkedin')])

    CONSUMER_KEY = config.get("Linkedin", "CONSUMER_KEY")
    CONSUMER_SECRET = config.get("Linkedin", "CONSUMER_SECRET")
    USER_TOKEN = config.get("Linkedin", "USER_TOKEN")
    USER_SECRET = config.get("Linkedin", "USER_SECRET")
    RETURN_URL = config.get("Linkedin", "RETURN_URL"),

    try:
        authentication = linkedin.LinkedInDeveloperAuthentication(
                         CONSUMER_KEY,
                         CONSUMER_SECRET,
                         USER_TOKEN,
                         USER_SECRET,
                         RETURN_URL,
                         linkedin.PERMISSIONS.enums.values())

        application = linkedin.LinkedInApplication(authentication)

    except:
        print("Linkedin posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(application)

def connectTelegram(channel):
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssTelegram')])

    TOKEN = config.get("Telegram", "TOKEN")

    try:
        bot = telepot.Bot(TOKEN)
        meMySelf = bot.getMe()
    except:
        print("Telegram posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(bot)

def publishBuffer(profileList, title, link, tumblrLink, isDebug, lenMax):
    if isDebug:
        profileList = []
        tumblrLink = None
    fail = 'no'
    for profile in profileList:
        line = profile['service']
        #print(profile['service'])

        if (len(title) > 140 - 30):
        # We are allowing 30 characters for the (short) link
            titlePostT = title[:140-30]
        else:
            titlePostT = ""
        post = title + " " + link

        try:
            if titlePostT and (profile['service'] == 'twitter'):
                profile.updates.new(urllib.parse.quote(titlePostT + " " + link).encode('utf-8'))
            else:
                profile.updates.new(urllib.parse.quote(post).encode('utf-8'))
            line = line + ' ok'
            time.sleep(3)
        except:
            print("Buffer posting failed!")
            print("Unexpected error:", sys.exc_info()[0])
            print("Unexpected error:", sys.exc_info()[1])
            logging.info("Buffer posting failed!")
            logging.info("Unexpected error: %s"% sys.exc_info()[0])
            logging.info("Unexpected error: %s"% sys.exc_info()[1])

            line = line + ' fail'
            failFile = open(os.path.expanduser("~/."
                       + urllib.parse.urlparse(tumblrLink).netloc
                       + ".fail"), "w")
            failFile.write(post)
            logging.info("  %s service" % line)
            fail = 'yes'
            break

        logging.info("  %s service" % line)
        if (fail == 'no' and tumblrLink):
            urlFile = open(os.path.expanduser("~/."
                           + urllib.parse.urlparse(tumblrLink).netloc
                           + ".last"), "w")

            urlFile.write(tumblrLink)
            urlFile.close()

def publishTwitter(title, link, comment, twitter):
    statusTxt = comment + " " + title + " " + link
    h = HTMLParser()
    statusTxt = h.unescape(statusTxt)

    print("Twitter...\n")
    try:
        t = connectTwitter(twitter)
        t.statuses.update(status=statusTxt)
    except:
        print("Twitter posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

def publishFacebook(title, link, summaryLinks, image, fbPage):

    #publishFacebook("prueba2", "https://www.facebook.com/reflexioneseirreflexiones/", "b", "https://scontent-mad1-1.xx.fbcdn.net/v/t1.0-9/426052_381657691846622_987775451_n.jpg", "Reflexiones e Irreflexiones")

    print("Facebook...\n")
    try:
        h = HTMLParser()
        title = h.unescape(title)
        (access, page) = connectFacebook(fbPage)
        print(page)
        facebook.GraphAPI(access).put_object(page,
                          "feed", message=title + " \n" + summaryLinks,
                          link=link, picture=image,
                          name=title, caption='',
                          description=summaryLinks.encode('utf-8'))
    except:
        print("Facebook posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

def publishLinkedin(title, link, summary, image):
    # publishLinkedin("Prueba", "http://fernand0.blogalia.com/", "bla bla bla", "https://scontent-mad1-1.xx.fbcdn.net/v/t1.0-1/31694_125680874118651_1644400_n.jpg")
    print("Linkedin...\n")
    try:
        application = connectLinkedin()
        comment = 'Publicado! ' + title
        application.submit_share(comment, title, summary, link, image)
    except:
        print("Linkedin posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

def cleanTags(soup):
    tags = [tag.name for tag in soup.find_all()]
    validTags = ['b', 'strong', 'i', 'em', 'a', 'code', 'pre']

    quotes = soup.find_all('blockquote')
    for quote in quotes:
        quote.insert_before('«')
        quote.insert_after( '»')

    for tag in tags:
        if tag not in validTags:
            for theTag in soup.find_all(tag):
                theTag.unwrap()

    code = [td.find('code') for td in soup.findAll('pre')]
    # github.io inserts code tags inside pre tags
    for cod in code:
        cod.unwrap()

    tags = soup.findAll(text=lambda text:isinstance(text, Doctype))
    if (len(tags)>0):
        tags[0].extract()
    # <!DOCTYPE html> in github.io

def publishTelegram(channel, title, link, summary, summaryHtml, summaryLinks, image):
    #publishTelegram("reflexioneseirreflexiones","Canal de Reflexiones e Irreflexiones", "http://fernand0.blogalia.com/", "", "", "", "")

    print("Telegram...%s\n"%channel)

    try:
        bot = connectTelegram(channel)

        h = HTMLParser()
        title = h.unescape(title)
        htmlText=''+title + "\n" + summaryHtml
        soup = BeautifulSoup(htmlText)
        cleanTags(soup)
        print(soup)
        textToPublish = str(soup)[:4096]
        index = textToPublish.rfind('<')
        index2 = textToPublish.find('>',index)
        if (index2 < 0):
        # unclosed tag
        # Maybe we can still have an unclosed tag
        # Something like: < we would
            textToPublish = str(soup)[:index - 1]+' ...'
        bot.sendMessage('@'+channel, textToPublish, parse_mode='HTML')
    except:
        print("Telegram posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

if __name__ == "__main__":

    import moduleSocial

    # Test pending
<commit_msg>Cleaning code<commit_after>#!/usr/bin/env python

import configparser
import os
import logging
import facebook
from linkedin import linkedin
from twitter import *
from html.parser import HTMLParser
import telepot
# sudo pip install buffpy version does not work
# Better use:
# git clone https://github.com/vtemian/buffpy.git
# cd buffpy
# sudo python setup.py install
from buffpy.api import API
from buffpy.managers.profiles import Profiles
from buffpy.managers.updates import Update

def connectBuffer():
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssBuffer')])

    clientId = config.get("appKeys", "client_id")
    clientSecret = config.get("appKeys", "client_secret")
    redirectUrl = config.get("appKeys", "redirect_uri")
    accessToken = config.get("appKeys", "access_token")

    # instantiate the api object
    api = API(client_id=clientId,
              client_secret=clientSecret,
              access_token=accessToken)

    logging.debug(api.info)

    return(api)

def connectTwitter(twitterAC):
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssTwitter')])

    CONSUMER_KEY = config.get("appKeys", "CONSUMER_KEY")
    CONSUMER_SECRET = config.get("appKeys", "CONSUMER_SECRET")
    TOKEN_KEY = config.get(twitterAC, "TOKEN_KEY")
    TOKEN_SECRET = config.get(twitterAC, "TOKEN_SECRET")

    try:
        authentication = OAuth(
                    TOKEN_KEY,
                    TOKEN_SECRET,
                    CONSUMER_KEY,
                    CONSUMER_SECRET)
        t = Twitter(auth=authentication)
    except:
        print("Twitter authentication failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(t)

def connectFacebook(fbPage):
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssFacebook')])

    try:
        oauth_access_token = config.get("Facebook", "oauth_access_token")

        graph = facebook.GraphAPI(oauth_access_token, version='2.7')
        pages = graph.get_connections("me", "accounts")

        for i in range(len(pages['data'])):
            if (pages['data'][i]['name'] == fbPage):
                print("\tWriting in... ", pages['data'][i]['name'], "\n")
                graph2 = facebook.GraphAPI(pages['data'][i]['access_token'])
    except:
        print("Facebook authentication failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(pages['data'][i]['access_token'], pages['data'][i]['id'])

def connectLinkedin():
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssLinkedin')])

    CONSUMER_KEY = config.get("Linkedin", "CONSUMER_KEY")
    CONSUMER_SECRET = config.get("Linkedin", "CONSUMER_SECRET")
    USER_TOKEN = config.get("Linkedin", "USER_TOKEN")
    USER_SECRET = config.get("Linkedin", "USER_SECRET")
    RETURN_URL = config.get("Linkedin", "RETURN_URL"),

    try:
        authentication = linkedin.LinkedInDeveloperAuthentication(
                         CONSUMER_KEY,
                         CONSUMER_SECRET,
                         USER_TOKEN,
                         USER_SECRET,
                         RETURN_URL,
                         linkedin.PERMISSIONS.enums.values())

        application = linkedin.LinkedInApplication(authentication)

    except:
        print("Linkedin posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(application)

def connectTelegram(channel):
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssTelegram')])

    TOKEN = config.get("Telegram", "TOKEN")

    try:
        bot = telepot.Bot(TOKEN)
        meMySelf = bot.getMe()
    except:
        print("Telegram posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(bot)

def publishBuffer(profileList, title, link, tumblrLink, isDebug, lenMax):
    if isDebug:
        profileList = []
        tumblrLink = None
    fail = 'no'
    for profile in profileList:
        line = profile['service']
        #print(profile['service'])

        if (len(title) > 140 - 30):
        # We are allowing 30 characters for the (short) link
            titlePostT = title[:140-30]
        else:
            titlePostT = ""
        post = title + " " + link

        try:
            if titlePostT and (profile['service'] == 'twitter'):
                profile.updates.new(urllib.parse.quote(titlePostT + " " + link).encode('utf-8'))
            else:
                profile.updates.new(urllib.parse.quote(post).encode('utf-8'))
            line = line + ' ok'
            time.sleep(3)
        except:
            print("Buffer posting failed!")
            print("Unexpected error:", sys.exc_info()[0])
            print("Unexpected error:", sys.exc_info()[1])
            logging.info("Buffer posting failed!")
            logging.info("Unexpected error: %s"% sys.exc_info()[0])
            logging.info("Unexpected error: %s"% sys.exc_info()[1])

            line = line + ' fail'
            failFile = open(os.path.expanduser("~/."
                       + urllib.parse.urlparse(tumblrLink).netloc
                       + ".fail"), "w")
            failFile.write(post)
            logging.info("  %s service" % line)
            fail = 'yes'
            break

        logging.info("  %s service" % line)
        if (fail == 'no' and tumblrLink):
            urlFile = open(os.path.expanduser("~/."
                           + urllib.parse.urlparse(tumblrLink).netloc
                           + ".last"), "w")

            urlFile.write(tumblrLink)
            urlFile.close()

def publishTwitter(title, link, comment, twitter):
    statusTxt = comment + " " + title + " " + link
    h = HTMLParser()
    statusTxt = h.unescape(statusTxt)

    print("Twitter...\n")
    try:
        t = connectTwitter(twitter)
        t.statuses.update(status=statusTxt)
    except:
        print("Twitter posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

def publishFacebook(title, link, summaryLinks, image, fbPage):

    #publishFacebook("prueba2", "https://www.facebook.com/reflexioneseirreflexiones/", "b", "https://scontent-mad1-1.xx.fbcdn.net/v/t1.0-9/426052_381657691846622_987775451_n.jpg", "Reflexiones e Irreflexiones")

    print("Facebook...\n")
    try:
        h = HTMLParser()
        title = h.unescape(title)
        (access, page) = connectFacebook(fbPage)
        facebook.GraphAPI(access).put_object(page,
                          "feed", message=title + " \n" + summaryLinks,
                          link=link, picture=image,
                          name=title, caption='',
                          description=summaryLinks.encode('utf-8'))
    except:
        print("Facebook posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

def publishLinkedin(title, link, summary, image):
    # publishLinkedin("Prueba", "http://fernand0.blogalia.com/", "bla bla bla", "https://scontent-mad1-1.xx.fbcdn.net/v/t1.0-1/31694_125680874118651_1644400_n.jpg")
    print("Linkedin...\n")
    try:
        application = connectLinkedin()
        comment = 'Publicado! ' + title
        application.submit_share(comment, title, summary, link, image)
    except:
        print("Linkedin posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

def cleanTags(soup):
    tags = [tag.name for tag in soup.find_all()]
    validTags = ['b', 'strong', 'i', 'em', 'a', 'code', 'pre']

    quotes = soup.find_all('blockquote')
    for quote in quotes:
        quote.insert_before('«')
        quote.insert_after( '»')

    for tag in tags:
        if tag not in validTags:
            for theTag in soup.find_all(tag):
                theTag.unwrap()

    code = [td.find('code') for td in soup.findAll('pre')]
    # github.io inserts code tags inside pre tags
    for cod in code:
        cod.unwrap()

    tags = soup.findAll(text=lambda text:isinstance(text, Doctype))
    if (len(tags)>0):
        tags[0].extract()
    # <!DOCTYPE html> in github.io

def publishTelegram(channel, title, link, summary, summaryHtml, summaryLinks, image):
    #publishTelegram("reflexioneseirreflexiones","Canal de Reflexiones e Irreflexiones", "http://fernand0.blogalia.com/", "", "", "", "")

    print("Telegram...%s\n"%channel)

    try:
        bot = connectTelegram(channel)

        h = HTMLParser()
        title = h.unescape(title)
        htmlText=''+title + "\n" + summaryHtml
        soup = BeautifulSoup(htmlText)
        cleanTags(soup)
        print(soup)
        textToPublish = str(soup)[:4096]
        index = textToPublish.rfind('<')
        index2 = textToPublish.find('>',index)
        if (index2 < 0):
        # unclosed tag
        # Maybe we can still have an unclosed tag
        # Something like: < we would
            textToPublish = str(soup)[:index - 1]+' ...'
        bot.sendMessage('@'+channel, textToPublish, parse_mode='HTML')
    except:
        print("Telegram posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

if __name__ == "__main__":

    import moduleSocial

    # Test pending
<|endoftext|>


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

import configparser
import os
import sys
import logging
from bs4 import BeautifulSoup
from bs4 import NavigableString
from bs4 import Tag
from bs4 import Doctype
from html.parser import HTMLParser
import facebook
import urllib
import time
from linkedin import linkedin
from twitter import *
from html.parser import HTMLParser
import telepot
# sudo pip install buffpy version does not work
# Better use:
# git clone https://github.com/vtemian/buffpy.git
# cd buffpy
# sudo python setup.py install
from buffpy.api import API
from buffpy.managers.profiles import Profiles
from buffpy.managers.updates import Update
from medium import Client

def connectBuffer():
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssBuffer')])

    clientId = config.get("appKeys", "client_id")
    clientSecret = config.get("appKeys", "client_secret")
    redirectUrl = config.get("appKeys", "redirect_uri")
    accessToken = config.get("appKeys", "access_token")

    try:
        # instantiate the api object
        api = API(client_id=clientId,
                  client_secret=clientSecret,
                  access_token=accessToken)

        logging.debug(api.info)
    except:
        print("Buffer authentication failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(api)

def connectTwitter(twitterAC):
    # In order to obtain the parameters for a new account, just write twitter
    # and follow the instructions
    # The result will be at ~/.twitter_oauth
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssTwitter')])

    CONSUMER_KEY = config.get("appKeys", "CONSUMER_KEY")
    CONSUMER_SECRET = config.get("appKeys", "CONSUMER_SECRET")
    TOKEN_KEY = config.get(twitterAC, "TOKEN_KEY")
    TOKEN_SECRET = config.get(twitterAC, "TOKEN_SECRET")

    try:
        authentication = OAuth(
                    TOKEN_KEY,
                    TOKEN_SECRET,
                    CONSUMER_KEY,
                    CONSUMER_SECRET)
        t = Twitter(auth=authentication)
    except:
        print("Twitter authentication failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(t)

def connectFacebook(fbPage = 'me'):
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssFacebook')])

    try:
        oauth_access_token = config.get("Facebook", "oauth_access_token")

        graph = facebook.GraphAPI(oauth_access_token, version='2.7')
        pages = graph.get_connections("me", "accounts")

        if (fbPage != 'me'):
            for i in range(len(pages['data'])):
                if (pages['data'][i]['name'] == fbPage):
                    print("\tWriting in... ", pages['data'][i]['name'], "\n")
                    graph2 = facebook.GraphAPI(pages['data'][i]['access_token'])
                    # Publishing as the page
                    return(graph2, pages['data'][i]['id'])
        else:
            # Publishing as me
            return(graph, fbPage)
    except:
        print("Facebook authentication failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(0,0)

def connectLinkedin():
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssLinkedin')])

    CONSUMER_KEY = config.get("Linkedin", "CONSUMER_KEY")
    CONSUMER_SECRET = config.get("Linkedin", "CONSUMER_SECRET")
    USER_TOKEN = config.get("Linkedin", "USER_TOKEN")
    USER_SECRET = config.get("Linkedin", "USER_SECRET")
    RETURN_URL = config.get("Linkedin", "RETURN_URL"),

    try:
        authentication = linkedin.LinkedInDeveloperAuthentication(
                         CONSUMER_KEY,
                         CONSUMER_SECRET,
                         USER_TOKEN,
                         USER_SECRET,
                         RETURN_URL,
                         linkedin.PERMISSIONS.enums.values())

        application = linkedin.LinkedInApplication(authentication)

    except:
        print("Linkedin authentication failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(application)

def connectTelegram(channel):
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssTelegram')])

    TOKEN = config.get("Telegram", "TOKEN")

    try:
        bot = telepot.Bot(TOKEN)
        meMySelf = bot.getMe()
    except:
        print("Telegram authentication failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(bot)

def connectMedium():
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssMedium')])
    client = Client(application_id=config.get("appKeys","ClientID"), application_secret=config.get("appKeys","ClientSecret"))
    try:
        client.access_token = config.get("appKeys","access_token")
        # Get profile details of the user identified by the access token.
        user = client.get_current_user()
    except:
        print("Medium authentication failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(client, user)

def checkLimitPosts(api):
    # We can put as many items as the service with most items allow
    # The limit is ten.
    # Get all pending updates of a social network profile

    lenMax = 0
    logging.info("Checking services...")

    profileList = Profiles(api=api).all()
    for profile in profileList:
        lenProfile = len(profile.updates.pending)
        if (lenProfile > lenMax):
            lenMax = lenProfile
        logging.info("%s ok" % profile['service'])

    logging.info("There are %d in some buffer, we can put %d" %
                 (lenMax, 10-lenMax))

    return(lenMax, profileList)

def publishBuffer(profileList, title, link, firstLink, isDebug, lenMax):
    if isDebug:
        profileList = []
        firstLink = None
    fail = 'no'
    for profile in profileList:
        line = profile['service']
        print(profile['service'])

        if (len(title) > 140 - 24):
        # We are allowing 24 characters for the (short) link
            titlePostT = title[:140-24]
        else:
            titlePostT = ""
        post = title + " " + firstLink

        try:
            if titlePostT and (profile['service'] == 'twitter'):
                profile.updates.new(urllib.parse.quote(titlePostT + " " + firstLink).encode('utf-8'))
            else:
                profile.updates.new(urllib.parse.quote(post).encode('utf-8'))
            line = line + ' ok'
            time.sleep(3)
        except:
            print("Buffer posting failed!")
            print("Unexpected error:", sys.exc_info()[0])
            print("Unexpected error:", sys.exc_info()[1])
            logging.info("Buffer posting failed!")
            logging.info("Unexpected error: %s"% sys.exc_info()[0])
            logging.info("Unexpected error: %s"% sys.exc_info()[1])

            line = line + ' fail'
            failFile = open(os.path.expanduser("~/."
                       + urllib.parse.urlparse(link).netloc
                       + ".fail"), "w")
            failFile.write(post)
            logging.info("  %s service" % line)
            fail = 'yes'
            break

        logging.info("  %s service" % line)
        if (fail == 'no' and link):
            urlFile = open(os.path.expanduser("~/."
                           + urllib.parse.urlparse(link).netloc
                           + ".last"), "w")

            urlFile.write(link)
            urlFile.close()
        print("")

def publishTwitter(title, link, comment, twitter):

    print("Twitter...\n")
    try:
        t = connectTwitter(twitter)
        statusTxt = comment + " " + title + " " + link
        h = HTMLParser()
        statusTxt = h.unescape(statusTxt)
        t.statuses.update(status=statusTxt)
    except:
        print("Twitter posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

def publishFacebook(title, link, summaryLinks, image, fbPage):
    #publishFacebook("prueba2", "https://www.facebook.com/reflexioneseirreflexiones/", "b", "https://scontent-mad1-1.xx.fbcdn.net/v/t1.0-9/426052_381657691846622_987775451_n.jpg", "Reflexiones e Irreflexiones")

    print("Facebook...\n")
    try:
        h = HTMLParser()
        title = h.unescape(title)
        (graph, page) = connectFacebook(fbPage)
        graph.put_object(page,
                          "feed", message=title + " \n" + summaryLinks,
                          link=link, picture=image,
                          name=title, caption='',
                          description=summaryLinks.encode('utf-8'))
    except:
        print("Facebook posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

def publishLinkedin(title, link, summary, image):
    # publishLinkedin("Prueba", "http://fernand0.blogalia.com/", "bla bla bla", "https://scontent-mad1-1.xx.fbcdn.net/v/t1.0-1/31694_125680874118651_1644400_n.jpg")
    print("Linkedin...\n")
    try:
        application = connectLinkedin()
        presentation = 'Publicado! ' + title
        if link:
            application.submit_share(presentation, summary, link, image)
        else:
            application.submit_share(comment = title)
    except:
        print("Linkedin posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

def cleanTags(soup):
    tags = [tag.name for tag in soup.find_all()]
    validtags = ['b', 'strong', 'i', 'em', 'a', 'code', 'pre']

    quotes = soup.find_all('blockquote')
    for quote in quotes:
        quote.insert_before('«')
        quote.insert_after( '»')

    for tag in tags:
        if tag not in validtags:
            for theTag in soup.find_all(tag):
                theTag.unwrap()

    code = [td.find('code') for td in soup.findAll('pre')]
    # github.io inserts code tags inside pre tags
    for cod in code:
        cod.unwrap()

    tags = soup.findAll(text=lambda text:isinstance(text, Doctype))
    if (len(tags)>0):
        tags[0].extract()
    # <!DOCTYPE html> in github.io

def publishTelegram(channel, title, link, summary, summaryHtml, summaryLinks, image):
    #publishTelegram("reflexioneseirreflexiones","Canal de Reflexiones e Irreflexiones", "http://fernand0.blogalia.com/", "", "", "", "")

    print("Telegram...%s\n"%channel)

    if True:
        bot = connectTelegram(channel)

        h = HTMLParser()
        title = h.unescape(title)
        htmlText=''+title + "\n" + summaryHtml
        soup = BeautifulSoup(htmlText)
        cleanTags(soup)
        #print(soup)
        textToPublish = str(soup)[:4096]
        index = textToPublish.rfind('<')
        index2 = textToPublish.find('>',index)
        if (index2 < 0):
        # unclosed tag
        # Maybe we can still have an unclosed tag
        # Something like: < we would
            textToPublish = str(soup)[:index - 1]+' ...'
        bot.sendMessage('@'+channel, textToPublish, parse_mode='HTML')
    else:
        print("Telegram posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

def publishMedium(channel, title, link, summary, summaryHtml, summaryLinks, image):
    print("Medium...\n")
    try:
        (client, user) = connectMedium()

        post = client.create_post(user_id=user["id"], title=title,
                content=summaryHtml, canonical_url = link,
                content_format="html", publish_status="draft")
        print("My new post!", post["url"])
    except:
        print("Medium posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

if __name__ == "__main__":

    import moduleSocial

    publishTwitter("Hola caracola", "https://github.com/fernand0/scripts/blob/master/moduleSocial.py", "", "fernand0Test")
    publishFacebook("Hola caracola", "https://github.com/fernand0/scripts/blob/master/moduleSocial.py", "", "", "me")
    publishLinkedin("Hola caracola", "", "", "")
<commit_msg>Now we can publish in Medium directly. Not drafts<commit_after>#!/usr/bin/env python

import configparser
import os
import sys
import logging
from bs4 import BeautifulSoup
from bs4 import NavigableString
from bs4 import Tag
from bs4 import Doctype
from html.parser import HTMLParser
import facebook
import urllib
import time
from linkedin import linkedin
from twitter import *
from html.parser import HTMLParser
import telepot
# sudo pip install buffpy version does not work
# Better use:
# git clone https://github.com/vtemian/buffpy.git
# cd buffpy
# sudo python setup.py install
from buffpy.api import API
from buffpy.managers.profiles import Profiles
from buffpy.managers.updates import Update
from medium import Client

def connectBuffer():
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssBuffer')])

    clientId = config.get("appKeys", "client_id")
    clientSecret = config.get("appKeys", "client_secret")
    redirectUrl = config.get("appKeys", "redirect_uri")
    accessToken = config.get("appKeys", "access_token")

    try:
        # instantiate the api object
        api = API(client_id=clientId,
                  client_secret=clientSecret,
                  access_token=accessToken)

        logging.debug(api.info)
    except:
        print("Buffer authentication failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(api)

def connectTwitter(twitterAC):
    # In order to obtain the parameters for a new account, just write twitter
    # and follow the instructions
    # The result will be at ~/.twitter_oauth
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssTwitter')])

    CONSUMER_KEY = config.get("appKeys", "CONSUMER_KEY")
    CONSUMER_SECRET = config.get("appKeys", "CONSUMER_SECRET")
    TOKEN_KEY = config.get(twitterAC, "TOKEN_KEY")
    TOKEN_SECRET = config.get(twitterAC, "TOKEN_SECRET")

    try:
        authentication = OAuth(
                    TOKEN_KEY,
                    TOKEN_SECRET,
                    CONSUMER_KEY,
                    CONSUMER_SECRET)
        t = Twitter(auth=authentication)
    except:
        print("Twitter authentication failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(t)

def connectFacebook(fbPage = 'me'):
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssFacebook')])

    try:
        oauth_access_token = config.get("Facebook", "oauth_access_token")

        graph = facebook.GraphAPI(oauth_access_token, version='2.7')
        pages = graph.get_connections("me", "accounts")

        if (fbPage != 'me'):
            for i in range(len(pages['data'])):
                if (pages['data'][i]['name'] == fbPage):
                    print("\tWriting in... ", pages['data'][i]['name'], "\n")
                    graph2 = facebook.GraphAPI(pages['data'][i]['access_token'])
                    # Publishing as the page
                    return(graph2, pages['data'][i]['id'])
        else:
            # Publishing as me
            return(graph, fbPage)
    except:
        print("Facebook authentication failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(0,0)

def connectLinkedin():
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssLinkedin')])

    CONSUMER_KEY = config.get("Linkedin", "CONSUMER_KEY")
    CONSUMER_SECRET = config.get("Linkedin", "CONSUMER_SECRET")
    USER_TOKEN = config.get("Linkedin", "USER_TOKEN")
    USER_SECRET = config.get("Linkedin", "USER_SECRET")
    RETURN_URL = config.get("Linkedin", "RETURN_URL"),

    try:
        authentication = linkedin.LinkedInDeveloperAuthentication(
                         CONSUMER_KEY,
                         CONSUMER_SECRET,
                         USER_TOKEN,
                         USER_SECRET,
                         RETURN_URL,
                         linkedin.PERMISSIONS.enums.values())

        application = linkedin.LinkedInApplication(authentication)

    except:
        print("Linkedin authentication failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(application)

def connectTelegram(channel):
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssTelegram')])

    TOKEN = config.get("Telegram", "TOKEN")

    try:
        bot = telepot.Bot(TOKEN)
        meMySelf = bot.getMe()
    except:
        print("Telegram authentication failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(bot)

def connectMedium():
    config = configparser.ConfigParser()
    config.read([os.path.expanduser('~/.rssMedium')])
    client = Client(application_id=config.get("appKeys","ClientID"), application_secret=config.get("appKeys","ClientSecret"))
    try:
        client.access_token = config.get("appKeys","access_token")
        # Get profile details of the user identified by the access token.
        user = client.get_current_user()
    except:
        print("Medium authentication failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

    return(client, user)

def checkLimitPosts(api):
    # We can put as many items as the service with most items allow
    # The limit is ten.
    # Get all pending updates of a social network profile

    lenMax = 0
    logging.info("Checking services...")

    profileList = Profiles(api=api).all()
    for profile in profileList:
        lenProfile = len(profile.updates.pending)
        if (lenProfile > lenMax):
            lenMax = lenProfile
        logging.info("%s ok" % profile['service'])

    logging.info("There are %d in some buffer, we can put %d" %
                 (lenMax, 10-lenMax))

    return(lenMax, profileList)

def publishBuffer(profileList, title, link, firstLink, isDebug, lenMax):
    if isDebug:
        profileList = []
        firstLink = None
    fail = 'no'
    for profile in profileList:
        line = profile['service']
        print(profile['service'])

        if (len(title) > 140 - 24):
        # We are allowing 24 characters for the (short) link
            titlePostT = title[:140-24]
        else:
            titlePostT = ""
        post = title + " " + firstLink

        try:
            if titlePostT and (profile['service'] == 'twitter'):
                profile.updates.new(urllib.parse.quote(titlePostT + " " + firstLink).encode('utf-8'))
            else:
                profile.updates.new(urllib.parse.quote(post).encode('utf-8'))
            line = line + ' ok'
            time.sleep(3)
        except:
            print("Buffer posting failed!")
            print("Unexpected error:", sys.exc_info()[0])
            print("Unexpected error:", sys.exc_info()[1])
            logging.info("Buffer posting failed!")
            logging.info("Unexpected error: %s"% sys.exc_info()[0])
            logging.info("Unexpected error: %s"% sys.exc_info()[1])

            line = line + ' fail'
            failFile = open(os.path.expanduser("~/."
                       + urllib.parse.urlparse(link).netloc
                       + ".fail"), "w")
            failFile.write(post)
            logging.info("  %s service" % line)
            fail = 'yes'
            break

        logging.info("  %s service" % line)
        if (fail == 'no' and link):
            urlFile = open(os.path.expanduser("~/."
                           + urllib.parse.urlparse(link).netloc
                           + ".last"), "w")

            urlFile.write(link)
            urlFile.close()
        print("")

def publishTwitter(title, link, comment, twitter):

    print("Twitter...\n")
    try:
        t = connectTwitter(twitter)
        statusTxt = comment + " " + title + " " + link
        h = HTMLParser()
        statusTxt = h.unescape(statusTxt)
        t.statuses.update(status=statusTxt)
    except:
        print("Twitter posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

def publishFacebook(title, link, summaryLinks, image, fbPage):
    #publishFacebook("prueba2", "https://www.facebook.com/reflexioneseirreflexiones/", "b", "https://scontent-mad1-1.xx.fbcdn.net/v/t1.0-9/426052_381657691846622_987775451_n.jpg", "Reflexiones e Irreflexiones")

    print("Facebook...\n")
    try:
        h = HTMLParser()
        title = h.unescape(title)
        (graph, page) = connectFacebook(fbPage)
        graph.put_object(page,
                          "feed", message=title + " \n" + summaryLinks,
                          link=link, picture=image,
                          name=title, caption='',
                          description=summaryLinks.encode('utf-8'))
    except:
        print("Facebook posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

def publishLinkedin(title, link, summary, image):
    # publishLinkedin("Prueba", "http://fernand0.blogalia.com/", "bla bla bla", "https://scontent-mad1-1.xx.fbcdn.net/v/t1.0-1/31694_125680874118651_1644400_n.jpg")
    print("Linkedin...\n")
    try:
        application = connectLinkedin()
        presentation = 'Publicado! ' + title
        if link:
            application.submit_share(presentation, summary, link, image)
        else:
            application.submit_share(comment = title)
    except:
        print("Linkedin posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

def cleanTags(soup):
    tags = [tag.name for tag in soup.find_all()]
    validtags = ['b', 'strong', 'i', 'em', 'a', 'code', 'pre']

    quotes = soup.find_all('blockquote')
    for quote in quotes:
        quote.insert_before('«')
        quote.insert_after( '»')

    for tag in tags:
        if tag not in validtags:
            for theTag in soup.find_all(tag):
                theTag.unwrap()

    code = [td.find('code') for td in soup.findAll('pre')]
    # github.io inserts code tags inside pre tags
    for cod in code:
        cod.unwrap()

    tags = soup.findAll(text=lambda text:isinstance(text, Doctype))
    if (len(tags)>0):
        tags[0].extract()
    # <!DOCTYPE html> in github.io

def publishTelegram(channel, title, link, summary, summaryHtml, summaryLinks, image):
    #publishTelegram("reflexioneseirreflexiones","Canal de Reflexiones e Irreflexiones", "http://fernand0.blogalia.com/", "", "", "", "")

    print("Telegram...%s\n"%channel)

    if True:
        bot = connectTelegram(channel)

        h = HTMLParser()
        title = h.unescape(title)
        htmlText=''+title + "\n" + summaryHtml
        soup = BeautifulSoup(htmlText)
        cleanTags(soup)
        #print(soup)
        textToPublish = str(soup)[:4096]
        index = textToPublish.rfind('<')
        index2 = textToPublish.find('>',index)
        if (index2 < 0):
        # unclosed tag
        # Maybe we can still have an unclosed tag
        # Something like: < we would
            textToPublish = str(soup)[:index - 1]+' ...'
        bot.sendMessage('@'+channel, textToPublish, parse_mode='HTML')
    else:
        print("Telegram posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

def publishMedium(channel, title, link, summary, summaryHtml, summaryLinks, image):
    print("Medium...\n")
    try:
        (client, user) = connectMedium()

        post = client.create_post(user_id=user["id"], title=title,
                content=summaryHtml, canonical_url = link,
                content_format="html", publish_status="public") #draft")
        print("My new post!", post["url"])
    except:
        print("Medium posting failed!\n")
        print("Unexpected error:", sys.exc_info()[0])

if __name__ == "__main__":

    import moduleSocial

    publishTwitter("Hola caracola", "https://github.com/fernand0/scripts/blob/master/moduleSocial.py", "", "fernand0Test")
    publishFacebook("Hola caracola", "https://github.com/fernand0/scripts/blob/master/moduleSocial.py", "", "", "me")
    publishLinkedin("Hola caracola", "", "", "")
<|endoftext|>


<commit_before>class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

def create_tree_by_list(lst):
    # recursion ver
    def helper(idx):
        if idx > len(lst) - 1 or lst[idx] is None:
            return None
        else:
            root = TreeNode(lst[idx])
            root.left = helper(idx*2+1)
            root.right = helper(idx*2+2)
        return root
    return helper(0)

def tree_traversal(root):
    ret = []
    if root:
        ret.append(root.val)
        child = [root.left, root.right]
        while child:
            new_child = []
            current_layer = []
            flag = False
            for node in child:
                if node:
                    flag = True
                    current_layer.append(node.val)
                    new_child += [ node.left, node.right ]
                else:
                    current_layer.append(None)
                    new_child += [None, None]
            if flag:
                ret += current_layer
                child = new_child
            else:
                break
    return ret

if __name__ == "__main__":
    a = TreeNode(-10)
    a.left = TreeNode(9)
    a.right = TreeNode(20)
    a.right.left = TreeNode(15)
    a.right.right = TreeNode(7)
    b = tree_traversal(a)
    print(b)
    null = None
    c = [3,9,20,null,null,15,7]
    d = create_tree_by_list(c)
    e = tree_traversal(d)
    assert c == e<commit_msg>+ helper.tree: return i th node of tree<commit_after>class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

def create_tree_by_list(lst, node_indexes=[]):
    # recursion ver
    if node_indexes:
        ret = []
    def helper(idx):
        if idx > len(lst) - 1 or lst[idx] is None:
            return None
        else:
            root = TreeNode(lst[idx])
            ret.append(root)
            root.left = helper(idx*2+1)
            root.right = helper(idx*2+2)
        return root
    if node_indexes:
        return helper(0), [ret[i] for i in node_indexes]
    return helper(0)

def tree_traversal(root):
    ret = []
    if root:
        ret.append(root.val)
        child = [root.left, root.right]
        while child:
            new_child = []
            current_layer = []
            flag = False
            for node in child:
                if node:
                    flag = True
                    current_layer.append(node.val)
                    new_child += [ node.left, node.right ]
                else:
                    current_layer.append(None)
                    new_child += [None, None]
            if flag:
                ret += current_layer
                child = new_child
            else:
                break
    return ret

if __name__ == "__main__":
    a = TreeNode(-10)
    a.left = TreeNode(9)
    a.right = TreeNode(20)
    a.right.left = TreeNode(15)
    a.right.right = TreeNode(7)
    b = tree_traversal(a)
    print(b)
    null = None
    c = [3,9,20,null,null,15,7]
    d = create_tree_by_list(c)
    e = tree_traversal(d)
    assert c == e<|endoftext|>