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

import re

from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo

class PromptfileCom(SimpleHoster):
    __name__ = "PromptfileCom"
    __type__ = "hoster"
    __version__ = "0.1"

    __pattern__ = r'https?://(?:www\.)?promptfile\.com/'

    __description__ = """Promptfile.com hoster plugin"""
    __license__ = "GPLv3"
    __authors__ = [("igel", "igelkun@myopera.com")]

    FILE_INFO_PATTERN = r'(?P<N>.*?) \((?P<S>[\d.,]+) (?P[\w^_]+)\)'
    OFFLINE_PATTERN = r'File Not Found'

    CHASH_PATTERN = r'<input type="hidden" name="chash" value="([^"]*)" />'
    LINK_PATTERN = r'clip: {\s*url: \'(https?://(?:www\.)promptfile[^\']*)\','

    def handleFree(self):
        # STAGE 1: get link to continue
        m = re.search(self.CHASH_PATTERN, self.html)
        if m is None:
            self.parseError("Unable to detect chash")
        chash = m.group(1)
        self.logDebug("Read chash %s" % chash)
        # continue to stage2
        self.html = self.load(self.pyfile.url, decode=True, post={'chash': chash})

        # STAGE 2: get the direct link
        m = re.search(self.LINK_PATTERN, self.html, re.MULTILINE | re.DOTALL)
        if m is None:
            self.parseError("Unable to detect direct link")
        direct = m.group(1)
        self.logDebug("Found direct link: " + direct)
        self.download(direct, disposition=True)

getInfo = create_getInfo(PromptfileCom)
<commit_msg>Update PromptfileCom.py<commit_after># -*- coding: utf-8 -*-

import re

from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo

class PromptfileCom(SimpleHoster):
    __name__ = "PromptfileCom"
    __type__ = "hoster"
    __version__ = "0.11"

    __pattern__ = r'https?://(?:www\.)?promptfile\.com/'

    __description__ = """Promptfile.com hoster plugin"""
    __license__ = "GPLv3"
    __authors__ = [("igel", "igelkun@myopera.com")]

    FILE_INFO_PATTERN = r'(?P<N>.*?) \((?P<S>[\d.,]+) (?P[\w^_]+)\)'
    OFFLINE_PATTERN = r'File Not Found'

    CHASH_PATTERN = r'<input type="hidden" name="chash" value="([^"]*)" />'
    LINK_PATTERN = r'Download File'

    def handleFree(self):
        # STAGE 1: get link to continue
        m = re.search(self.CHASH_PATTERN, self.html)
        if m is None:
            self.parseError("Unable to detect chash")
        chash = m.group(1)
        self.logDebug("Read chash %s" % chash)
        # continue to stage2
        self.html = self.load(self.pyfile.url, decode=True, post={'chash': chash})

        # STAGE 2: get the direct link
        m = re.search(self.LINK_PATTERN, self.html)
        if m is None:
            self.parseError("Unable to detect direct link")
        direct = m.group(1)
        self.logDebug("Found direct link: " + direct)
        self.download(direct, disposition=True)

getInfo = create_getInfo(PromptfileCom)
<|endoftext|>


<commit_before>"""
Tests for L{txzmq.factory} automatic shutdown.

The _z_ infix is used to have this test a last-called one.
"""
from txzmq.factory import ZmqFactory

from twisted.internet.test.reactormixins import ReactorBuilder
from twisted.internet.interfaces import IReactorCore

class ZmqReactorShutdownTestCase(ReactorBuilder):
    """
    Test case for L{zmq.twisted.factory.Factory}
    automatic shutdown when the reactor is shutting down.
    """

    requiredInterfaces = (IReactorCore,)

    def test_reactor_shutdown(self):
        reactor = self.buildReactor()

        def _test():
            factory = ZmqFactory()
            factory.reactor = reactor
            factory.registerForShutdown()
            factory.shutdown()
            reactor.stop()
        reactor.callWhenRunning(_test)

globals().update(ZmqReactorShutdownTestCase.makeTestCaseClasses())
<commit_msg>Just a comment<commit_after>"""
Tests for L{txzmq.factory} automatic shutdown.
"""
from txzmq.factory import ZmqFactory

from twisted.internet.test.reactormixins import ReactorBuilder
from twisted.internet.interfaces import IReactorCore

class ZmqReactorShutdownTestCase(ReactorBuilder):
    """
    Test case for L{zmq.twisted.factory.Factory}
    automatic shutdown when the reactor is shutting down.
    """

    requiredInterfaces = (IReactorCore,)

    def test_reactor_shutdown(self):
        reactor = self.buildReactor()

        def _test():
            factory = ZmqFactory()
            factory.reactor = reactor
            factory.registerForShutdown()
            factory.shutdown()
            reactor.stop()
        reactor.callWhenRunning(_test)

globals().update(ZmqReactorShutdownTestCase.makeTestCaseClasses())
<|endoftext|>


<commit_before>#ipc_lista1.8
#Professor: Jucimar Junior
#Any Mendes Carvalho - 1615310044
#
#
#
#
#Faça um programa que pergunte quanto você ganha por hora e o número de horas trabalhadas no mês.
#Calcule e mostre o total do seu salário no referido mês.

QntHora = input("Entre com o valor de seu rendimento por hora: ")
hT = input("Entre com a quantidade de horas trabalhadas no mês: )

Salario = round(QntHora*hT,2)

print("\n Você ganhou %.2f
<commit_msg>Update ipc_lista1.8.py<commit_after>#ipc_lista1.8
#Professor: Jucimar Junior
#Any Mendes Carvalho - 1615310044
#
#
#
#
#Faça um programa que pergunte quanto você ganha por hora e o número de horas trabalhadas no mês.
#Calcule e mostre o total do seu salário no referido mês.

QntHora = input("Entre com o valor de seu rendimento por hora: ")
hT = input("Entre com a quantidade de horas trabalhadas no mês: )

Salario = round(QntHora*hT,2)

print("\n Você ganhou %.2f reais
<|endoftext|>


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

# Test links (random.bin):
# http://www8.zippyshare.com/v/3120421/file.html

import re
import subprocess
import tempfile
import os

from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, timestamp
from module.plugins.internal.CaptchaService import ReCaptcha
from module.common.json_layer import json_loads

class ZippyshareCom(SimpleHoster):
    __name__ = "ZippyshareCom"
    __type__ = "hoster"
    __pattern__ = r'(?P<HOST>http://www\d{0,2}\.zippyshare.com)/v(?:/|iew.jsp.*key=)(?P<KEY>\d+)'
    __version__ = "0.46"
    __description__ = """Zippyshare.com hoster plugin"""
    __author_name__ = ("spoob", "zoidberg", "stickell")
    __author_mail__ = ("spoob@pyload.org", "zoidberg@mujmail.cz", "l.stickell@yahoo.it")
    __config__ = [("swfdump_path", "string", "Path to swfdump", "")]

    FILE_NAME_PATTERN = r'>Name:\s*]*>(?P<N>[^<]+)
'
    FILE_SIZE_PATTERN = r'>Size:\s*]*>(?P<S>[0-9.,]+) (?P[kKMG]+)i?B
'
    FILE_INFO_PATTERN = r'document\.getElementById\(\'dlbutton\'\)\.href = "[^;]*/(?P<N>[^"]+)";'
    FILE_OFFLINE_PATTERN = r'>File does not exist on this server
'

    SH_COOKIES = [('zippyshare.com', 'ziplocale', 'en')]

    DOWNLOAD_URL_PATTERN = r"


<commit_before># Copyright (C) 2015 Twitter, Inc.

"""Container for all audience management logic used by the Ads API SDK."""

from twitter_ads.enum import TRANSFORM
from twitter_ads.resource import resource_property, Resource
from twitter_ads.http import Request
from twitter_ads.error import BadRequest
from twitter_ads.cursor import Cursor
from twitter_ads import API_VERSION

import json

class TailoredAudience(Resource):

    PROPERTIES = {}
    RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/tailored_audiences'
    RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/tailored_audiences/{id}'
    RESOURCE_USERS = '/' + API_VERSION + '/accounts/{account_id}/tailored_audiences/\
{id}/users'
    RESOURCE_PERMISSIONS = '/' + API_VERSION + '/accounts/{account_id}/tailored_audiences/\
{id}/permissions'

    @classmethod
    def create(klass, account, name):
        """
        Creates a new tailored audience.
        """
        audience = klass(account)
        getattr(audience, '__create_audience__')(name)
        try:
            return audience.reload()
        except BadRequest as e:
            audience.delete()
            raise e

    def users(self, params):
        """
        This is a private API and requires whitelisting from Twitter.
        This endpoint will allow partners to add, update and remove users from a given
        tailored_audience_id.
        The endpoint will also accept multiple user identifier types per user as well.
        """
        resource = self.RESOURCE_USERS.format(account_id=self.account.id, id=self.id)
        headers = {'Content-Type': 'application/json'}
        response = Request(self.account.client,
                           'post',
                           resource,
                           headers=headers,
                           body=json.dumps(params)).perform()
        success_count = response.body['data']['success_count']
        total_count = response.body['data']['total_count']
        return (success_count, total_count)

    def delete(self):
        """
        Deletes the current tailored audience instance.
        """
        resource = self.RESOURCE.format(account_id=self.account.id, id=self.id)
        response = Request(self.account.client, 'delete', resource).perform()
        return self.from_response(response.body['data'])

    def permissions(self, **kwargs):
        """
        Returns a collection of permissions for the curent tailored audience.
        """
        self._validate_loaded()
        return TailoredAudiencePermission.all(self.account, self.id, **kwargs)

    def __create_audience__(self, name):
        params = {'name': name}
        resource = self.RESOURCE_COLLECTION.format(account_id=self.account.id)
        response = Request(self.account.client, 'post', resource, params=params).perform()
        return self.from_response(response.body['data'])

# tailored audience properties
# read-only
resource_property(TailoredAudience, 'id', readonly=True)
resource_property(TailoredAudience, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(TailoredAudience, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(TailoredAudience, 'deleted', readonly=True, transform=TRANSFORM.BOOL)
resource_property(TailoredAudience, 'audience_size', readonly=True)
resource_property(TailoredAudience, 'audience_type', readonly=True)
resource_property(TailoredAudience, 'metadata', readonly=True)
resource_property(TailoredAudience, 'partner_source', readonly=True)
resource_property(TailoredAudience, 'reasons_not_targetable', readonly=True)
resource_property(TailoredAudience, 'targetable', readonly=True)
resource_property(TailoredAudience, 'targetable_types', readonly=True)
# writable
resource_property(TailoredAudience, 'name')
resource_property(TailoredAudience, 'list_type')

class TailoredAudiencePermission(Resource):

    PROPERTIES = {}

    RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/tailored_audiences/'
    RESOURCE_COLLECTION += '{tailored_audience_id}/permissions'
    RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/tailored_audiences/\
{tailored_audience_id}/permissions/{id}'

    @classmethod
    def all(klass, account, tailored_audience_id, **kwargs):
        """Returns a Cursor instance for the given tailored audience permission resource."""

        resource = klass.RESOURCE_COLLECTION.format(
            account_id=account.id,
            tailored_audience_id=tailored_audience_id)
        request = Request(account.client, 'get', resource, params=kwargs)

        return Cursor(klass, request, init_with=[account])

    def save(self):
        """
        Saves or updates the current tailored audience permission.
        """
        if self.id:
            method = 'put'
            resource = self.RESOURCE.format(
                account_id=self.account.id,
                tailored_audience_id=self.tailored_audience_id,
                id=self.id)
        else:
            method = 'post'
            resource = self.RESOURCE_COLLECTION.format(
                account_id=self.account.id,
                tailored_audience_id=self.tailored_audience_id)

        response = Request(
            self.account.client, method,
            resource, params=self.to_params()).perform()

        return self.from_response(response.body['data'])

    def delete(self):
        """
        Deletes the current tailored audience permission.
        """
        resource = self.RESOURCE.format(
            account_id=self.account.id,
            tailored_audience_id=self.tailored_audience_id,
            id=self.id)
        response = Request(self.account.client, 'delete', resource).perform()
        return self.from_response(response.body['data'])

# tailored audience permission properties
# read-only
resource_property(TailoredAudiencePermission, 'id', readonly=True)
resource_property(TailoredAudiencePermission, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(TailoredAudiencePermission, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(TailoredAudiencePermission, 'deleted', readonly=True, transform=TRANSFORM.BOOL)
# writable
resource_property(TailoredAudiencePermission, 'tailored_audience_id')
resource_property(TailoredAudiencePermission, 'granted_account_id')
resource_property(TailoredAudiencePermission, 'permission_level')

class AudienceIntelligence(Resource):

    PROPERTIES = {}

    RESOURCE_BASE = '/' + API_VERSION + '/accounts/{account_id}/audience_intelligence/'
    RESOURCE_CONVERSATIONS = RESOURCE_BASE + 'conversations'
    RESOURCE_DEMOGRAPHICS = RESOURCE_BASE + 'demographics'
    METHOD = 'post'
    HEADERS = {'Content-Type': 'application/json'}

    @classmethod
    def __get(klass, account, client, params):
        """
        Helper function to get the conversation data
        Returns a Cursor instance
        """
        resource = klass.RESOURCE_CONVERSATIONS.format(account_id=account.id)

        request = Request(
            account.client, klass.METHOD,
            resource, headers=klass.HEADERS, body=params)
        return Cursor(klass, request, init_with=[account])

    def conversations(self):
        """
        Get the conversation topics for an input targeting criteria
        """
        body = {
            "conversation_type": self.conversation_type,
            "audience_definition": self.audience_definition,
            "targeting_inputs": self.targeting_inputs
        }
        return self.__get(account=self.account, client=self.account.client, params=json.dumps(body))

    def demographics(self):
        """
        Get the demographic breakdown for an input targeting criteria
        """
        body = {
            "audience_definition": self.audience_definition,
            "targeting_inputs": self.targeting_inputs
        }
        resource = self.RESOURCE_DEMOGRAPHICS.format(account_id=self.account.id)
        response = Request(
            self.account.client, self.METHOD,
            resource, headers=self.HEADERS, body=json.dumps(body)).perform()
        return response.body['data']

# tailored audience permission properties
# read-only
resource_property(AudienceIntelligence, 'operator_type', readonly=True)
resource_property(AudienceIntelligence, 'targeting_type', readonly=True)
resource_property(AudienceIntelligence, 'targeting_value', readonly=True)
resource_property(AudienceIntelligence, 'localized', readonly=True)
# writable
resource_property(AudienceIntelligence, 'conversation_type')
resource_property(AudienceIntelligence, 'targeting_inputs')
resource_property(AudienceIntelligence, 'audience_definition')
# demographics only
resource_property(AudienceIntelligence, 'start_time', transform=TRANSFORM.TIME)
resource_property(AudienceIntelligence, 'end_time', transform=TRANSFORM.TIME)
<commit_msg>"PUT" TA permissions path no longer exists (#197)<commit_after># Copyright (C) 2015 Twitter, Inc.

"""Container for all audience management logic used by the Ads API SDK."""

from twitter_ads.enum import TRANSFORM
from twitter_ads.resource import resource_property, Resource
from twitter_ads.http import Request
from twitter_ads.error import BadRequest
from twitter_ads.cursor import Cursor
from twitter_ads import API_VERSION

import json

class TailoredAudience(Resource):

    PROPERTIES = {}
    RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/tailored_audiences'
    RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/tailored_audiences/{id}'
    RESOURCE_USERS = '/' + API_VERSION + '/accounts/{account_id}/tailored_audiences/\
{id}/users'
    RESOURCE_PERMISSIONS = '/' + API_VERSION + '/accounts/{account_id}/tailored_audiences/\
{id}/permissions'

    @classmethod
    def create(klass, account, name):
        """
        Creates a new tailored audience.
        """
        audience = klass(account)
        getattr(audience, '__create_audience__')(name)
        try:
            return audience.reload()
        except BadRequest as e:
            audience.delete()
            raise e

    def users(self, params):
        """
        This is a private API and requires whitelisting from Twitter.
        This endpoint will allow partners to add, update and remove users from a given
        tailored_audience_id.
        The endpoint will also accept multiple user identifier types per user as well.
        """
        resource = self.RESOURCE_USERS.format(account_id=self.account.id, id=self.id)
        headers = {'Content-Type': 'application/json'}
        response = Request(self.account.client,
                           'post',
                           resource,
                           headers=headers,
                           body=json.dumps(params)).perform()
        success_count = response.body['data']['success_count']
        total_count = response.body['data']['total_count']
        return (success_count, total_count)

    def delete(self):
        """
        Deletes the current tailored audience instance.
        """
        resource = self.RESOURCE.format(account_id=self.account.id, id=self.id)
        response = Request(self.account.client, 'delete', resource).perform()
        return self.from_response(response.body['data'])

    def permissions(self, **kwargs):
        """
        Returns a collection of permissions for the curent tailored audience.
        """
        self._validate_loaded()
        return TailoredAudiencePermission.all(self.account, self.id, **kwargs)

    def __create_audience__(self, name):
        params = {'name': name}
        resource = self.RESOURCE_COLLECTION.format(account_id=self.account.id)
        response = Request(self.account.client, 'post', resource, params=params).perform()
        return self.from_response(response.body['data'])

# tailored audience properties
# read-only
resource_property(TailoredAudience, 'id', readonly=True)
resource_property(TailoredAudience, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(TailoredAudience, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(TailoredAudience, 'deleted', readonly=True, transform=TRANSFORM.BOOL)
resource_property(TailoredAudience, 'audience_size', readonly=True)
resource_property(TailoredAudience, 'audience_type', readonly=True)
resource_property(TailoredAudience, 'metadata', readonly=True)
resource_property(TailoredAudience, 'partner_source', readonly=True)
resource_property(TailoredAudience, 'reasons_not_targetable', readonly=True)
resource_property(TailoredAudience, 'targetable', readonly=True)
resource_property(TailoredAudience, 'targetable_types', readonly=True)
# writable
resource_property(TailoredAudience, 'name')
resource_property(TailoredAudience, 'list_type')

class TailoredAudiencePermission(Resource):

    PROPERTIES = {}

    RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/tailored_audiences/'
    RESOURCE_COLLECTION += '{tailored_audience_id}/permissions'
    RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/tailored_audiences/\
{tailored_audience_id}/permissions/{id}'

    @classmethod
    def all(klass, account, tailored_audience_id, **kwargs):
        """Returns a Cursor instance for the given tailored audience permission resource."""

        resource = klass.RESOURCE_COLLECTION.format(
            account_id=account.id,
            tailored_audience_id=tailored_audience_id)
        request = Request(account.client, 'get', resource, params=kwargs)

        return Cursor(klass, request, init_with=[account])

    def save(self):
        """
        Saves or updates the current tailored audience permission.
        """
        resource = self.RESOURCE_COLLECTION.format(
            account_id=self.account.id,
            tailored_audience_id=self.tailored_audience_id)

        response = Request(
            self.account.client, 'post',
            resource, params=self.to_params()).perform()

        return self.from_response(response.body['data'])

    def delete(self):
        """
        Deletes the current tailored audience permission.
        """
        resource = self.RESOURCE.format(
            account_id=self.account.id,
            tailored_audience_id=self.tailored_audience_id,
            id=self.id)
        response = Request(self.account.client, 'delete', resource).perform()
        return self.from_response(response.body['data'])

# tailored audience permission properties
# read-only
resource_property(TailoredAudiencePermission, 'id', readonly=True)
resource_property(TailoredAudiencePermission, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(TailoredAudiencePermission, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(TailoredAudiencePermission, 'deleted', readonly=True, transform=TRANSFORM.BOOL)
# writable
resource_property(TailoredAudiencePermission, 'tailored_audience_id')
resource_property(TailoredAudiencePermission, 'granted_account_id')
resource_property(TailoredAudiencePermission, 'permission_level')

class AudienceIntelligence(Resource):

    PROPERTIES = {}

    RESOURCE_BASE = '/' + API_VERSION + '/accounts/{account_id}/audience_intelligence/'
    RESOURCE_CONVERSATIONS = RESOURCE_BASE + 'conversations'
    RESOURCE_DEMOGRAPHICS = RESOURCE_BASE + 'demographics'
    METHOD = 'post'
    HEADERS = {'Content-Type': 'application/json'}

    @classmethod
    def __get(klass, account, client, params):
        """
        Helper function to get the conversation data
        Returns a Cursor instance
        """
        resource = klass.RESOURCE_CONVERSATIONS.format(account_id=account.id)

        request = Request(
            account.client, klass.METHOD,
            resource, headers=klass.HEADERS, body=params)
        return Cursor(klass, request, init_with=[account])

    def conversations(self):
        """
        Get the conversation topics for an input targeting criteria
        """
        body = {
            "conversation_type": self.conversation_type,
            "audience_definition": self.audience_definition,
            "targeting_inputs": self.targeting_inputs
        }
        return self.__get(account=self.account, client=self.account.client, params=json.dumps(body))

    def demographics(self):
        """
        Get the demographic breakdown for an input targeting criteria
        """
        body = {
            "audience_definition": self.audience_definition,
            "targeting_inputs": self.targeting_inputs
        }
        resource = self.RESOURCE_DEMOGRAPHICS.format(account_id=self.account.id)
        response = Request(
            self.account.client, self.METHOD,
            resource, headers=self.HEADERS, body=json.dumps(body)).perform()
        return response.body['data']

# tailored audience permission properties
# read-only
resource_property(AudienceIntelligence, 'operator_type', readonly=True)
resource_property(AudienceIntelligence, 'targeting_type', readonly=True)
resource_property(AudienceIntelligence, 'targeting_value', readonly=True)
resource_property(AudienceIntelligence, 'localized', readonly=True)
# writable
resource_property(AudienceIntelligence, 'conversation_type')
resource_property(AudienceIntelligence, 'targeting_inputs')
resource_property(AudienceIntelligence, 'audience_definition')
# demographics only
resource_property(AudienceIntelligence, 'start_time', transform=TRANSFORM.TIME)
resource_property(AudienceIntelligence, 'end_time', transform=TRANSFORM.TIME)
<|endoftext|>


<commit_before>import json
import logging

import tornado.httpclient
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.netutil

from tornado.gen import coroutine, Return
from options import options

import tornado.log

import internal
import access
import discover
import admin
import jsonrpc
import handler
import traceback
import time
import signal

# just included to define things
import options.default as opts_

from . import retry, ElapsedTime

MAX_WAIT_SECONDS_BEFORE_SHUTDOWN = 5

SERVICE_VERSION = "0.1"
tornado.netutil.Resolver.configure('tornado.netutil.ThreadedResolver')

class ServerError(RuntimeError):
    def __init__(self, message, *args, **kwargs):
        super(ServerError, self).__init__(*args, **kwargs)
        self.message = message

    def __str__(self):
        return self.message

class Server(tornado.web.Application):
    def __init__(self):

        self.http_server = None

        self.api_version = SERVICE_VERSION

        handlers = self.get_handlers() or []

        admin_actions = self.get_admin()
        if admin_actions:
            self.actions = admin.AdminActions(admin_actions)
            handlers.extend([
                (r"/@admin", admin.AdminHandler),
                (r"/@admin_upload", admin.AdminUploadHandler)
            ])
        else:
            self.actions = None

        stream_admin_actions = self.get_admin_stream()
        if stream_admin_actions:
            self.stream_actions = admin.AdminActions(stream_admin_actions)
            handlers.append((r"/@stream_admin", admin.AdminWSHandler))
        else:
            self.stream_actions = None

        self.internal_handler = self.get_internal_handler()

        metadata = self.get_metadata()

        if isinstance(metadata, dict):
            self.metadata = self.__load_metadata__(metadata)
            logging.info("Metadata loaded")
            handlers.append((r"/@metadata", admin.AdminMetadataHandler))

        auth_callback = self.get_auth_callback()
        if auth_callback:
            handlers.append((r"/callback", auth_callback))

        if options.serve_static:
            handlers.append((r'/static/(.*)', tornado.web.StaticFileHandler,
                             {'path': 'static', "default_filename": "index.html"}))

        super(Server, self).__init__(
            handlers=handlers, debug=options.debug
        )

        self.token_cache = access.AccessTokenCache()
        self.name = None

        self.internal = None
        self.shutting_down = False
        self.graceful_shutdown = options.graceful_shutdown

        tornado.ioloop.IOLoop.instance().set_blocking_log_threshold(0.5)

    def __load_metadata__(self, data):
        data["version"] = self.api_version
        return data

    @coroutine
    def get_auth_location(self, network):
        result = yield discover.cache.get_service("login", network)
        raise Return(result)

    def get_handlers(self):
        """
        This method is need to be overridden to return a list of tuples: one tuple for each request the
        service can process.

        For example,

        [
            ("/user", handlers.UserHandler)
        ]

        This binds a /user request to a UserHandler (overridden from RequestHandler)

        """
        return []

    def get_auth_callback(self):
        return handler.AuthCallbackHandler

    def get_admin(self):
        """
        This method is need to be overridden to return a dict of classes: AdminController's
        This allows to administrate each service in admin tool.
        Each AdminController corresponds one single action can be done in such tool.
        Please see `AdminController` for more information.
        """
        return {}

    def get_admin_stream(self):
        return {}

    def get_internal_handler(self):
        """
        Object, returned by this method is used handle request from other services across environment.

        To do so, they may do yield internal.request("<service_id>", "<command_name>", <arguments>)
        In that case, a @coroutine method <command_name> would be called on that object with <arguments>

        for example, for such internal handler:

        class InternalHandler():
            @coroutine
            def hello(name):
                ... do some work ...
                raise Return({"hello, your name is": name})

        a call would be:

        result = yield internal.request("<service_id>", "hello", name="john")

        a result would be:

         {"hello, your name is": "john"}

        """

        return None

    def get_metadata(self):
        """
        Returns a location of metadata file.
        This file is used in admin tool to acquire description of the service.
        """
        return None

    @coroutine
    def get_gamespace(self, gamespace_name):
        """
        :returns a gamespace ID from given name.
        """
        internal_ = internal.Internal()

        @retry(operation="Acquiring gamespace", max=5, delay=5)
        @coroutine
        def do_try():
            response = yield internal_.request(
                "login",
                "get_gamespace",
                name=gamespace_name)
            raise Return(str(response["id"]))

        raise Return((yield do_try()))

    @coroutine
    def get_gamespace_list(self):
        """
        :returns: a list of available gamespaces across the environment.
        """
        internal_ = internal.Internal()

        @retry(operation="Acquiring gamespace list", max=5, delay=5)
        @coroutine
        def do_try():
            response = yield internal_.request("login", "get_gamespaces")
            raise Return(response)

        raise Return((yield do_try()))

    def init_discovery(self):
        discover.init()

    # noinspection PyMethodMayBeStatic
    def get_models(self):
        """
        Returns a list of models in the application
        """
        return []

    @coroutine
    def started(self):
        self.name = options.name

        self.token_cache.load()
        self.init_discovery()
        self.internal = internal.Internal()

        if self.internal_handler:
            yield self.internal.listen(self.name, self.__on_internal_receive__)

        for model in self.get_models():
            if hasattr(model, "started"):
                yield model.started()

        logging.info("Service '%s' started.", self.name)

    def run(self):
        signal.signal(signal.SIGTERM, self.__sig_handler__)
        signal.signal(signal.SIGINT, self.__sig_handler__)

        self.http_server = tornado.httpserver.HTTPServer(self, xheaders=True)

        listen_uri = options.listen
        listen_group = listen_uri.split(":")

        if len(listen_group) < 2:
            raise ServerError("Failed to listen on " + listen_uri + ": bad format")

        kind, address = listen_group[0], listen_group[1]

        def listen_port(port):
            self.http_server.listen(int(port), "127.0.0.1")

        def listen_unix(sock):
            logging.info("Listening for socket: " + sock)
            unix_socket = tornado.netutil.bind_unix_socket(sock, mode=0o777)
            self.http_server.add_socket(unix_socket)

        kinds = {
            "port": listen_port,
            "unix": listen_unix
        }

        if kind not in kinds:
            raise ServerError("Failed to listen on " + listen_uri + ": unsupported kind")

        listen_method = kinds[kind]
        listen_method(address)

        logging.info("Listening '{0}' on '{1}'".format(kind, address))
        logging.info("Host is '{0}'".format(self.get_host()))

        tornado.ioloop.IOLoop.instance().add_callback(self.started)
        tornado.ioloop.IOLoop.instance().start()

    # noinspection PyMethodMayBeStatic
    def get_host(self):
        return options.host

    @coroutine
    def __on_internal_receive__(self, context, method, *args, **kwargs):
        if hasattr(self.internal_handler, method):

            if not isinstance(method, (str, unicode)):
                raise jsonrpc.JsonRPCError(-32600, "Method is not a string")

            if method.startswith("_"):
                raise jsonrpc.JsonRPCError(-32600, "No such method")

            timer = ElapsedTime("incoming request: {0}".format(method))

            # noinspection PyBroadException
            try:
                result = yield getattr(self.internal_handler, method)(*args, **kwargs)
            except internal.InternalError as e:
                raise jsonrpc.JsonRPCError(e.code, e.body, "code: " + str(e.code))
            except Exception:
                raise jsonrpc.JsonRPCError(-32603, traceback.format_exc())
            else:
                raise Return(result)
            finally:
                timer.done()

        else:
            raise jsonrpc.JsonRPCError(-32600, "No such method")

    def __sig_handler__(self, sig, frame):
        if self.shutting_down:
            return

        logging.warning('Caught signal: %s', sig)
        tornado.ioloop.IOLoop.instance().add_callback(self.shutdown)

    def shutdown(self):
        self.shutting_down = True

        logging.info('Stopping server!')
        self.http_server.stop()

        if self.graceful_shutdown:

            for model in self.get_models():
                if hasattr(model, "stopped"):
                    tornado.ioloop.IOLoop.instance().add_callback(model.stopped)

            logging.info('Will shutdown in %s seconds ...', MAX_WAIT_SECONDS_BEFORE_SHUTDOWN)
            io_loop = tornado.ioloop.IOLoop.instance()

            deadline = time.time() + MAX_WAIT_SECONDS_BEFORE_SHUTDOWN

            # noinspection PyProtectedMember
            def stop_loop():
                now = time.time()
                if now < deadline and (io_loop._callbacks or io_loop._timeouts):
                    io_loop.add_timeout(now + 1, stop_loop)
                else:
                    io_loop.stop()
                    logging.info('Stopped!')
            stop_loop()

        else:
            tornado.ioloop.IOLoop.instance().stop()
            logging.info('Stopped!')

def init():
    import options

    options.parse_command_line()
    options.parse_env()

    return options

def start(server_cls):
    application = server_cls()
    application.run()
<commit_msg>Added multi socket support<commit_after>import json
import logging

import tornado.httpclient
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.netutil

from tornado.gen import coroutine, Return
from options import options

import tornado.log

import internal
import access
import discover
import admin
import jsonrpc
import handler
import traceback
import time
import signal

# just included to define things
import options.default as opts_

from . import retry, ElapsedTime

MAX_WAIT_SECONDS_BEFORE_SHUTDOWN = 5

SERVICE_VERSION = "0.1"
tornado.netutil.Resolver.configure('tornado.netutil.ThreadedResolver')

class ServerError(RuntimeError):
    def __init__(self, message, *args, **kwargs):
        super(ServerError, self).__init__(*args, **kwargs)
        self.message = message

    def __str__(self):
        return self.message

class Server(tornado.web.Application):
    def __init__(self):

        self.http_server = None

        self.api_version = SERVICE_VERSION

        handlers = self.get_handlers() or []

        admin_actions = self.get_admin()
        if admin_actions:
            self.actions = admin.AdminActions(admin_actions)
            handlers.extend([
                (r"/@admin", admin.AdminHandler),
                (r"/@admin_upload", admin.AdminUploadHandler)
            ])
        else:
            self.actions = None

        stream_admin_actions = self.get_admin_stream()
        if stream_admin_actions:
            self.stream_actions = admin.AdminActions(stream_admin_actions)
            handlers.append((r"/@stream_admin", admin.AdminWSHandler))
        else:
            self.stream_actions = None

        self.internal_handler = self.get_internal_handler()

        metadata = self.get_metadata()

        if isinstance(metadata, dict):
            self.metadata = self.__load_metadata__(metadata)
            logging.info("Metadata loaded")
            handlers.append((r"/@metadata", admin.AdminMetadataHandler))

        auth_callback = self.get_auth_callback()
        if auth_callback:
            handlers.append((r"/callback", auth_callback))

        if options.serve_static:
            handlers.append((r'/static/(.*)', tornado.web.StaticFileHandler,
                             {'path': 'static', "default_filename": "index.html"}))

        super(Server, self).__init__(
            handlers=handlers, debug=options.debug
        )

        self.token_cache = access.AccessTokenCache()
        self.name = None

        self.internal = None
        self.shutting_down = False
        self.graceful_shutdown = options.graceful_shutdown

        tornado.ioloop.IOLoop.instance().set_blocking_log_threshold(0.5)

    def __load_metadata__(self, data):
        data["version"] = self.api_version
        return data

    @coroutine
    def get_auth_location(self, network):
        result = yield discover.cache.get_service("login", network)
        raise Return(result)

    def get_handlers(self):
        """
        This method is need to be overridden to return a list of tuples: one tuple for each request the
        service can process.

        For example,

        [
            ("/user", handlers.UserHandler)
        ]

        This binds a /user request to a UserHandler (overridden from RequestHandler)

        """
        return []

    def get_auth_callback(self):
        return handler.AuthCallbackHandler

    def get_admin(self):
        """
        This method is need to be overridden to return a dict of classes: AdminController's
        This allows to administrate each service in admin tool.
        Each AdminController corresponds one single action can be done in such tool.
        Please see `AdminController` for more information.
        """
        return {}

    def get_admin_stream(self):
        return {}

    def get_internal_handler(self):
        """
        Object, returned by this method is used handle request from other services across environment.

        To do so, they may do yield internal.request("<service_id>", "<command_name>", <arguments>)
        In that case, a @coroutine method <command_name> would be called on that object with <arguments>

        for example, for such internal handler:

        class InternalHandler():
            @coroutine
            def hello(name):
                ... do some work ...
                raise Return({"hello, your name is": name})

        a call would be:

        result = yield internal.request("<service_id>", "hello", name="john")

        a result would be:

         {"hello, your name is": "john"}

        """

        return None

    def get_metadata(self):
        """
        Returns a location of metadata file.
        This file is used in admin tool to acquire description of the service.
        """
        return None

    @coroutine
    def get_gamespace(self, gamespace_name):
        """
        :returns a gamespace ID from given name.
        """
        internal_ = internal.Internal()

        @retry(operation="Acquiring gamespace", max=5, delay=5)
        @coroutine
        def do_try():
            response = yield internal_.request(
                "login",
                "get_gamespace",
                name=gamespace_name)
            raise Return(str(response["id"]))

        raise Return((yield do_try()))

    @coroutine
    def get_gamespace_list(self):
        """
        :returns: a list of available gamespaces across the environment.
        """
        internal_ = internal.Internal()

        @retry(operation="Acquiring gamespace list", max=5, delay=5)
        @coroutine
        def do_try():
            response = yield internal_.request("login", "get_gamespaces")
            raise Return(response)

        raise Return((yield do_try()))

    def init_discovery(self):
        discover.init()

    # noinspection PyMethodMayBeStatic
    def get_models(self):
        """
        Returns a list of models in the application
        """
        return []

    @coroutine
    def started(self):
        self.name = options.name

        self.token_cache.load()
        self.init_discovery()
        self.internal = internal.Internal()

        if self.internal_handler:
            yield self.internal.listen(self.name, self.__on_internal_receive__)

        for model in self.get_models():
            if hasattr(model, "started"):
                yield model.started()

        logging.info("Service '%s' started.", self.name)

    def run(self):
        signal.signal(signal.SIGTERM, self.__sig_handler__)
        signal.signal(signal.SIGINT, self.__sig_handler__)

        self.http_server = tornado.httpserver.HTTPServer(self, xheaders=True)

        listen_uri = options.listen
        listen_group = listen_uri.split(":")

        if len(listen_group) < 2:
            raise ServerError("Failed to listen on " + listen_uri + ": bad format")

        kind, address = listen_group[0], listen_group[1]

        def listen_port(port):
            self.http_server.listen(int(port), "127.0.0.1")

        def listen_unix(sockets):
            for sock in sockets.split(":"):
                logging.info("Listening for socket: " + sock)
                unix_socket = tornado.netutil.bind_unix_socket(sock, mode=0o777)
                self.http_server.add_socket(unix_socket)

        kinds = {
            "port": listen_port,
            "unix": listen_unix
        }

        if kind not in kinds:
            raise ServerError("Failed to listen on " + listen_uri + ": unsupported kind")

        listen_method = kinds[kind]
        listen_method(address)

        logging.info("Listening '{0}' on '{1}'".format(kind, address))
        logging.info("Host is '{0}'".format(self.get_host()))

        tornado.ioloop.IOLoop.instance().add_callback(self.started)
        tornado.ioloop.IOLoop.instance().start()

    # noinspection PyMethodMayBeStatic
    def get_host(self):
        return options.host

    @coroutine
    def __on_internal_receive__(self, context, method, *args, **kwargs):
        if hasattr(self.internal_handler, method):

            if not isinstance(method, (str, unicode)):
                raise jsonrpc.JsonRPCError(-32600, "Method is not a string")

            if method.startswith("_"):
                raise jsonrpc.JsonRPCError(-32600, "No such method")

            timer = ElapsedTime("incoming request: {0}".format(method))

            # noinspection PyBroadException
            try:
                result = yield getattr(self.internal_handler, method)(*args, **kwargs)
            except internal.InternalError as e:
                raise jsonrpc.JsonRPCError(e.code, e.body, "code: " + str(e.code))
            except Exception:
                raise jsonrpc.JsonRPCError(-32603, traceback.format_exc())
            else:
                raise Return(result)
            finally:
                timer.done()

        else:
            raise jsonrpc.JsonRPCError(-32600, "No such method")

    def __sig_handler__(self, sig, frame):
        if self.shutting_down:
            return

        logging.warning('Caught signal: %s', sig)
        tornado.ioloop.IOLoop.instance().add_callback(self.shutdown)

    def shutdown(self):
        self.shutting_down = True

        logging.info('Stopping server!')
        self.http_server.stop()

        if self.graceful_shutdown:

            for model in self.get_models():
                if hasattr(model, "stopped"):
                    tornado.ioloop.IOLoop.instance().add_callback(model.stopped)

            logging.info('Will shutdown in %s seconds ...', MAX_WAIT_SECONDS_BEFORE_SHUTDOWN)
            io_loop = tornado.ioloop.IOLoop.instance()

            deadline = time.time() + MAX_WAIT_SECONDS_BEFORE_SHUTDOWN

            # noinspection PyProtectedMember
            def stop_loop():
                now = time.time()
                if now < deadline and (io_loop._callbacks or io_loop._timeouts):
                    io_loop.add_timeout(now + 1, stop_loop)
                else:
                    io_loop.stop()
                    logging.info('Stopped!')
            stop_loop()

        else:
            tornado.ioloop.IOLoop.instance().stop()
            logging.info('Stopped!')

def init():
    import options

    options.parse_command_line()
    options.parse_env()

    return options

def start(server_cls):
    application = server_cls()
    application.run()
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import print_function
from __future__ import division
from __future__ import unicode_literals

import time
import glob
import threading

try:
    from . import Tools
    from . import pyserial
    from . import Messages
    from .Preferences import Preferences
except:
    from libs import Tools
    from libs import pyserial
    from libs import Messages
    from libs.Preferences import Preferences

if Tools.getOsName() == 'windows':
    if Tools.getPythonVersion() < 3:
        import _winreg as winreg
    else:
        import winreg

@Tools.singleton
class SerialListener(object):
    """
    Constantly checks if a port has been connected or disconnected
    """

    def __init__(self, func=None):
        self.func = func
        self.serial_list = []
        self.is_alive = False

    def start(self):
        if not self.is_alive:
            self.is_alive = True
            listener_thread = threading.Thread(target=self.update)
            listener_thread.start()

    def update(self):
        while self.is_alive:
            pre_serial_list = self.serial_list
            self.serial_list = listSerialPorts()
            if self.serial_list != pre_serial_list:
                if self.func:
                    self.func()
            time.sleep(1)

    def stop(self):
        self.is_alive = False

serials_in_use = []
serial_monitor_dict = {}

class SerialMonitor(object):
    """
    Handle the messages sended and received from/to the serial monitor
    """

    def __init__(self, serial_port, console=None):
        super(SerialMonitor, self).__init__()
        self.port = serial_port
        self.serial = pyserial.Serial()
        self.serial.port = serial_port
        self.queue = Messages.MessageQueue(console)
        self.Preferences = Preferences()
        self.is_alive = False

    def isRunning(self):
        return self.is_alive

    def start(self):
        self.queue.startPrint()
        if not self.is_alive:
            baudrate = self.Preferences.get('baudrate', 9600)
            self.serial.baudrate = baudrate
            if isSerialAvailable(self.port):
                self.serial.open()
                self.is_alive = True
                monitor_thread = threading.Thread(target=self.receive)
                monitor_thread.start()
            else:
                msg = 'Serial port {0} already in use. '
                msg += 'Try stopping any programs that may be using it.\\n'
                self.queue.put(msg, self.port)
                self.stop()

    def stop(self):
        self.is_alive = False
        self.queue.stopPrint()

    def receive(self):
        length_before = 0
        while self.is_alive:
            number = self.serial.inWaiting()
            if number > 0:
                in_text = self.serial.read(number)
                length_in_text = len(in_text)
                in_text = convertMode(in_text, length_before)
                self.queue.put(in_text)
                length_before += length_in_text
                length_before %= 16
            time.sleep(0.01)
        self.serial.close()

    def send(self, out_text):
        line_ending = self.Preferences.get('line_ending', '\n')
        out_text += line_ending
        self.queue.put('\\n[SENDED] {0}\\n', out_text)
        out_text = out_text.encode('utf-8', 'replace')
        self.serial.write(out_text)

def convertMode(in_text, str_len=0):
    """
    Convert a text in differents formats (ASCII,HEX)

    Arguments:
        in_text {string}
            Text to convert

    Keyword Arguments:
        str_len {int}
            leng of the in_text string (default: {0})

    Returns:
        [string] -- Converted string
    """
    text = u''
    display_mode = Preferences().get('display_mode', 'Text')
    if display_mode == 'Ascii':
        for character in in_text:
            text += chr(character)
    elif display_mode == 'Hex':
        for (index, character) in enumerate(in_text):
            text += u'%02X ' % character
            if (index + str_len + 1) % 8 == 0:
                text += '\t'
            if (index + str_len + 1) % 16 == 0:
                text += '\n'
    else:
        text = in_text.decode('utf-8', 'replace')
    return text

def isSerialAvailable(serial_port):
    """
    Check if the serial port is available

    Arguments:
        serial_port {string}
            name of the port to check

    Returns:
        [bool] -- true or false when the port is available or not
    """
    state = False
    serial = pyserial.Serial()
    serial.port = serial_port
    try:
        serial.open()
    except pyserial.serialutil.SerialException:
        pass
    except UnicodeDecodeError:
        pass
    else:
        if serial.isOpen():
            state = True
            serial.close()
    return state

def listSerialPorts():
    """
    List all the serial ports availables in the diffents O.S
    """
    os_name = Tools.getOsName()
    if os_name == "windows":
        serial_ports = listWinSerialPorts()
    elif os_name == 'osx':
        serial_ports = listOsxSerialPorts()
    else:
        serial_ports = listLinuxSerialPorts()
    serial_ports.sort()
    return serial_ports

def listWinSerialPorts():
    """
    List all the serial ports availables in Windows
    """
    serial_ports = []
    has_ports = False
    path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
    try:
        reg = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path,)
        has_ports = True
    except WindowsError:
        pass
    if has_ports:
        for i in range(128):
            try:
                name, value, type = winreg.EnumValue(reg, i)
            except WindowsError:
                pass
            else:
                serial_ports.append(value)
    return serial_ports

def listOsxSerialPorts():
    """
    List all the serial ports availables in OS X
    """
    serial_ports = []
    dev_path = '/dev/'
    dev_names = ['tty.*', 'cu.*']
    for dev_name in dev_names:
        pattern = dev_path + dev_name
        serial_ports += glob.glob(pattern)
    return serial_ports

def listLinuxSerialPorts():
    """
    List all the serial ports availables in Linux
    """
    serial_ports = []
    dev_path = '/dev/'
    dev_names = ['ttyACM*', 'ttyUSB*']
    for dev_name in dev_names:
        pattern = dev_path + dev_name
        serial_ports += glob.glob(pattern)
    return serial_ports
<commit_msg>Removing CR and NULL tag in text mode<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import print_function
from __future__ import division
from __future__ import unicode_literals

import time
import glob
import threading

try:
    from . import Tools
    from . import pyserial
    from . import Messages
    from .Preferences import Preferences
except:
    from libs import Tools
    from libs import pyserial
    from libs import Messages
    from libs.Preferences import Preferences

if Tools.getOsName() == 'windows':
    if Tools.getPythonVersion() < 3:
        import _winreg as winreg
    else:
        import winreg

@Tools.singleton
class SerialListener(object):
    """
    Constantly checks if a port has been connected or disconnected
    """

    def __init__(self, func=None):
        self.func = func
        self.serial_list = []
        self.is_alive = False

    def start(self):
        if not self.is_alive:
            self.is_alive = True
            listener_thread = threading.Thread(target=self.update)
            listener_thread.start()

    def update(self):
        while self.is_alive:
            pre_serial_list = self.serial_list
            self.serial_list = listSerialPorts()
            if self.serial_list != pre_serial_list:
                if self.func:
                    self.func()
            time.sleep(1)

    def stop(self):
        self.is_alive = False

serials_in_use = []
serial_monitor_dict = {}

class SerialMonitor(object):
    """
    Handle the messages sended and received from/to the serial monitor
    """

    def __init__(self, serial_port, console=None):
        super(SerialMonitor, self).__init__()
        self.port = serial_port
        self.serial = pyserial.Serial()
        self.serial.port = serial_port
        self.queue = Messages.MessageQueue(console)
        self.Preferences = Preferences()
        self.is_alive = False

    def isRunning(self):
        return self.is_alive

    def start(self):
        self.queue.startPrint()
        if not self.is_alive:
            baudrate = self.Preferences.get('baudrate', 9600)
            self.serial.baudrate = baudrate
            if isSerialAvailable(self.port):
                self.serial.open()
                self.is_alive = True
                monitor_thread = threading.Thread(target=self.receive)
                monitor_thread.start()
            else:
                msg = 'Serial port {0} already in use. '
                msg += 'Try stopping any programs that may be using it.\\n'
                self.queue.put(msg, self.port)
                self.stop()

    def stop(self):
        self.is_alive = False
        self.queue.stopPrint()

    def receive(self):
        length_before = 0
        while self.is_alive:
            number = self.serial.inWaiting()
            if number > 0:
                in_text = self.serial.read(number)
                length_in_text = len(in_text)
                in_text = convertMode(in_text, length_before)
                self.queue.put(in_text)
                length_before += length_in_text
                length_before %= 16
            time.sleep(0.01)
        self.serial.close()

    def send(self, out_text):
        line_ending = self.Preferences.get('line_ending', '\n')
        out_text += line_ending
        self.queue.put('\\n[SENDED] {0}\\n', out_text)
        out_text = out_text.encode('utf-8', 'replace')
        self.serial.write(out_text)

def convertMode(in_text, str_len=0):
    """
    Convert a text in differents formats (ASCII,HEX)

    Arguments:
        in_text {string}
            Text to convert

    Keyword Arguments:
        str_len {int}
            leng of the in_text string (default: {0})

    Returns:
        [string] -- Converted string
    """
    text = u''
    display_mode = Preferences().get('display_mode', 'Text')
    if display_mode == 'Ascii':
        for character in in_text:
            text += chr(character)
    elif display_mode == 'Hex':
        for (index, character) in enumerate(in_text):
            text += u'%02X ' % character
            if (index + str_len + 1) % 8 == 0:
                text += '\t'
            if (index + str_len + 1) % 16 == 0:
                text += '\n'
    else:
        text = in_text.decode('utf-8', 'replace')
        text = text.replace('\r', '').replace('NULL', '')
    return text

def isSerialAvailable(serial_port):
    """
    Check if the serial port is available

    Arguments:
        serial_port {string}
            name of the port to check

    Returns:
        [bool] -- true or false when the port is available or not
    """
    state = False
    serial = pyserial.Serial()
    serial.port = serial_port
    try:
        serial.open()
    except pyserial.serialutil.SerialException:
        pass
    except UnicodeDecodeError:
        pass
    else:
        if serial.isOpen():
            state = True
            serial.close()
    return state

def listSerialPorts():
    """
    List all the serial ports availables in the diffents O.S
    """
    os_name = Tools.getOsName()
    if os_name == "windows":
        serial_ports = listWinSerialPorts()
    elif os_name == 'osx':
        serial_ports = listOsxSerialPorts()
    else:
        serial_ports = listLinuxSerialPorts()
    serial_ports.sort()
    return serial_ports

def listWinSerialPorts():
    """
    List all the serial ports availables in Windows
    """
    serial_ports = []
    has_ports = False
    path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
    try:
        reg = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path,)
        has_ports = True
    except WindowsError:
        pass
    if has_ports:
        for i in range(128):
            try:
                name, value, type = winreg.EnumValue(reg, i)
            except WindowsError:
                pass
            else:
                serial_ports.append(value)
    return serial_ports

def listOsxSerialPorts():
    """
    List all the serial ports availables in OS X
    """
    serial_ports = []
    dev_path = '/dev/'
    dev_names = ['tty.*', 'cu.*']
    for dev_name in dev_names:
        pattern = dev_path + dev_name
        serial_ports += glob.glob(pattern)
    return serial_ports

def listLinuxSerialPorts():
    """
    List all the serial ports availables in Linux
    """
    serial_ports = []
    dev_path = '/dev/'
    dev_names = ['ttyACM*', 'ttyUSB*']
    for dev_name in dev_names:
        pattern = dev_path + dev_name
        serial_ports += glob.glob(pattern)
    return serial_ports
<|endoftext|>


<commit_before># Check the basic discovery process, including a sub-suite.
#
# RUN: %{lit} %{inputs}/discovery \
# RUN:   -j 1 --debug --no-execute --show-suites -v > %t.out 2> %t.err
# RUN: FileCheck --check-prefix=CHECK-BASIC-OUT < %t.out %s
# RUN: FileCheck --check-prefix=CHECK-BASIC-ERR < %t.err %s
#
# CHECK-BASIC-ERR: loading suite config '{{.*}}/tests/Inputs/discovery/lit.cfg'
# CHECK-BASIC-ERR: loading local config '{{.*}}/tests/Inputs/discovery/subdir/lit.local.cfg'
# CHECK-BASIC-ERR: loading suite config '{{.*}}/tests/Inputs/discovery/subsuite/lit.cfg'
#
# CHECK-BASIC-OUT: -- Test Suites --
# CHECK-BASIC-OUT:   sub-suite - 2 tests
# CHECK-BASIC-OUT:     Source Root:
# CHECK-BASIC-OUT:     Exec Root  :
# CHECK-BASIC-OUT:   top-level-suite - 3 tests
# CHECK-BASIC-OUT:     Source Root:
# CHECK-BASIC-OUT:     Exec Root  :
#
# CHECK-BASIC-OUT: -- Testing: 5 tests, 1 threads --
# CHECK-BASIC-OUT: PASS: sub-suite :: test-one
# CHECK-BASIC-OUT: PASS: sub-suite :: test-two
# CHECK-BASIC-OUT: PASS: top-level-suite :: subdir/test-three
# CHECK-BASIC-OUT: PASS: top-level-suite :: test-one
# CHECK-BASIC-OUT: PASS: top-level-suite :: test-two
<commit_msg>lit: Add a test for discovery when exact test names are given.<commit_after># Check the basic discovery process, including a sub-suite.
#
# RUN: %{lit} %{inputs}/discovery \
# RUN:   -j 1 --debug --no-execute --show-suites -v > %t.out 2> %t.err
# RUN: FileCheck --check-prefix=CHECK-BASIC-OUT < %t.out %s
# RUN: FileCheck --check-prefix=CHECK-BASIC-ERR < %t.err %s
#
# CHECK-BASIC-ERR: loading suite config '{{.*}}/tests/Inputs/discovery/lit.cfg'
# CHECK-BASIC-ERR: loading local config '{{.*}}/tests/Inputs/discovery/subdir/lit.local.cfg'
# CHECK-BASIC-ERR: loading suite config '{{.*}}/tests/Inputs/discovery/subsuite/lit.cfg'
#
# CHECK-BASIC-OUT: -- Test Suites --
# CHECK-BASIC-OUT:   sub-suite - 2 tests
# CHECK-BASIC-OUT:     Source Root:
# CHECK-BASIC-OUT:     Exec Root  :
# CHECK-BASIC-OUT:   top-level-suite - 3 tests
# CHECK-BASIC-OUT:     Source Root:
# CHECK-BASIC-OUT:     Exec Root  :
#
# CHECK-BASIC-OUT: -- Testing: 5 tests, 1 threads --
# CHECK-BASIC-OUT: PASS: sub-suite :: test-one
# CHECK-BASIC-OUT: PASS: sub-suite :: test-two
# CHECK-BASIC-OUT: PASS: top-level-suite :: subdir/test-three
# CHECK-BASIC-OUT: PASS: top-level-suite :: test-one
# CHECK-BASIC-OUT: PASS: top-level-suite :: test-two

# Check discovery when exact test names are given.
#
# RUN: %{lit} \
# RUN:     %{inputs}/discovery/subdir/test-three.py \
# RUN:     %{inputs}/discovery/subsuite/test-one.txt \
# RUN:   -j 1 --no-execute --show-suites -v > %t.out
# RUN: FileCheck --check-prefix=CHECK-EXACT-TEST < %t.out %s
#
# CHECK-EXACT-TEST: -- Testing: 2 tests, 1 threads --
# CHECK-EXACT-TEST: PASS: sub-suite :: test-one
# CHECK-EXACT-TEST: PASS: top-level-suite :: subdir/test-three

<|endoftext|>


<commit_before>try:
    from src.base_classes import SQLModule
except ImportError:
    from base_classes import SQLModule

class Company(SQLModule):
    def __init__(self, uid="", name="", address="", website="", phone=""):
        super().__init__()
        self.uid = uid
        self.name = name
        self.address = address
        self.website = website
        self.phone = phone

    def get_all_companies(self):
        if not self.db:
            self.init_db()

        query = self.db.con.execute("""
        SELECT * FROM company ORDER BY id;
        """)

        return [Company(*item) for item in query]

    def get_a_company(self, uid):
        assert isinstance(uid, int)
        if not hasattr(self, "db"):
            self.init_db()

        query = self.db.con.execute("""
        SELECT * FROM company WHERE (id=?) ORDER BY id;
        """, (uid,))

        return [Company(*data) for data in query]

    def __str__(self):
        return """
        uid: {}
        name: {}
        address: {}
        website: {}
        phone: {}""".format(self.uid, self.name, self.address, self.website, self.phone)

if __name__ == "__main__":
    test = Company(name="Crazcalm")
    test.get_all_companies()
    print(test.get_a_company(1)[0])
<commit_msg>reformated some of the sql code<commit_after>try:
    from src.base_classes import SQLModule
except ImportError:
    from base_classes import SQLModule

class Company(SQLModule):
    def __init__(self, uid="", name="", address="", website="", phone=""):
        super().__init__()
        self.uid = uid
        self.name = name
        self.address = address
        self.website = website
        self.phone = phone

    def get_all_companies(self):
        if not self.db:
            self.init_db()

        query = """
        SELECT id, name, address, website, phone FROM company ORDER BY id;
        """

        data = self.db.con.execute(query)

        return [Company(*item) for item in data]

    def get_a_company(self, uid):
        assert isinstance(uid, int)
        if not hasattr(self, "db"):
            self.init_db()

        query = """
        SELECT id, name, address, website, phone FROM company WHERE (id=?) ORDER BY id
        """

        data = self.db.con.execute(query, (uid,))

        return [Company(*item) for item in data]

    def __str__(self):
        return """
        uid: {}
        name: {}
        address: {}
        website: {}
        phone: {}""".format(self.uid, self.name, self.address, self.website, self.phone)

if __name__ == "__main__":
    test = Company(name="Crazcalm")
    test.get_all_companies()
    print(test.get_a_company(1)[0])
<|endoftext|>


<commit_before>#!/usr/bin/env python3
#
# Copyright (C) 2020 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import os
import jinja2

from sys import exit
from copy import deepcopy
from subprocess import check_call, CalledProcessError

from vyos.config import Config
from vyos.configdict import list_diff
from vyos.ifconfig import Interface
from vyos import ConfigError

config_file = r'/etc/iproute2/rt_tables.d/vyos-vrf.conf'

# Please be careful if you edit the template.
config_tmpl = """
### Autogenerated by vrf.py ###
#
# Routing table ID to name mapping reference

# id       vrf name         comment
{% for vrf in vrf_add -%}
{{ "%-10s" | format(vrf.table) }} {{ "%-16s" | format(vrf.name) }} # {{ vrf.description }}
{% endfor -%}

"""

default_config_data = {
    'bind_to_all': 0,
    'deleted': False,
    'vrf_add': [],
    'vrf_existing': [],
    'vrf_remove': []
}

def _cmd(command):
    """
    Run any arbitrary command on the system
    """
    try:
        check_call(command.split())
    except CalledProcessError as e:
        raise ConfigError(f'Error changing VRF: {e}')

def interfaces_with_vrf(match):
    matched = []
    config = Config()
    section = config.get_config_dict('interfaces')
    for type in section:
        interfaces = section[type]
        for name in interfaces:
            interface = interfaces[name]
            if 'vrf' in interface:
                v = interface.get('vrf', '')
                if v == match:
                    matched.append(name)
    return matched

def get_config():
    conf = Config()
    vrf_config = deepcopy(default_config_data)

    cfg_base = ['vrf']
    if not conf.exists(cfg_base):
        # get all currently effetive VRFs and mark them for deletion
        vrf_config['vrf_remove'] = conf.list_effective_nodes(cfg_base + ['name'])
    else:

        # Should services be allowed to bind to all VRFs?
        if conf.exists(['bind-to-all']):
            vrf_config['bind_to_all'] = 1

        # Determine vrf interfaces (currently effective) - to determine which
        # vrf interface is no longer present and needs to be removed
        eff_vrf = conf.list_effective_nodes(cfg_base + ['name'])
        act_vrf = conf.list_nodes(cfg_base + ['name'])
        vrf_config['vrf_remove'] = list_diff(eff_vrf, act_vrf)

        # read in individual VRF definition and build up
        # configuration
        for name in conf.list_nodes(cfg_base + ['name']):
            vrf_inst = {
                'description' : '',
                'members': [],
                'name' : name,
                'table' : '',
                'table_mod': False
            }
            conf.set_level(cfg_base + ['name', name])

            if conf.exists(['table']):
                # VRF table can't be changed on demand, thus we need to read in the
                # current and the effective routing table number
                act_table = conf.return_value(['table'])
                eff_table = conf.return_effective_value(['table'])
                vrf_inst['table'] = act_table
                if eff_table and eff_table != act_table:
                    vrf_inst['table_mod'] = True

            if conf.exists(['description']):
                vrf_inst['description'] = conf.return_value(['description'])

            # find member interfaces of this particulat VRF
            vrf_inst['members'] = interfaces_with_vrf(name)

            # append individual VRF configuration to global configuration list
            vrf_config['vrf_add'].append(vrf_inst)

    # check VRFs which need to be removed as they are not allowed to have
    # interfaces attached
    tmp = []
    for name in vrf_config['vrf_remove']:
        vrf_inst = {
            'members': [],
            'name' : name,
        }

        # find member interfaces of this particulat VRF
        vrf_inst['members'] = interfaces_with_vrf(name)

        # append individual VRF configuration to temporary configuration list
        tmp.append(vrf_inst)

    # replace values in vrf_remove with list of dictionaries
    # as we need it in verify() - we can't delete a VRF with members attached
    vrf_config['vrf_remove'] = tmp
    return vrf_config

def verify(vrf_config):
    # ensure VRF is not assigned to any interface
    for vrf in vrf_config['vrf_remove']:
        if len(vrf['members']) > 0:
            raise ConfigError('VRF "{}" can not be deleted as it has active members'.format(vrf['name']))

    for vrf in vrf_config['vrf_add']:
        # table id is mandatory
        if not vrf['table']:
            raise ConfigError('VRF "{}": table id is mandatory'.format(vrf['name']))

        # routing table id can't be changed - OS restriction
        if vrf['table_mod']:
            raise ConfigError('VRF "{}": modification of table id is not possible'.format(vrf['name']))

    # add test to see if routing table already exists or not?

    return None

def generate(vrf_config):
    tmpl = jinja2.Template(config_tmpl)
    config_text = tmpl.render(vrf_config)
    with open(config_file, 'w') as f:
        f.write(config_text)

    return None

def apply(vrf_config):
    # https://github.com/torvalds/linux/blob/master/Documentation/networking/vrf.txt

    # set the default VRF global behaviour
    bind_all = vrf_config['bind_to_all']
    _cmd(f'sysctl -wq net.ipv4.tcp_l3mdev_accept={bind_all}')
    _cmd(f'sysctl -wq net.ipv4.udp_l3mdev_accept={bind_all}')

    for vrf_name in vrf_config['vrf_remove']:
        if os.path.isdir(f'/sys/class/net/{vrf_name}'):
            _cmd(f'ip link delete dev {vrf_name}')

    for vrf in vrf_config['vrf_add']:
        name = vrf['name']
        table = vrf['table']

        if not os.path.isdir(f'/sys/class/net/{name}'):
            # For each VRF apart from your default context create a VRF
            # interface with a separate routing table
            _cmd(f'ip link add {name} type vrf table {table}')
            # Start VRf
            _cmd(f'ip link set dev {name} up')
            # The kernel Documentation/networking/vrf.txt also recommends
            # adding unreachable routes to the VRF routing tables so that routes
            # afterwards are taken.
            _cmd(f'ip -4 route add vrf {name} unreachable default metric 4278198272')
            _cmd(f'ip -6 route add vrf {name} unreachable default metric 4278198272')

        # set VRF description for e.g. SNMP monitoring
        Interface(name).set_alias(vrf['description'])

    # Linux routing uses rules to find tables - routing targets are then
    # looked up in those tables. If the lookup got a matching route, the
    # process ends.
    #
    # TL;DR; first table with a matching entry wins!
    #
    # You can see your routing table lookup rules using "ip rule", sadly the
    # local lookup is hit before any VRF lookup. Pinging an addresses from the
    # VRF will usually find a hit in the local table, and never reach the VRF
    # routing table - this is usually not what you want. Thus we will
    # re-arrange the tables and move the local lookup furhter down once VRFs
    # are enabled.

    # set "normal" non VRF table lookups
    add_pref = '0'
    del_pref = '32765'

    # Lookup table is adjusted if we are in VRF mode
    if vrf_config['vrf_add']:
        add_pref = '32765'
        del_pref = '0'

    # Configure table lookups
    _cmd(f'ip -4 rule add pref {add_pref} table local')
    _cmd(f'ip -4 rule del pref {del_pref}')
    _cmd(f'ip -6 rule add pref {add_pref} table local')
    _cmd(f'ip -6 rule del pref {del_pref}')

    return None

if __name__ == '__main__':
    try:
        c = get_config()
        verify(c)
        generate(c)
        apply(c)
    except ConfigError as e:
        print(e)
        exit(1)
<commit_msg>vrf: T31: routing table IDs must be unique<commit_after>#!/usr/bin/env python3
#
# Copyright (C) 2020 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import os
import jinja2

from sys import exit
from copy import deepcopy
from subprocess import check_call, CalledProcessError

from vyos.config import Config
from vyos.configdict import list_diff
from vyos.ifconfig import Interface
from vyos import ConfigError

config_file = r'/etc/iproute2/rt_tables.d/vyos-vrf.conf'

# Please be careful if you edit the template.
config_tmpl = """
### Autogenerated by vrf.py ###
#
# Routing table ID to name mapping reference

# id       vrf name         comment
{% for vrf in vrf_add -%}
{{ "%-10s" | format(vrf.table) }} {{ "%-16s" | format(vrf.name) }} # {{ vrf.description }}
{% endfor -%}

"""

default_config_data = {
    'bind_to_all': 0,
    'deleted': False,
    'vrf_add': [],
    'vrf_existing': [],
    'vrf_remove': []
}

def _cmd(command):
    """
    Run any arbitrary command on the system
    """
    try:
        check_call(command.split())
    except CalledProcessError as e:
        raise ConfigError(f'Error changing VRF: {e}')

def interfaces_with_vrf(match):
    matched = []
    config = Config()
    section = config.get_config_dict('interfaces')
    for type in section:
        interfaces = section[type]
        for name in interfaces:
            interface = interfaces[name]
            if 'vrf' in interface:
                v = interface.get('vrf', '')
                if v == match:
                    matched.append(name)
    return matched

def get_config():
    conf = Config()
    vrf_config = deepcopy(default_config_data)

    cfg_base = ['vrf']
    if not conf.exists(cfg_base):
        # get all currently effetive VRFs and mark them for deletion
        vrf_config['vrf_remove'] = conf.list_effective_nodes(cfg_base + ['name'])
    else:

        # Should services be allowed to bind to all VRFs?
        if conf.exists(['bind-to-all']):
            vrf_config['bind_to_all'] = 1

        # Determine vrf interfaces (currently effective) - to determine which
        # vrf interface is no longer present and needs to be removed
        eff_vrf = conf.list_effective_nodes(cfg_base + ['name'])
        act_vrf = conf.list_nodes(cfg_base + ['name'])
        vrf_config['vrf_remove'] = list_diff(eff_vrf, act_vrf)

        # read in individual VRF definition and build up
        # configuration
        for name in conf.list_nodes(cfg_base + ['name']):
            vrf_inst = {
                'description' : '',
                'members': [],
                'name' : name,
                'table' : '',
                'table_mod': False
            }
            conf.set_level(cfg_base + ['name', name])

            if conf.exists(['table']):
                # VRF table can't be changed on demand, thus we need to read in the
                # current and the effective routing table number
                act_table = conf.return_value(['table'])
                eff_table = conf.return_effective_value(['table'])
                vrf_inst['table'] = act_table
                if eff_table and eff_table != act_table:
                    vrf_inst['table_mod'] = True

            if conf.exists(['description']):
                vrf_inst['description'] = conf.return_value(['description'])

            # find member interfaces of this particulat VRF
            vrf_inst['members'] = interfaces_with_vrf(name)

            # append individual VRF configuration to global configuration list
            vrf_config['vrf_add'].append(vrf_inst)

    # check VRFs which need to be removed as they are not allowed to have
    # interfaces attached
    tmp = []
    for name in vrf_config['vrf_remove']:
        vrf_inst = {
            'members': [],
            'name' : name,
        }

        # find member interfaces of this particulat VRF
        vrf_inst['members'] = interfaces_with_vrf(name)

        # append individual VRF configuration to temporary configuration list
        tmp.append(vrf_inst)

    # replace values in vrf_remove with list of dictionaries
    # as we need it in verify() - we can't delete a VRF with members attached
    vrf_config['vrf_remove'] = tmp
    return vrf_config

def verify(vrf_config):
    # ensure VRF is not assigned to any interface
    for vrf in vrf_config['vrf_remove']:
        if len(vrf['members']) > 0:
            raise ConfigError('VRF "{}" can not be deleted as it has active members'.format(vrf['name']))

    table_ids = []
    for vrf in vrf_config['vrf_add']:
        # table id is mandatory
        if not vrf['table']:
            raise ConfigError('VRF "{}" table id is mandatory'.format(vrf['name']))

        # routing table id can't be changed - OS restriction
        if vrf['table_mod']:
            raise ConfigError('VRF "{}" modification of table id is not possible'.format(vrf['name']))

        # VRf routing table ID must be unique on the system
        if vrf['table'] in table_ids:
            raise ConfigError('VRF "{}" routing table id "{}" not unique'.format(vrf['name'], vrf['table']))
        table_ids.append(vrf['table'])

    return None

def generate(vrf_config):
    tmpl = jinja2.Template(config_tmpl)
    config_text = tmpl.render(vrf_config)
    with open(config_file, 'w') as f:
        f.write(config_text)

    return None

def apply(vrf_config):
    # https://github.com/torvalds/linux/blob/master/Documentation/networking/vrf.txt

    # set the default VRF global behaviour
    bind_all = vrf_config['bind_to_all']
    _cmd(f'sysctl -wq net.ipv4.tcp_l3mdev_accept={bind_all}')
    _cmd(f'sysctl -wq net.ipv4.udp_l3mdev_accept={bind_all}')

    for vrf_name in vrf_config['vrf_remove']:
        if os.path.isdir(f'/sys/class/net/{vrf_name}'):
            _cmd(f'ip link delete dev {vrf_name}')

    for vrf in vrf_config['vrf_add']:
        name = vrf['name']
        table = vrf['table']

        if not os.path.isdir(f'/sys/class/net/{name}'):
            # For each VRF apart from your default context create a VRF
            # interface with a separate routing table
            _cmd(f'ip link add {name} type vrf table {table}')
            # Start VRf
            _cmd(f'ip link set dev {name} up')
            # The kernel Documentation/networking/vrf.txt also recommends
            # adding unreachable routes to the VRF routing tables so that routes
            # afterwards are taken.
            _cmd(f'ip -4 route add vrf {name} unreachable default metric 4278198272')
            _cmd(f'ip -6 route add vrf {name} unreachable default metric 4278198272')

        # set VRF description for e.g. SNMP monitoring
        Interface(name).set_alias(vrf['description'])

    # Linux routing uses rules to find tables - routing targets are then
    # looked up in those tables. If the lookup got a matching route, the
    # process ends.
    #
    # TL;DR; first table with a matching entry wins!
    #
    # You can see your routing table lookup rules using "ip rule", sadly the
    # local lookup is hit before any VRF lookup. Pinging an addresses from the
    # VRF will usually find a hit in the local table, and never reach the VRF
    # routing table - this is usually not what you want. Thus we will
    # re-arrange the tables and move the local lookup furhter down once VRFs
    # are enabled.

    # set "normal" non VRF table lookups
    add_pref = '0'
    del_pref = '32765'

    # Lookup table is adjusted if we are in VRF mode
    if vrf_config['vrf_add']:
        add_pref = '32765'
        del_pref = '0'

    # Configure table lookups
    _cmd(f'ip -4 rule add pref {add_pref} table local')
    _cmd(f'ip -4 rule del pref {del_pref}')
    _cmd(f'ip -6 rule add pref {add_pref} table local')
    _cmd(f'ip -6 rule del pref {del_pref}')

    return None

if __name__ == '__main__':
    try:
        c = get_config()
        verify(c)
        generate(c)
        apply(c)
    except ConfigError as e:
        print(e)
        exit(1)
<|endoftext|>


<commit_before>import json, os
from jsonschema import validate
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw

from hammerhal.text_drawer import TextDrawer
from hammerhal import ConfigLoader
from hammerhal.compilers import CompilerBase
from logging import getLogger
logger = getLogger('hammerhal.compilers.hero_compiler')

class HeroCompiler(CompilerBase):
    compiler_type = "hero"

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    @staticmethod
    def __get_font(fontfamily, size):
        return ImageFont.truetype("fonts/" + fontfamily + ".ttf", size)

    def compile(self):

        base = self.__prepare_base()
        if (not base):
            return None

        self.__print_name(base)
        self.__print_stats(base)
        self.__print_dice_space(base)
        self.__print_weapons(base)
        self.__print_rules(base)

        self.compiled = base
        return self.compiled

    def __prepare_base(self):
        filename = "{directory}{name}.png".format\
        (
            directory=self.sources_directory,
            name="hero_card_base_{n}_weapons".format(n=len(self.raw['weapons'])),
        )
        if (not os.path.isfile(filename)):
            logger.error("Cannot load hero card template with proper number of weapons: {n}".format(n=len(self.raw['weapons'])))
            return None
        base = Image.open(filename)
        if (self.raw.get('image')):
            filename = "{directory}{name}".format\
            (
                directory=ConfigLoader.get_from_config('rawDirectoryRoot'),
                name=self.raw['image'],
            )
            if (not os.path.isfile(filename)):
                logger.error("Cannot load hero image by path: '{path}' - no such file".format(path=self.raw['image']))
                return None
            base = self.insert_image_scaled(base_image=base, region=(0, 0, 1080, 1150), image_path=filename)
        return base

    def __print_name(self, base):
        # TODO: subtitle
        td = TextDrawer(base, font_size=int(285 * self.raw.get('titleFontSizeScale', 1.0)), bold=True)
        td.set_font_direct('BOD_B.TTF')
        td.set_font(capitalization=TextDrawer.CapitalizationModes.SmallCaps, horizontal_alignment=TextDrawer.TextAlignment.Center, vertical_alignment=TextDrawer.TextAlignment.Center)
        td.print_in_region((2400, 0, 0, 240), self.raw['name'], offset_borders=True)
    def __print_stats(self, base):
        td = TextDrawer(base, font_size=110, bold=True, font_family='Constantia', color='white')
        td.print_line((910, 750), "{move}".format(**self.raw['stats']))
        td.print_line((790, 950), "{save}+".format(**self.raw['stats']))
        td.print_line((990, 950), "{agility}+".format(**self.raw['stats']))
    def __print_dice_space(self, base):
        dice_section = self.raw.get('diceSpace', "default")
        if (dice_section == "default"):
            dice_section = ConfigLoader.get_from_config('compilerTypeSpecific/hero/defaultDiceSpace', 'compilers')

        total_dices_count = sum(_dice_type['count'] for _dice_type in dice_section)
        x1 = 1630; x2 = 3260
        _x = x1; _y = 533
        _dx = (x2 - x1) // (total_dices_count - 1)
        for _dice_type in dice_section:
            for i in range(_dice_type['count']):
                self.insert_image_centered(base_image=base, position=(_x, _y), image_path=self.sources_directory + _dice_type['image'])
                _x += _dx
    def __print_weapons(self, base):
        td = TextDrawer(base, font_size=70, color='black', bold=True)
        td.set_font(horizontal_alignment=TextDrawer.TextAlignment.Center, vertical_alignment=TextDrawer.TextAlignment.Center)

        self.insert_table \
        (
            vertical_columns = [ 1340, 2420, 2860, 3070, 3455 ],
            top = 760,
            cell_height = 110,
            data = self.raw['weapons'],

            body_row_template = [ "{name} ({cost}+)", "{range}", "{hit}+", "{damage}" ],
            body_text_drawer = td,
            body_row_interval = [ None, None, 60, 40 ][len(self.raw['weapons'])],
            body_capitalization = TextDrawer.CapitalizationModes.Capitalize,

            header_row = [ "WEAPON ACTIONS", "Range", "Hit", "Damage" ],
            header_text_drawer = td,
            header_row_interval = 70,
            header_capitalization = TextDrawer.CapitalizationModes.Normal,
        )
    def __print_rules(self, base):
        td = TextDrawer(base, font_size=90, color='black')
        td.set_font \
        (
            horizontal_alignment=TextDrawer.TextAlignment.Justify,
            vertical_alignment=TextDrawer.TextAlignment.Center,
            vertical_space_scale=0.15,
            paragraph_vertical_space=50,
        )
        y = 1330; light = True
        gradient_base = self.__get_gradient_image()

        for ability in self.raw['abilities']:
            if (ability.get('cost', None)):
                text = "**{name} ({cost}+)**: {description}".format(**ability)
            else:
                text = "**{name}**: {description}".format(**ability)

            _h = self.__print_rules_block(base, td, y, text, light, gradient_base, dice_space=ability['diceSpace'])
            y += _h
            light = not light

        text_traits = "**TRAITS:** The {name} is **{trait_1}** and **{trait_2}**.".format(name=self.raw['name'], trait_1=self.raw['traits'][0].capitalize(), trait_2=self.raw['traits'][1].capitalize())
        text_renown = "**RENOWN:** {description}".format(description=self.raw['renown'])
        text = text_traits + '\n' + text_renown
        _h = self.__print_rules_block(base, td, y, text, light, gradient_base)
        y += _h
        light = not light

    def __get_gradient_image(self):

        r = 255; g = 255; b = 255; aMin = 0; aMax = 80
        im = Image.new("RGBA", size=(3600, 1), color=(r, g, b, aMin))

        x1 = 250
        x2 = 1200
        x3 = 2400
        x4 = 3400

        for i in range(x1, x2):
            a = int((aMax - aMin) * (i - x1) / (x2 - x1))
            im.putpixel((i, 0), (r, g, b, a))
        for i in range(x2, x3):
            a = aMax
            im.putpixel((i, 0), (r, g, b, a))
        for i in range(x3, x4):
            a = int(aMax - (aMax - aMin) * (i - x3) / (x4 - x3))
            im.putpixel((i, 0), (r, g, b, a))

        return im

    def __print_rules_block(self, base:Image.Image, text_drawer, y:int, text:str, light:bool, gradient_base:Image.Image, dice_space:bool=False):
        x1 = 365; x2 = 2933 if dice_space else 3233
        dy = self.raw.get('rulesSeparatorHeight', 100)

        _, _h = text_drawer.get_text_size((x1, y, x2, 0), text, offset_borders=False)

        if (dice_space):
            _, _h2 = self.get_image_size(self.sources_directory + "dice.png")
            _h = max(_h, _h2)
        _h += dy

        if (light):
            _w = gradient_base.width
            gradient = gradient_base.resize((_w, _h))
            base.paste(gradient, (0, y), gradient)

        if (dice_space):
            _x = 3260; _y = y + _h // 2
            self.insert_image_centered(base, (_x, _y), self.sources_directory + "dice.png")

        # -5 because of not correct intuitive of text while on print
        text_drawer.print_in_region((x1, y - 5, x2, y - 5 + _h), text, offset_borders=False)
        return _h
<commit_msg>Logging added for hero compiler; minor typo fixed<commit_after>import json, os
from jsonschema import validate
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw

from hammerhal.text_drawer import TextDrawer
from hammerhal import ConfigLoader
from hammerhal.compilers import CompilerBase
from logging import getLogger
logger = getLogger('hammerhal.compilers.hero_compiler')

class HeroCompiler(CompilerBase):
    compiler_type = "hero"

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    @staticmethod
    def __get_font(fontfamily, size):
        return ImageFont.truetype("fonts/" + fontfamily + ".ttf", size)

    def compile(self):

        base = self.__prepare_base()
        if (not base):
            return None

        self.__print_name(base)
        self.__print_stats(base)
        self.__print_dice_space(base)
        self.__print_weapons(base)
        self.__print_rules(base)

        self.compiled = base
        logger.info("Hero compiled!")
        return self.compiled

    def __prepare_base(self):
        filename = "{directory}{name}.png".format\
        (
            directory=self.sources_directory,
            name="hero_card_base_{n}_weapons".format(n=len(self.raw['weapons'])),
        )
        if (not os.path.isfile(filename)):
            logger.error("Cannot load hero card template with proper number of weapons: {n}".format(n=len(self.raw['weapons'])))
            return None
        base = Image.open(filename)
        if (self.raw.get('image')):
            filename = "{directory}{name}".format\
            (
                directory=ConfigLoader.get_from_config('rawDirectoryRoot'),
                name=self.raw['image'],
            )
            if (not os.path.isfile(filename)):
                logger.error("Cannot load hero image by path: '{path}' - no such file".format(path=self.raw['image']))
                return None
            base = self.insert_image_scaled(base_image=base, region=(0, 0, 1080, 1150), image_path=filename)
        logger.info("Image base prepared")
        return base

    def __print_name(self, base):
        # TODO: subtitle
        td = TextDrawer(base, font_size=int(285 * self.raw.get('titleFontSizeScale', 1.0)), bold=True)
        td.set_font_direct('BOD_B.TTF')
        td.set_font(capitalization=TextDrawer.CapitalizationModes.SmallCaps, horizontal_alignment=TextDrawer.TextAlignment.Center, vertical_alignment=TextDrawer.TextAlignment.Center)
        td.print_in_region((2400, 0, 0, 240), self.raw['name'], offset_borders=True)
        logger.info("Name printed")
    def __print_stats(self, base):
        td = TextDrawer(base, font_size=110, bold=True, font_family='Constantia', color='white')
        td.print_line((910, 750), "{move}".format(**self.raw['stats']))
        td.print_line((790, 950), "{save}+".format(**self.raw['stats']))
        td.print_line((990, 950), "{agility}+".format(**self.raw['stats']))
        logger.info("Stats printed")
    def __print_dice_space(self, base):
        dice_section = self.raw.get('diceSpace', "default")
        if (dice_section == "default"):
            dice_section = ConfigLoader.get_from_config('compilerTypeSpecific/hero/defaultDiceSpace', 'compilers')

        total_dices_count = sum(_dice_type['count'] for _dice_type in dice_section)
        x1 = 1630; x2 = 3260
        _x = x1; _y = 533
        _dx = (x2 - x1) // (total_dices_count - 1)
        for _dice_type in dice_section:
            for i in range(_dice_type['count']):
                self.insert_image_centered(base_image=base, position=(_x, _y), image_path=self.sources_directory + _dice_type['image'])
                _x += _dx
        logger.info("Dice space printed")
    def __print_weapons(self, base):
        td = TextDrawer(base, font_size=70, color='black', bold=True)
        td.set_font(horizontal_alignment=TextDrawer.TextAlignment.Center, vertical_alignment=TextDrawer.TextAlignment.Center)

        self.insert_table \
        (
            vertical_columns = [ 1340, 2420, 2860, 3070, 3455 ],
            top = 760,
            cell_height = 110,
            data = self.raw['weapons'],

            body_row_template = [ "{name} ({cost}+)", "{range}", "{hit}+", "{damage}" ],
            body_text_drawer = td,
            body_row_interval = [ None, None, 60, 40 ][len(self.raw['weapons'])],
            body_capitalization = TextDrawer.CapitalizationModes.Capitalize,

            header_row = [ "WEAPON ACTIONS", "Range", "Hit", "Damage" ],
            header_text_drawer = td,
            header_row_interval = 70,
            header_capitalization = TextDrawer.CapitalizationModes.Normal,
        )
        logger.info("Weapon table printed")
    def __print_rules(self, base):
        td = TextDrawer(base, font_size=90, color='black')
        td.set_font \
        (
            horizontal_alignment=TextDrawer.TextAlignment.Justify,
            vertical_alignment=TextDrawer.TextAlignment.Center,
            vertical_space_scale=0.15,
            paragraph_vertical_space=50,
        )
        y = 1330; light = True
        gradient_base = self.__get_gradient_image()

        for ability in self.raw['abilities']:
            if (ability.get('cost', None)):
                text = "**{name} ({cost}+):** {description}".format(**ability)
            else:
                text = "**{name}:** {description}".format(**ability)

            _h = self.__print_rules_block(base, td, y, text, light, gradient_base, dice_space=ability['diceSpace'])
            y += _h
            light = not light

        text_traits = "**TRAITS:** The {name} is **{trait_1}** and **{trait_2}**.".format(name=self.raw['name'], trait_1=self.raw['traits'][0].capitalize(), trait_2=self.raw['traits'][1].capitalize())
        text_renown = "**RENOWN:** {description}".format(description=self.raw['renown'])
        text = text_traits + '\n' + text_renown
        _h = self.__print_rules_block(base, td, y, text, light, gradient_base)
        y += _h
        light = not light
        logger.info("Rules printed")

    def __get_gradient_image(self):

        r = 255; g = 255; b = 255; aMin = 0; aMax = 80
        im = Image.new("RGBA", size=(3600, 1), color=(r, g, b, aMin))

        x1 = 250
        x2 = 1200
        x3 = 2400
        x4 = 3400

        for i in range(x1, x2):
            a = int((aMax - aMin) * (i - x1) / (x2 - x1))
            im.putpixel((i, 0), (r, g, b, a))
        for i in range(x2, x3):
            a = aMax
            im.putpixel((i, 0), (r, g, b, a))
        for i in range(x3, x4):
            a = int(aMax - (aMax - aMin) * (i - x3) / (x4 - x3))
            im.putpixel((i, 0), (r, g, b, a))

        return im

    def __print_rules_block(self, base:Image.Image, text_drawer, y:int, text:str, light:bool, gradient_base:Image.Image, dice_space:bool=False):
        x1 = 365; x2 = 2933 if dice_space else 3233
        dy = self.raw.get('rulesSeparatorHeight', 100)

        _, _h = text_drawer.get_text_size((x1, y, x2, 0), text, offset_borders=False)

        if (dice_space):
            _, _h2 = self.get_image_size(self.sources_directory + "dice.png")
            _h = max(_h, _h2)
        _h += dy

        if (light):
            _w = gradient_base.width
            gradient = gradient_base.resize((_w, _h))
            base.paste(gradient, (0, y), gradient)

        if (dice_space):
            _x = 3260; _y = y + _h // 2
            self.insert_image_centered(base, (_x, _y), self.sources_directory + "dice.png")

        # -5 because of not correct intuitive of text while on print
        text_drawer.print_in_region((x1, y - 5, x2, y - 5 + _h), text, offset_borders=False)
        return _h
<|endoftext|>