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

"""All the necessary functions to interact with the backend or server side."""

try:
    import simple_json as json
except ImportError:
    import json

import contextlib
import datetime
import gzip
import hashlib
import io
import re
import requests
import types
import urlparse

from flask import (
    abort,
    current_app as app,
)
from requests.exceptions import (
    ConnectionError,
    ConnectTimeout,
    ReadTimeout,
)

CONFIG_GET = app.config.get

# Timeout seconds to connect and read from the remote server.
CONNECT_TIMEOUT = CONFIG_GET("REQUEST_CONNECT_TIMEOUT")
READ_TIMEOUT = CONFIG_GET("REQUEST_READ_TIMEOUT")
CACHE_DEFAULT_TIMEOUT = CONFIG_GET("CACHE_DEFAULT_TIMEOUT")

AUTH_HEADER = CONFIG_GET("BACKEND_TOKEN_HEADER")
AUTH_TOKEN = CONFIG_GET("BACKEND_TOKEN")
BACKEND_URL = CONFIG_GET("BACKEND_URL")

# The requests session object.
REQ_SESSION = requests.Session()
HTTP_ADAPTER = requests.adapters.HTTPAdapter(
    pool_connections=CONFIG_GET("REQUEST_MIN_POOL_SIZE"),
    pool_maxsize=CONFIG_GET("REQUEST_MAX_POOL_SIZE")
)
REQ_SESSION.mount("http://", HTTP_ADAPTER)
REQ_SESSION.mount("https://", HTTP_ADAPTER)
REQ_SESSION.headers.update({AUTH_HEADER: AUTH_TOKEN})

def extract_gzip_data(data, headers):
    """Extract and json-serialize gzipped data from a response.

    :param data: The data from the response.
    :param headers: The headers of the response.
    :return The data itself or a json object.
    """
    read_data = None
    if "content-encoding" in headers:
        if "gzip" in headers["content-encoding"]:
            in_buffer = io.BytesIO()
            in_buffer.write(data)
            in_buffer.seek(io.SEEK_SET)

            with gzip.GzipFile(mode="rb", fileobj=in_buffer) as g_data:
                read_data = g_data.read()

    if read_data:
        json_data = None
        json_data = json.loads(read_data, encoding="utf-8")
        read_data = data = None
    else:
        json_data = data

    return json_data

def is_mobile_browser(request):
    """Verify if the request is made from a mobile browser.

    :param request: The request to analyze.
    :return True or False.
    """
    platform = request.user_agent.platform
    user_agent = request.user_agent.string
    return _is_mobile_browser(platform, user_agent)

@app.cache.memoize(timeout=60*60*6)
def _is_mobile_browser(platform, user_agent):
    """Wrapper to make the function cachable.

    This is where the logic lies. This function is only used to provide an
    easy way to cache its results based on valid arguments.

    :param platform: The platform making the request.
    :param user_agent: The user agent string.
    :return True or False.
    """
    is_mobile = False
    if any([platform == "android", platform == "iphone"]):
        is_mobile = True
    elif all([
            platform == "windows",
            re.search("Windows Phone", user_agent)]):
        is_mobile = True
    elif re.search("BlackBerry|BB", user_agent):
        is_mobile = True
    elif re.search("Mobile", user_agent):
        is_mobile = True

    return is_mobile

def is_old_browser(request):
    """Define if a browser is an older version.

    An older browser might not support all features. Right now we check only
    if IE is < 9.

    :param request: The request to analyze.
    :return True or False.
    """
    browser = request.user_agent.browser
    version = (
        request.user_agent.version and
        int(request.user_agent.version.split(".")[0])
    )
    return _is_old_browser(browser, version)

@app.cache.memoize(timeout=60*60*6)
def _is_old_browser(browser, version):
    """Wrapper to make the function cachable.

    This is where the logic lies. This function is only used to provide an
    easy way to cache its results based on valid arguments.

    :param browser: The browser string in a request.
    :param version: The browser version number.
    :return True or False.
    """
    is_old = False
    if all([browser == "msie", version < 9]):
        is_old = True

    return is_old

def get_search_parameters(request):
    """Get the request parameters for the search box.

    :param request: The request to analyze.
    :return The search filter to apply and the page length.
    """
    search_filter = ""
    page_len = 25

    if request.args:
        page_len = request.args.get("show", 25)
        search_filter = " ".join(
            [arg for arg in request.args if arg != "show"]
        )

    return search_filter, page_len

def today_date():
    """Return today date as: %a, %d %b %Y

    Date is based on the server, hopefully with the system clock set at UTC.

    :return The date string.
    """
    return datetime.date.today().strftime("%a, %d %b %Y")

@app.cache.memoize(timeout=60*60*6)
def create_url(api_path):
    """Create the complete URL to the API backend.

    :param api_path: The API path.
    :return The full URL to the backend.
    """
    return urlparse.urljoin(BACKEND_URL, api_path)

def _create_api_path(api_path, other_path=None):
    """Merge URL tokens together.

    :param api_path: The path to the API endpoint.
    :type api_path: str
    :param other_path: The path to append, defaults to None.
    :type other_path: list or str
    """
    def _check_and_add_trailing_slash(path):
        """Check if the path is missing the trailing /."""
        if path[-1] != "/":
            path += "/"
        return path

    # pylint: disable=invalid-name
    def _check_and_remove_trailing_slash(path):
        """Remove the trailing / from the path."""
        if path[-1] == "/":
            path = path[:-1]
        return path

    api_path = _check_and_add_trailing_slash(api_path)

    if other_path:
        if isinstance(other_path, types.StringTypes):
            api_path += _check_and_remove_trailing_slash(other_path)
        elif isinstance(other_path, types.ListType):
            for path in other_path:
                api_path += _check_and_add_trailing_slash(path)
            api_path = _check_and_remove_trailing_slash(api_path)

    return api_path

@app.cache.memoize(timeout=60*60*6)
def _get_request_headers():
    """Get the default request headers.

    :return The headers as a dictionary.
    """
    headers = {}
    if AUTH_TOKEN:
        headers = {
            AUTH_HEADER: AUTH_TOKEN
        }

    return headers

def request_get(url, params=None, timeout=None):
    """Perform a GET request on the provided URL.

    :return The server response.
    """
    if not params:
        params = []

    return_data = status_code = headers = None
    cache_key = hashlib.md5("%s%s" % (url, str(params))).digest()

    cached = app.cache.get(cache_key)
    if cached:
        return_data, status_code, headers = cached
    else:
        try:
            with contextlib.closing(
                    REQ_SESSION.get(
                        url,
                        params=params,
                        timeout=(CONNECT_TIMEOUT, READ_TIMEOUT),
                        stream=True)) as req:
                return_data = req.raw.data or req.text
                status_code = req.status_code
                headers = req.headers

            if timeout is None:
                timeout = CACHE_DEFAULT_TIMEOUT

            app.cache.set(
                cache_key,
                (return_data, status_code, headers),
                timeout=timeout
            )
        except (ConnectTimeout, ReadTimeout):
            abort(408)
        except ConnectionError:
            abort(500)

    return return_data, status_code, headers

# pylint: disable=too-many-arguments
def request_post(
        url, data, params=None, headers=None, stream=True, timeout=None):
    """Perform a POST request on the provided URL with the given data.

    :return The server response.
    """
    if not params:
        params = []
    if not headers:
        headers = {}

    return_data = status_code = r_headers = None
    cache_key = hashlib.md5("%s%s%s" % (url, data, str(params))).digest()

    cached = app.cache.get(cache_key)
    if cached:
        return_data, status_code, r_headers = cached
    else:
        try:
            with contextlib.closing(REQ_SESSION.post(
                    url,
                    data=data,
                    params=params,
                    headers=headers,
                    stream=stream,
                    timeout=(CONNECT_TIMEOUT, READ_TIMEOUT))) as req:
                return_data = req.raw.data or req.text
                status_code = req.status_code
                r_headers = req.headers

            if timeout is None:
                timeout = CACHE_DEFAULT_TIMEOUT

            app.cache.set(
                cache_key,
                (return_data, status_code, r_headers),
                timeout=timeout
            )
        except (ConnectTimeout, ReadTimeout):
            abort(408)
        except ConnectionError:
            abort(500)

    return return_data, status_code, r_headers

def ajax_count_get(request, api_path, collection, timeout=None):
    """Handle AJAX call from the client to the `count` API.

    :param request: The request performed.
    :param api_path: The API endpoint where to perform the request.
    :param collection: The collection to count.

    :return A tuple with the data, status code and headers of the
        `requests.Response` object.
    """
    params_list = request.args.lists()

    api_path = _create_api_path(api_path)

    if collection:
        api_path = _create_api_path(api_path, collection)

    url = create_url(api_path)

    data, status_code, headers = request_get(
        url, params=params_list, timeout=timeout)
    return data, status_code, headers.items()

def ajax_get(request, api_path, doc_id=None, timeout=None):
    """Handle general AJAX calls from the client.

    :param request: The request performed.
    :param api_path: The API endpoint where to perform the request.
    :return A tuple with the data, status code and headers of the
        `requests.Response` object.
    """
    params_list = request.args.lists()

    if "id" in request.args:
        doc_id = request.args["id"]
        params_list.remove(("id", [doc_id]))

    if doc_id:
        api_path = _create_api_path(api_path, doc_id)

    url = create_url(api_path)

    data, status_code, headers = request_get(
        url, params=params_list, timeout=timeout)
    return (data, status_code, headers.items())

def ajax_bisect(request, doc_id, api_path, timeout=None):
    """Handle GET operations on the bisect collection.

    :param request: The request performed.
    :param doc_id: The ID of the bisect document.
    :param api_path: The API endpoint where to perform the request.
    """
    params_list = request.args.lists()

    if doc_id:
        api_path = _create_api_path(api_path, [doc_id])
    else:
        api_path = _create_api_path(api_path)
    url = create_url(api_path)

    data, status_code, headers = request_get(
        url, params=params_list, timeout=timeout)
    return (data, status_code, headers.items())

def ajax_batch_post(request, api_path, timeout=None):
    """Handle batch POST operations.

    :param request: The request performed.
    :param api_path: The API endpoint where to perform the request.
    :return A tuple with the data, status code and headers of the
        `requests.Response` object.
    """
    url = create_url(api_path)
    data, status_code, headers = request_post(
        url,
        request.data,
        headers={"Content-Type": "application/json"},
        timeout=timeout
    )

    return data, status_code, headers.items()

@app.cache.memoize(timeout=60*60*8)
def get_version():
    """Get the backend API version."""
    url = create_url(CONFIG_GET("VERSION_API_ENDPOINT"))
    data, status_code, headers = request_get(url)

    backend_version = None
    if status_code == 200:
        read_data = extract_gzip_data(data, headers)

        if read_data:
            backend_version = read_data["result"][0]["version"]

    return backend_version

def ajax_logs(request, api_path, doc_id=None, timeout=None):
    """Get logs from the backend.

    :param request: The request performed.
    :param api_path: The API endpoint where to perform the request.
    :param doc_id: The ID of the bisect document.
    """
    params_list = request.args.lists()

    if doc_id:
        api_path = _create_api_path(api_path % doc_id)
    else:
        api_path = _create_api_path(api_path)
    url = create_url(api_path)

    data, status_code, headers = request_get(
        url, params=params_list, timeout=timeout)
    return (data, status_code, headers.items())
<commit_msg>Clean up and reorganize code<commit_after># This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""All the necessary functions to interact with the backend or server side."""

try:
    import simple_json as json
except ImportError:
    import json

import contextlib
import datetime
import gzip
import hashlib
import io
import re
import requests
import types
import urlparse

from flask import (
    abort,
    current_app as app,
)
from requests.exceptions import (
    ConnectionError,
    ConnectTimeout,
    ReadTimeout,
)

CONFIG_GET = app.config.get

# Timeout seconds to connect and read from the remote server.
CONNECT_TIMEOUT = CONFIG_GET("REQUEST_CONNECT_TIMEOUT")
READ_TIMEOUT = CONFIG_GET("REQUEST_READ_TIMEOUT")
CACHE_DEFAULT_TIMEOUT = CONFIG_GET("CACHE_DEFAULT_TIMEOUT")

AUTH_HEADER = CONFIG_GET("BACKEND_TOKEN_HEADER")
AUTH_TOKEN = CONFIG_GET("BACKEND_TOKEN")
BACKEND_URL = CONFIG_GET("BACKEND_URL")

# The requests session object.
REQ_SESSION = requests.Session()
HTTP_ADAPTER = requests.adapters.HTTPAdapter(
    pool_connections=CONFIG_GET("REQUEST_MIN_POOL_SIZE"),
    pool_maxsize=CONFIG_GET("REQUEST_MAX_POOL_SIZE")
)
REQ_SESSION.mount("http://", HTTP_ADAPTER)
REQ_SESSION.mount("https://", HTTP_ADAPTER)
REQ_SESSION.headers.update({AUTH_HEADER: AUTH_TOKEN})

def extract_gzip_data(data, headers):
    """Extract and json-serialize gzipped data from a response.

    :param data: The data from the response.
    :param headers: The headers of the response.
    :return The data itself or a json object.
    """
    read_data = None
    if "content-encoding" in headers:
        if "gzip" in headers["content-encoding"]:
            in_buffer = io.BytesIO()
            in_buffer.write(data)
            in_buffer.seek(io.SEEK_SET)

            with gzip.GzipFile(mode="rb", fileobj=in_buffer) as g_data:
                read_data = g_data.read()

    if read_data:
        json_data = None
        json_data = json.loads(read_data, encoding="utf-8")
        read_data = data = None
    else:
        json_data = data

    return json_data

@app.cache.memoize(timeout=60*60*6)
def _is_mobile_browser(platform, user_agent):
    """Wrapper to make the function cachable.

    This is where the logic lies. This function is only used to provide an
    easy way to cache its results based on valid arguments.

    :param platform: The platform making the request.
    :param user_agent: The user agent string.
    :return True or False.
    """
    is_mobile = False
    if any([platform == "android", platform == "iphone"]):
        is_mobile = True
    elif all([
            platform == "windows",
            re.search("Windows Phone", user_agent)]):
        is_mobile = True
    elif re.search("BlackBerry|BB", user_agent):
        is_mobile = True
    elif re.search("Mobile", user_agent):
        is_mobile = True

    return is_mobile

def is_mobile_browser(request):
    """Verify if the request is made from a mobile browser.

    :param request: The request to analyze.
    :return True or False.
    """
    platform = request.user_agent.platform
    user_agent = request.user_agent.string
    return _is_mobile_browser(platform, user_agent)

@app.cache.memoize(timeout=60*60*6)
def _is_old_browser(browser, version):
    """Wrapper to make the function cachable.

    This is where the logic lies. This function is only used to provide an
    easy way to cache its results based on valid arguments.

    :param browser: The browser string in a request.
    :param version: The browser version number.
    :return True or False.
    """
    is_old = False
    if all([browser == "msie", version < 9]):
        is_old = True

    return is_old

def is_old_browser(request):
    """Define if a browser is an older version.

    An older browser might not support all features. Right now we check only
    if IE is < 9.

    :param request: The request to analyze.
    :return True or False.
    """
    browser = request.user_agent.browser
    version = (
        request.user_agent.version and
        int(request.user_agent.version.split(".")[0])
    )
    return _is_old_browser(browser, version)

def get_search_parameters(request):
    """Get the request parameters for the search box.

    :param request: The request to analyze.
    :return The search filter to apply and the page length.
    """
    search_filter = ""
    page_len = 25

    if request.args:
        page_len = request.args.get("show", 25)
        search_filter = " ".join(
            [arg for arg in request.args if arg != "show"]
        )

    return search_filter, page_len

def today_date():
    """Return today date as: %a, %d %b %Y

    Date is based on the server, hopefully with the system clock set at UTC.

    :return The date string.
    """
    return datetime.date.today().strftime("%a, %d %b %Y")

@app.cache.memoize(timeout=60*60*6)
def create_url(api_path):
    """Create the complete URL to the API backend.

    :param api_path: The API path.
    :return The full URL to the backend.
    """
    return urlparse.urljoin(BACKEND_URL, api_path)

def _create_api_path(api_path, other_path=None):
    """Merge URL tokens together.

    :param api_path: The path to the API endpoint.
    :type api_path: str
    :param other_path: The path to append, defaults to None.
    :type other_path: list or str
    """
    def _check_and_add_trailing_slash(path):
        """Check if the path is missing the trailing /."""
        if path[-1] != "/":
            path += "/"
        return path

    # pylint: disable=invalid-name
    def _check_and_remove_trailing_slash(path):
        """Remove the trailing / from the path."""
        if path[-1] == "/":
            path = path[:-1]
        return path

    api_path = _check_and_add_trailing_slash(api_path)

    if other_path:
        if isinstance(other_path, types.StringTypes):
            api_path += _check_and_remove_trailing_slash(other_path)
        elif isinstance(other_path, types.ListType):
            for path in other_path:
                api_path += _check_and_add_trailing_slash(path)
            api_path = _check_and_remove_trailing_slash(api_path)

    return api_path

def request_get(url, params=None, timeout=None):
    """Perform a GET request on the provided URL.

    :return The server response.
    """
    if not params:
        params = []

    return_data = status_code = headers = None
    cache_key = hashlib.md5("%s%s" % (url, str(params))).digest()

    cached = app.cache.get(cache_key)
    if cached:
        return_data, status_code, headers = cached
    else:
        try:
            with contextlib.closing(
                    REQ_SESSION.get(
                        url,
                        params=params,
                        timeout=(CONNECT_TIMEOUT, READ_TIMEOUT),
                        stream=True)) as req:
                return_data = req.raw.data or req.text
                status_code = req.status_code
                headers = req.headers

            if timeout is None:
                timeout = CACHE_DEFAULT_TIMEOUT

            app.cache.set(
                cache_key,
                (return_data, status_code, headers),
                timeout=timeout
            )
        except (ConnectTimeout, ReadTimeout):
            abort(408)
        except ConnectionError:
            abort(500)

    return return_data, status_code, headers

# pylint: disable=too-many-arguments
def request_post(
        url, data, params=None, headers=None, stream=True, timeout=None):
    """Perform a POST request on the provided URL with the given data.

    :return The server response.
    """
    if not params:
        params = []
    if not headers:
        headers = {}

    return_data = status_code = r_headers = None
    cache_key = hashlib.md5("%s%s%s" % (url, data, str(params))).digest()

    cached = app.cache.get(cache_key)
    if cached:
        return_data, status_code, r_headers = cached
    else:
        try:
            with contextlib.closing(REQ_SESSION.post(
                    url,
                    data=data,
                    params=params,
                    headers=headers,
                    stream=stream,
                    timeout=(CONNECT_TIMEOUT, READ_TIMEOUT))) as req:
                return_data = req.raw.data or req.text
                status_code = req.status_code
                r_headers = req.headers

            if timeout is None:
                timeout = CACHE_DEFAULT_TIMEOUT

            app.cache.set(
                cache_key,
                (return_data, status_code, r_headers),
                timeout=timeout
            )
        except (ConnectTimeout, ReadTimeout):
            abort(408)
        except ConnectionError:
            abort(500)

    return return_data, status_code, r_headers

def ajax_count_get(request, api_path, collection, timeout=None):
    """Handle AJAX call from the client to the `count` API.

    :param request: The request performed.
    :param api_path: The API endpoint where to perform the request.
    :param collection: The collection to count.

    :return A tuple with the data, status code and headers of the
        `requests.Response` object.
    """
    params_list = request.args.lists()

    api_path = _create_api_path(api_path)

    if collection:
        api_path = _create_api_path(api_path, collection)

    url = create_url(api_path)

    data, status_code, headers = request_get(
        url, params=params_list, timeout=timeout)
    return data, status_code, headers.items()

def ajax_get(request, api_path, doc_id=None, timeout=None):
    """Handle general AJAX calls from the client.

    :param request: The request performed.
    :param api_path: The API endpoint where to perform the request.
    :return A tuple with the data, status code and headers of the
        `requests.Response` object.
    """
    params_list = request.args.lists()

    if "id" in request.args:
        doc_id = request.args["id"]
        params_list.remove(("id", [doc_id]))

    if doc_id:
        api_path = _create_api_path(api_path, doc_id)

    url = create_url(api_path)

    data, status_code, headers = request_get(
        url, params=params_list, timeout=timeout)
    return (data, status_code, headers.items())

def ajax_bisect(request, doc_id, api_path, timeout=None):
    """Handle GET operations on the bisect collection.

    :param request: The request performed.
    :param doc_id: The ID of the bisect document.
    :param api_path: The API endpoint where to perform the request.
    """
    params_list = request.args.lists()

    if doc_id:
        api_path = _create_api_path(api_path, [doc_id])
    else:
        api_path = _create_api_path(api_path)
    url = create_url(api_path)

    data, status_code, headers = request_get(
        url, params=params_list, timeout=timeout)
    return (data, status_code, headers.items())

def ajax_batch_post(request, api_path, timeout=None):
    """Handle batch POST operations.

    :param request: The request performed.
    :param api_path: The API endpoint where to perform the request.
    :return A tuple with the data, status code and headers of the
        `requests.Response` object.
    """
    url = create_url(api_path)
    data, status_code, headers = request_post(
        url,
        request.data,
        headers={"Content-Type": "application/json"},
        timeout=timeout
    )

    return data, status_code, headers.items()

@app.cache.memoize(timeout=60*60*8)
def get_version():
    """Get the backend API version."""
    url = create_url(CONFIG_GET("VERSION_API_ENDPOINT"))
    data, status_code, headers = request_get(url)

    backend_version = None
    if status_code == 200:
        read_data = extract_gzip_data(data, headers)

        if read_data:
            backend_version = read_data["result"][0]["version"]

    return backend_version

def ajax_logs(request, api_path, doc_id=None, timeout=None):
    """Get logs from the backend.

    :param request: The request performed.
    :param api_path: The API endpoint where to perform the request.
    :param doc_id: The ID of the bisect document.
    """
    params_list = request.args.lists()

    if doc_id:
        api_path = _create_api_path(api_path % doc_id)
    else:
        api_path = _create_api_path(api_path)
    url = create_url(api_path)

    data, status_code, headers = request_get(
        url, params=params_list, timeout=timeout)
    return (data, status_code, headers.items())
<|endoftext|>


<commit_before>import yaml
import ConfigParser as _ConfigParser
from mapproxy.config.spec import validate_mapproxy_conf
from mapproxy.script.scales import scale_to_res
from mapproxy_webconf import utils

class ConfigError(Exception):
    pass

def load_mapproxy_yaml(filename):
    with open(filename, 'rb') as f:
        mapproxy_conf = yaml.load(f)

    return mapproxy_conf

def write_mapproxy_yaml(mapproxy_conf, filename):
    content = yaml.safe_dump(mapproxy_conf, default_flow_style=False)
    utils.save_atomic(filename, content=content)
    return content

def fill_storage_with_mapproxy_conf(storage, project, mapproxy_conf):
    # TODO convert named references (grids/caches/sources) to ids
    for section_name in ['services', 'layers', 'sources', 'grids', 'globals', 'caches']:
        section = mapproxy_conf.get(section_name, {})
        if isinstance(section, list):
            for item in section:
                storage.add(section_name, project, item)
        else:
            for name, item in section.iteritems():
                if item is None:
                    continue
                item['name'] = name
                storage.add(section_name, project, item)

def id_dict_to_named_dict(input):
    output = {}
    for _, item in input.iteritems():
        name = item.pop('name')
        output[name] = item
    return output

def create_id_name_map(*dicts):
    id_map = {}
    for d in dicts:
        for key, value in d.iteritems():
            id_map[key] = value.get('name')

    return id_map

def validate(mapproxy_conf):
    conf_dict = utils.convert(mapproxy_conf)
    #check given mapproxy config against specs

    errors, informal_only = validate_mapproxy_conf(conf_dict)
    if not informal_only:
        return (errors, informal_only)

    #check for needed sections to run mapproxy
    errors = []
    sources_conf = conf_dict.get('sources', False)
    if not sources_conf:
        errors.append('Missing sources section')
    else:
        for name, source in sources_conf.items():
            if source.get('type', False) == 'wms':
                if source.get('req', False):
                    if not source['req'].get('url', False):
                        errors.append('Missing "url" for source %s' % name)
                    if not source['req'].get('layers', False):
                        errors.append('Missing "layers" for source %s' % name)
                else:
                    errors.append('Missing "req" for source %s' % name)

    grids_conf = conf_dict.get('grids', False)

    caches_conf = conf_dict.get('caches', False)
    if caches_conf:
        for name, cache in caches_conf.items():
            sources = cache.get('sources', False)
            if sources:
                for source in sources:
                    if not sources_conf:
                        errors.append('Source %s for cache %s not found in config' % (source, name))
                    elif source not in sources_conf.keys():
                        errors.append('Source %s for cache %s not found in config' % (source, name))
            grids = cache.get('grids', False)
            if grids:
                for grid in grids:
                    known_grids = ['GLOBAL_MERCATOR', 'GLOBAL_GEODETIC']
                    if grids_conf:
                        known_grids += grids_conf.keys()
                    if grid not in known_grids:
                        errors.append('Grid %s for cache %s not found in config' % (grid, name))

    layers_conf = conf_dict.get('layers', False)
    if not layers_conf:
        errors.append('Missing layers section')
    else:
        for layer in layers_conf:
            sources = layer.get('sources', False)
            if not sources:
                errors.append('Missing sources for layer %s' % layer['name'])
            else:
                for source in sources:
                    found = False
                    if caches_conf and source in caches_conf.keys():
                        found = True
                    elif sources_conf and source in sources_conf.keys():
                        found = True
                    if not found:
                        errors.append('Source %s for layer %s neither found in caches- nor in sources-section' % (source, layer['name']))

    services_conf = conf_dict.get('services', False)
    if not services_conf:
        errors.append('Missing services section')

    if not errors:
        return (None, True)
    return (errors, False)

def mapproxy_conf_from_storage(storage, project):
    mapproxy_conf = {}

    services = storage.get_all_data('services', project).values()
    if services:
        mapproxy_conf['services'] = {}
        for service, config in services[0].items():
            if 'active' in config and config['active']:
                config.pop('active', None)
                mapproxy_conf['services'][service] = config

    _globals = storage.get_all_data('globals', project).values()
    if _globals:
        mapproxy_conf['globals'] = _globals[0]

    used_sources = set()
    used_caches = set()

    sources = storage.get_all_data('sources', project)
    caches = storage.get_all_data('caches', project)
    layers = storage.get_all_data('layers', project).values()
    grids = storage.get_all_data('grids', project)

    defaults = storage.get_all_data('defaults', project)

    if sources:
        clear_min_max_res_scales(sources.values(), 'source', defaults)

    if layers:
        clear_min_max_res_scales(layers, 'layer', defaults)

    if grids:
        dpi = float(defaults.values()[0].get('dpi', (2.54/(0.00028 * 100))))
        for grid in grids.items():
            if 'scales' in grid[1].keys():
                units = grid[1].get('units', 'm')
                units = 1 if units == 'm' else 111319.4907932736
                try:
                    grid[1]['res'] = [round(scale_to_res(float(scale), dpi, units), 9) for scale in grid[1]['scales']]
                except ValueError:
                    raise ConfigError('grid %s contains invalid value in scales section' % grid[1].get('name', ''))
                del grid[1]['scales']
            try:
                del grid[1]['units']
            except KeyError:
                pass

    used_caches, used_sources = used_caches_and_sources(layers, caches, sources)

    used_grids = find_cache_grids(caches).union(find_source_grids(sources))

    id_map = create_id_name_map(sources, caches, grids)

    if layers:
        mapproxy_conf['layers'] = [replace_ids_layer(l, id_map) for l in layers]
    if used_caches:
        mapproxy_conf['caches'] = id_dict_to_named_dict(dict((k, replace_ids_cache(caches[k], id_map)) for k in used_caches))
    if used_sources:
        mapproxy_conf['sources'] = id_dict_to_named_dict(dict((k, sources[k]) for k in used_sources))
    if used_grids:
        mapproxy_conf['grids'] = id_dict_to_named_dict(dict((k, grids[k]) for k in used_grids if type(k) == int))

    if 'sources' in mapproxy_conf:
        for source in mapproxy_conf['sources'].values():
            if 'req' in source and 'layers' in source['req']:
                source['req']['layers'] = ','.join(source['req']['layers'])

    return mapproxy_conf

def clear_min_max_res_scales(data_elements, element_type, defaults):
    dpi = float(defaults.values()[0].get('dpi', (2.54/(0.00028 * 100))))
    for data_element in data_elements:
        units = data_element.get('units', 'm')
        units = 1 if units == 'm' else 111319.4907932736
        for key in ['min_res_scale', 'max_res_scale']:
            if key in data_element.keys():
                mapproxy_conf_key = key[:7] # remove '_scale'
                try:
                    data_element[mapproxy_conf_key] = round(scale_to_res(float(data_element[key]), dpi, units), 9)
                except ValueError:
                    raise ConfigError('%s %s contains invalid value in %s item' % (element_type, data_element.get('name', ''), key))
                del data_element[key]
        try:
            del data_element['units']
        except KeyError:
            pass

def replace_ids_cache(cache, id_map):
    if 'grids' in cache:
        cache['grids'] = [id_map[i] if type(i) == int else i for i in cache['grids']]
    if 'sources' in cache:
        cache['sources'] = [id_map[i] if type(i) == int else i for i in cache['sources']]
    return cache

def replace_ids_layer(layer, id_map):
    if 'sources' in layer:
        layer['sources'] = [id_map[i] if type(i) == int else i for i in layer['sources']]
    return layer

def layer_tree(layers):
    root = []
    # add (sub)layers to parents
    for layer in layers.itervalues():
        parent = layer.pop('_parent')
        if parent is None:
            root.append(layer)
        else:
            layers[parent].setdefault('layers', []).append(layer)

    # order layers by rank
    for layer in layers.itervalues():
        if 'layers' in layer:
            layer['layers'].sort(key=lambda x: x['_rank'])

    # remove _ranks
    for layer in layers.itervalues():
        layer.pop('_rank')

    return root

def used_caches_and_sources(layers, caches, sources):
    """
    Find used cache and source names in layers and caches configuration.
    """
    used_layer_sources = find_layer_sources(layers)
    used_cache_sources = find_cache_sources(caches)
    all_used_sources = used_layer_sources.union(used_cache_sources)

    avail_caches = set(caches.iterkeys())
    avail_sources = set(sources.iterkeys())

    used_caches = avail_caches.intersection(all_used_sources)
    used_sources = avail_sources.intersection(all_used_sources).difference(used_caches)

    return used_caches, used_sources

def find_cache_grids(cache_conf):
    grids = set()
    for cache in cache_conf.itervalues():
        grids.update(cache.get('grids', []))
    return grids

def find_source_grids(source_conf):
    grids = set()
    for source in source_conf.itervalues():
        grid = source.get('grid')
        if grid:
            grids.add(grid)
    return grids

def find_layer_sources(layers_conf):
    sources = set()
    _find_layer_sources(layers_conf, sources)
    return sources

def _find_layer_sources(layers, sources):
    for layer in layers:
        sources.update(layer.get('sources', []))
        if 'layers' in layer:
            _find_layer_sources(layer['layers'], sources)

def find_cache_sources(caches_conf):
    sources = set()
    for cache in caches_conf.itervalues():
        sources.update(cache.get('sources', []))
    return sources

class ConfigParser(object):
    """
    Utility class for parsing ini-style configurations with
    predefined default values..
    """

    """Default values, set by subclass"""
    defaults = {}

    def __init__(self, parser, fname):
        self.parser = parser
        self.fname = fname

    @classmethod
    def from_file(cls, fname):
        parser = _ConfigParser.ConfigParser()
        try:
            with open(fname) as fp:
                parser.readfp(fp)
        except Exception, ex:
            #XXXkai: logging?
            print 'Unable to read configuration: %s', ex
        return cls(parser, fname)

    def has_option(self, section, name):
        if self.parser.has_option(section, name):
            return True
        return name in self.defaults.get(section, {})

    def get(self, section, name):
        if self.parser.has_option(section, name):
            return self.parser.get(section, name)
        else:
            return self.defaults[section][name]

    def get_bool(self, section, name):
        if self.parser.has_option(section, name):
            return self.parser.getboolean(section, name)
        else:
            return self.defaults[section][name]

    def get_int(self, section, name):
        if self.parser.has_option(section, name):
            return self.parser.getint(section, name)
        else:
            return self.defaults[section][name]

    def set(self, section, name, value):
        if not self.defaults.has_key(section):
            raise _ConfigParser.NoSectionError(section)
        if not self.parser.has_section(section):
            self.parser.add_section(section)
        self.parser.set(section, name, value)

    def write(self):
        self.parser.write(open(self.fname, 'w'))
<commit_msg>add global webmercator to know grids<commit_after>import yaml
import ConfigParser as _ConfigParser
from mapproxy.config.spec import validate_mapproxy_conf
from mapproxy.script.scales import scale_to_res
from mapproxy_webconf import utils

class ConfigError(Exception):
    pass

def load_mapproxy_yaml(filename):
    with open(filename, 'rb') as f:
        mapproxy_conf = yaml.load(f)

    return mapproxy_conf

def write_mapproxy_yaml(mapproxy_conf, filename):
    content = yaml.safe_dump(mapproxy_conf, default_flow_style=False)
    utils.save_atomic(filename, content=content)
    return content

def fill_storage_with_mapproxy_conf(storage, project, mapproxy_conf):
    # TODO convert named references (grids/caches/sources) to ids
    for section_name in ['services', 'layers', 'sources', 'grids', 'globals', 'caches']:
        section = mapproxy_conf.get(section_name, {})
        if isinstance(section, list):
            for item in section:
                storage.add(section_name, project, item)
        else:
            for name, item in section.iteritems():
                if item is None:
                    continue
                item['name'] = name
                storage.add(section_name, project, item)

def id_dict_to_named_dict(input):
    output = {}
    for _, item in input.iteritems():
        name = item.pop('name')
        output[name] = item
    return output

def create_id_name_map(*dicts):
    id_map = {}
    for d in dicts:
        for key, value in d.iteritems():
            id_map[key] = value.get('name')

    return id_map

def validate(mapproxy_conf):
    conf_dict = utils.convert(mapproxy_conf)
    #check given mapproxy config against specs

    errors, informal_only = validate_mapproxy_conf(conf_dict)
    if not informal_only:
        return (errors, informal_only)

    #check for needed sections to run mapproxy
    errors = []
    sources_conf = conf_dict.get('sources', False)
    if not sources_conf:
        errors.append('Missing sources section')
    else:
        for name, source in sources_conf.items():
            if source.get('type', False) == 'wms':
                if source.get('req', False):
                    if not source['req'].get('url', False):
                        errors.append('Missing "url" for source %s' % name)
                    if not source['req'].get('layers', False):
                        errors.append('Missing "layers" for source %s' % name)
                else:
                    errors.append('Missing "req" for source %s' % name)

    grids_conf = conf_dict.get('grids', False)

    caches_conf = conf_dict.get('caches', False)
    if caches_conf:
        for name, cache in caches_conf.items():
            sources = cache.get('sources', False)
            if sources:
                for source in sources:
                    if not sources_conf:
                        errors.append('Source %s for cache %s not found in config' % (source, name))
                    elif source not in sources_conf.keys():
                        errors.append('Source %s for cache %s not found in config' % (source, name))
            grids = cache.get('grids', False)
            if grids:
                for grid in grids:
                    known_grids = ['GLOBAL_MERCATOR', 'GLOBAL_GEODETIC', 'GLOBAL_WEBMERCATOR']
                    if grids_conf:
                        known_grids += grids_conf.keys()
                    if grid not in known_grids:
                        errors.append('Grid %s for cache %s not found in config' % (grid, name))

    layers_conf = conf_dict.get('layers', False)
    if not layers_conf:
        errors.append('Missing layers section')
    else:
        for layer in layers_conf:
            sources = layer.get('sources', False)
            if not sources:
                errors.append('Missing sources for layer %s' % layer['name'])
            else:
                for source in sources:
                    found = False
                    if caches_conf and source in caches_conf.keys():
                        found = True
                    elif sources_conf and source in sources_conf.keys():
                        found = True
                    if not found:
                        errors.append('Source %s for layer %s neither found in caches- nor in sources-section' % (source, layer['name']))

    services_conf = conf_dict.get('services', False)
    if not services_conf:
        errors.append('Missing services section')

    if not errors:
        return (None, True)
    return (errors, False)

def mapproxy_conf_from_storage(storage, project):
    mapproxy_conf = {}

    services = storage.get_all_data('services', project).values()
    if services:
        mapproxy_conf['services'] = {}
        for service, config in services[0].items():
            if 'active' in config and config['active']:
                config.pop('active', None)
                mapproxy_conf['services'][service] = config

    _globals = storage.get_all_data('globals', project).values()
    if _globals:
        mapproxy_conf['globals'] = _globals[0]

    used_sources = set()
    used_caches = set()

    sources = storage.get_all_data('sources', project)
    caches = storage.get_all_data('caches', project)
    layers = storage.get_all_data('layers', project).values()
    grids = storage.get_all_data('grids', project)

    defaults = storage.get_all_data('defaults', project)

    if sources:
        clear_min_max_res_scales(sources.values(), 'source', defaults)

    if layers:
        clear_min_max_res_scales(layers, 'layer', defaults)

    if grids:
        dpi = float(defaults.values()[0].get('dpi', (2.54/(0.00028 * 100))))
        for grid in grids.items():
            if 'scales' in grid[1].keys():
                units = grid[1].get('units', 'm')
                units = 1 if units == 'm' else 111319.4907932736
                try:
                    grid[1]['res'] = [round(scale_to_res(float(scale), dpi, units), 9) for scale in grid[1]['scales']]
                except ValueError:
                    raise ConfigError('grid %s contains invalid value in scales section' % grid[1].get('name', ''))
                del grid[1]['scales']
            try:
                del grid[1]['units']
            except KeyError:
                pass

    used_caches, used_sources = used_caches_and_sources(layers, caches, sources)

    used_grids = find_cache_grids(caches).union(find_source_grids(sources))

    id_map = create_id_name_map(sources, caches, grids)

    if layers:
        mapproxy_conf['layers'] = [replace_ids_layer(l, id_map) for l in layers]
    if used_caches:
        mapproxy_conf['caches'] = id_dict_to_named_dict(dict((k, replace_ids_cache(caches[k], id_map)) for k in used_caches))
    if used_sources:
        mapproxy_conf['sources'] = id_dict_to_named_dict(dict((k, sources[k]) for k in used_sources))
    if used_grids:
        mapproxy_conf['grids'] = id_dict_to_named_dict(dict((k, grids[k]) for k in used_grids if type(k) == int))

    if 'sources' in mapproxy_conf:
        for source in mapproxy_conf['sources'].values():
            if 'req' in source and 'layers' in source['req']:
                source['req']['layers'] = ','.join(source['req']['layers'])

    return mapproxy_conf

def clear_min_max_res_scales(data_elements, element_type, defaults):
    dpi = float(defaults.values()[0].get('dpi', (2.54/(0.00028 * 100))))
    for data_element in data_elements:
        units = data_element.get('units', 'm')
        units = 1 if units == 'm' else 111319.4907932736
        for key in ['min_res_scale', 'max_res_scale']:
            if key in data_element.keys():
                mapproxy_conf_key = key[:7] # remove '_scale'
                try:
                    data_element[mapproxy_conf_key] = round(scale_to_res(float(data_element[key]), dpi, units), 9)
                except ValueError:
                    raise ConfigError('%s %s contains invalid value in %s item' % (element_type, data_element.get('name', ''), key))
                del data_element[key]
        try:
            del data_element['units']
        except KeyError:
            pass

def replace_ids_cache(cache, id_map):
    if 'grids' in cache:
        cache['grids'] = [id_map[i] if type(i) == int else i for i in cache['grids']]
    if 'sources' in cache:
        cache['sources'] = [id_map[i] if type(i) == int else i for i in cache['sources']]
    return cache

def replace_ids_layer(layer, id_map):
    if 'sources' in layer:
        layer['sources'] = [id_map[i] if type(i) == int else i for i in layer['sources']]
    return layer

def layer_tree(layers):
    root = []
    # add (sub)layers to parents
    for layer in layers.itervalues():
        parent = layer.pop('_parent')
        if parent is None:
            root.append(layer)
        else:
            layers[parent].setdefault('layers', []).append(layer)

    # order layers by rank
    for layer in layers.itervalues():
        if 'layers' in layer:
            layer['layers'].sort(key=lambda x: x['_rank'])

    # remove _ranks
    for layer in layers.itervalues():
        layer.pop('_rank')

    return root

def used_caches_and_sources(layers, caches, sources):
    """
    Find used cache and source names in layers and caches configuration.
    """
    used_layer_sources = find_layer_sources(layers)
    used_cache_sources = find_cache_sources(caches)
    all_used_sources = used_layer_sources.union(used_cache_sources)

    avail_caches = set(caches.iterkeys())
    avail_sources = set(sources.iterkeys())

    used_caches = avail_caches.intersection(all_used_sources)
    used_sources = avail_sources.intersection(all_used_sources).difference(used_caches)

    return used_caches, used_sources

def find_cache_grids(cache_conf):
    grids = set()
    for cache in cache_conf.itervalues():
        grids.update(cache.get('grids', []))
    return grids

def find_source_grids(source_conf):
    grids = set()
    for source in source_conf.itervalues():
        grid = source.get('grid')
        if grid:
            grids.add(grid)
    return grids

def find_layer_sources(layers_conf):
    sources = set()
    _find_layer_sources(layers_conf, sources)
    return sources

def _find_layer_sources(layers, sources):
    for layer in layers:
        sources.update(layer.get('sources', []))
        if 'layers' in layer:
            _find_layer_sources(layer['layers'], sources)

def find_cache_sources(caches_conf):
    sources = set()
    for cache in caches_conf.itervalues():
        sources.update(cache.get('sources', []))
    return sources

class ConfigParser(object):
    """
    Utility class for parsing ini-style configurations with
    predefined default values..
    """

    """Default values, set by subclass"""
    defaults = {}

    def __init__(self, parser, fname):
        self.parser = parser
        self.fname = fname

    @classmethod
    def from_file(cls, fname):
        parser = _ConfigParser.ConfigParser()
        try:
            with open(fname) as fp:
                parser.readfp(fp)
        except Exception, ex:
            #XXXkai: logging?
            print 'Unable to read configuration: %s', ex
        return cls(parser, fname)

    def has_option(self, section, name):
        if self.parser.has_option(section, name):
            return True
        return name in self.defaults.get(section, {})

    def get(self, section, name):
        if self.parser.has_option(section, name):
            return self.parser.get(section, name)
        else:
            return self.defaults[section][name]

    def get_bool(self, section, name):
        if self.parser.has_option(section, name):
            return self.parser.getboolean(section, name)
        else:
            return self.defaults[section][name]

    def get_int(self, section, name):
        if self.parser.has_option(section, name):
            return self.parser.getint(section, name)
        else:
            return self.defaults[section][name]

    def set(self, section, name, value):
        if not self.defaults.has_key(section):
            raise _ConfigParser.NoSectionError(section)
        if not self.parser.has_section(section):
            self.parser.add_section(section)
        self.parser.set(section, name, value)

    def write(self):
        self.parser.write(open(self.fname, 'w'))
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from app.config import db_sql as db
from datetime import datetime

class Detalle_registro(db.Model):
    id = db.Column(db.Integer, primary_key=True)

    fecha_hora_toma = db.Column(db.DateTime, nullable=False,
                                default=datetime.utcnow)
    fecha_hora_entrega = db.Column(db.DateTime, nullable=True)

    id_computadora = db.Column(db.Integer, db.ForeignKey('computadora.id'),
                               nullable=False)
    id_registro = db.Column(db.Integer, db.ForeignKey('registro.id'),
                            nullable=False)

    def __unicode__(self):
        return self.id

    def __hash__(self):
        return hash(self.id)

    def __repr__(self):
        return '<Detalle_registro %r | %r>' % self.id, self.id_registro
<commit_msg>Se arregla la representación de un Detalle_registro.<commit_after># -*- coding: utf-8 -*-
from app.config import db_sql as db
from datetime import datetime

class Detalle_registro(db.Model):
    id = db.Column(db.Integer, primary_key=True)

    fecha_hora_toma = db.Column(db.DateTime, nullable=False,
                                default=datetime.utcnow)
    fecha_hora_entrega = db.Column(db.DateTime, nullable=True)

    id_computadora = db.Column(db.Integer, db.ForeignKey('computadora.id'),
                               nullable=False)
    id_registro = db.Column(db.Integer, db.ForeignKey('registro.id'),
                            nullable=False)

    def __unicode__(self):
        return self.id

    def __hash__(self):
        return hash(self.id)

    def __repr__(self):
        return '<Detalle_registro %d | %d>' % (self.id, self.id_registro)
<|endoftext|>


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

import subprocess
import fileinput
import platform
import socket
import errno
import sys
import re
import os

class System():
    def __init__(self):
        pass

    def checkRoot(self):
        """
        Return True if user execution is by root
        """
        user = os.geteuid()
        if user != 0:
            return False
        else:
            return True

    def runShellCommand(self, command):
        """
        Runs shell command via subprocess
        """
        try:
            sh = subprocess.Popen(command.split(),
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE,
                                 )
            output, error = sh.communicate()
            if sh.returncode:
                if sh.returncode == 2:
                    raise OSError
            return output
        except OSError:
            raise OSError

    def getKernelRelease(self):
        """
        Get Kernel Release Version
        """
        return platform.release()

    def getOs(self):
        """
        Get Operating System Release
        """
        return self.runShellCommand("cat /etc/system-release")

    def getHostname(self):
        """
        Get Hostname
        """
        return socket.gethostname()

    def scanFile(self, file, string, array=None):
        """
        Returns True if scan finds string
        """
        self.array = []
        try:
            regex = re.compile('\\b'+string+'\\b')
            with open(file, 'r') as lines:
                for line in lines:
                    match = regex.findall(line)
                    if len(match) > 0:
                        if array:
                            self.array.append(line)
                        return True
        except IOError:
            raise IOError
            return False

    def readFile(self, file):
        """
        Reads a file
        """
        try:
            with open(file, 'r') as lines:
                return lines.read()
        except IOError:
            raise IOError
            return False

    def writeFile(self, file, contents):
        """
        Writes a file
        """
        try:
            f = open(file, 'w')
            f.write(contents)
            f.close()
        except Exception, e:
            raise Exception

    def appendFile(self, file, string):
        """
        Appends line to a file
        """
        try:
            with open(file, 'a') as line:
                line.write(string)
                line.close
        except Exception:
            raise Exception

    def findReplaceFile(self, file, find, replace):
        """
        Find string and replace
        """
        try:
            for line in fileinput.FileInput(file, inplace=1):
                line = line.replace(find, replace)
                print line,
        except OSError:
            raise OSError
        except Exception, e:
            raise Exception

    def writeToLogFile(self):
        """
        Write line to log file
        """
        pass

    def createDirectory(self, path):
        """
        Create Directory
        """
        try:
            os.makedirs(path)
        except OSError as exception:
            if exception.errno != errno.EEXIST:
                raise OSError
        return True

if __name__ == '__main__':
    system = System()
    #print system.runShellCommand('l -al hello')
    #print system.runShellCommand('foo bar')
    #print system.runShellCommand('ls -al hello')
    #print system.runShellCommand('cas -al hello')
    #print system.readFile('/home/zeus/current/test.txt')
    #system.writeFile('app/modules/builtins/tests/testappendtofile.txt',
    #                 'Change: ME\n')
    #print system.readFile('app/modules/builtins/tests/testappendtofile.txt')
    #system.findReplaceFile("app/modules/builtins/tests/testappendtofile.txt",
    #                       "ME",
    #                       "I am changed",
    #                      )
    #print system.readFile('app/modules/builtins/tests/testappendtofile.txt')
    #system.findReplaceFile("app/modules/builtins/tests/testemptyappendtofile.txt",
    #                       "ME",
    #                       "I am changed",
    #                      )
    #print system.readFile('app/modules/builtins/tests/testemptyappendtofile.txt')

<commit_msg>added getIps() to System()<commit_after>#-*- coding: utf-8 -*-

from netifaces import interfaces, ifaddresses, AF_INET
import subprocess
import fileinput
import platform
import socket
import errno
import sys
import re
import os

class System():
    def __init__(self):
        pass

    def checkRoot(self):
        """
        Return True if user execution is by root
        """
        user = os.geteuid()
        if user != 0:
            return False
        else:
            return True

    def runShellCommand(self, command):
        """
        Runs shell command via subprocess
        """
        try:
            sh = subprocess.Popen(command.split(),
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE,
                                 )
            output, error = sh.communicate()
            if sh.returncode:
                if sh.returncode == 2:
                    raise OSError
            return output
        except OSError:
            raise OSError

    def getKernelRelease(self):
        """
        Get Kernel Release Version
        """
        return platform.release()

    def getOs(self):
        """
        Get Operating System Release
        """
        return self.runShellCommand("cat /etc/system-release")

    def getHostname(self):
        """
        Get Hostname
        """
        return socket.gethostname()

    def scanFile(self, file, string, array=None):
        """
        Returns True if scan finds string
        """
        self.array = []
        try:
            regex = re.compile('\\b'+string+'\\b')
            with open(file, 'r') as lines:
                for line in lines:
                    match = regex.findall(line)
                    if len(match) > 0:
                        if array:
                            self.array.append(line)
                        return True
        except IOError:
            raise IOError
            return False

    def readFile(self, file):
        """
        Reads a file
        """
        try:
            with open(file, 'r') as lines:
                return lines.read()
        except IOError:
            raise IOError
            return False

    def writeFile(self, file, contents):
        """
        Writes a file
        """
        try:
            f = open(file, 'w')
            f.write(contents)
            f.close()
        except Exception, e:
            raise Exception

    def appendFile(self, file, string):
        """
        Appends line to a file
        """
        try:
            with open(file, 'a') as line:
                line.write(string)
                line.close
        except Exception:
            raise Exception

    def findReplaceFile(self, file, find, replace):
        """
        Find string and replace
        """
        try:
            for line in fileinput.FileInput(file, inplace=1):
                line = line.replace(find, replace)
                print line,
        except OSError:
            raise OSError
        except Exception, e:
            raise Exception

    def writeToLogFile(self):
        """
        Write line to log file
        """
        pass

    def createDirectory(self, path):
        """
        Create Directory
        """
        try:
            os.makedirs(path)
        except OSError as exception:
            if exception.errno != errno.EEXIST:
                raise OSError
        return True

    def getIps(self):
        """
        Return List of IP addresses
        """
        ip_list = []
        for interface in interfaces():
            for link in ifaddresses(interface)[AF_INET]:
                ip_list.append(link['addr'])
        return ip_list

if __name__ == '__main__':
    system = System()
    #print system.runShellCommand('l -al hello')
    #print system.runShellCommand('foo bar')
    #print system.runShellCommand('ls -al hello')
    #print system.runShellCommand('cas -al hello')
    #print system.readFile('/home/zeus/current/test.txt')
    #system.writeFile('app/modules/builtins/tests/testappendtofile.txt',
    #                 'Change: ME\n')
    #print system.readFile('app/modules/builtins/tests/testappendtofile.txt')
    #system.findReplaceFile("app/modules/builtins/tests/testappendtofile.txt",
    #                       "ME",
    #                       "I am changed",
    #                      )
    #print system.readFile('app/modules/builtins/tests/testappendtofile.txt')
    #system.findReplaceFile("app/modules/builtins/tests/testemptyappendtofile.txt",
    #                       "ME",
    #                       "I am changed",
    #                      )
    #print system.readFile('app/modules/builtins/tests/testemptyappendtofile.txt')

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from app.common.constants_strategy import SUPERSONIC_MODEL_TO_BE_PURCHASED, JET_MODEL_TO_BE_PURCHASED, \
    COMMERCIAL_MODEL_TO_BE_PURCHASED
from app.common.logger import logger
from app.common.email_methods import notify
from app.common.http_methods import get_request, post_request
from app.common.string_methods import string_contains, exception_if_not_contains, get_values_from_regex
from app.common.target_strings import ALLIANCE_PUT_PLANE_SUCCESSFUL
from app.common.target_urls import CHANGE_ENGINES_URL, FILL_FUEL_URL, SCRAP_PLANE_URL, MAINTENANCE_URL, \
    ALLIANCE_PUT_PLANE, ALLIANCE_PAGE, SITE
from app.planes.commercial_plane import CommercialPlane
from app.planes.jet_plane import JetPlane
from app.planes.supersonic_plane import SupersonicPlane

class PlaneMaintainer(object):
    def __init__(self, plane, airport):
        self.plane = plane
        self.__ready = True
        self.airport = airport
        self.refresh_needed = False
        # TODO make sure airport contains enough resources before maintenance

    def __change_engines(self):
        result = post_request(CHANGE_ENGINES_URL.format(plane_id=self.plane.plane_id),
                              {'id_moteur': self.plane.replacement_engines_type})
        if not string_contains(u"L'avion va bien recevoir ses nouveaux moteurs, durée : 2 heures.", result):
            # TODO parse the answer
            logger.warning('Error while changing engines')
        self.__ready = False

    def __fill_fuel(self):
        fuel_qty = self.plane.fuel_capacity - self.plane.kerosene
        confirm_page = post_request(FILL_FUEL_URL.format(plane_id=self.plane.plane_id),
                                    {'cq': fuel_qty})
        if not string_contains(u'Vous avez ajouté .+ litres? de kérosène dans votre avion !',
                               confirm_page):
            logger.warning('Error when filling fuel')
            self.__ready = False

    def __scrap_plane(self):
        get_request(SCRAP_PLANE_URL.format(plane_id=self.plane.plane_id))
        self.__ready = False

    def __do_maintenance(self):
        page = None
        try:
            page = get_request(MAINTENANCE_URL.format(plane_id=self.plane.plane_id))
            exception_if_not_contains(u'Votre avion est maintenant en maintenance', page)
        except:
            logger.error('Problem sending to maintenance')
            if string_contains(u"en mission, en maintenance ou n'a pas plus de 100,000 km sans maintenance", page):
                # case plane maintenance was over
                logger.warning("Maintenance over, should refresh plane list")
                self.refresh_needed = True
            else:
                # case:
                # - not enough mechanics
                # - current airport has changed
                notify('FM : could not send to maintenance', page)
        self.__ready = False

    def prepare_plane(self):
        # if self.airport.airport_name == MAIN_AIRPORT_NAME:
        #     self.removing_planes()
        # else:
        #     self.removing_planes_minor_airports()
        if self.plane.endlife:
            self.__scrap_plane()
            return False
        if self.plane.required_maintenance:
            self.__do_maintenance()
            return False
        if self.plane.engines_to_be_changed():
            self.__change_engines()
            return False
        if not self.plane.is_fuel_full():
            self.__fill_fuel()
        return self.__ready

    def removing_planes(self):
        if isinstance(self.plane, SupersonicPlane) and not isinstance(self.plane, SUPERSONIC_MODEL_TO_BE_PURCHASED):
            put_plane_alliance(self.plane.plane_id)
        elif isinstance(self.plane, JetPlane) and not isinstance(self.plane, JET_MODEL_TO_BE_PURCHASED):
            put_plane_alliance(self.plane.plane_id)
        elif isinstance(self.plane, CommercialPlane) and not isinstance(self.plane, COMMERCIAL_MODEL_TO_BE_PURCHASED):
            put_plane_alliance(self.plane.plane_id)

    def removing_planes_minor_airports(self):
        if isinstance(self.plane, SupersonicPlane) and isinstance(self.plane, SUPERSONIC_MODEL_TO_BE_PURCHASED):
            put_plane_alliance(self.plane.plane_id)
        elif isinstance(self.plane, JetPlane) and isinstance(self.plane, JET_MODEL_TO_BE_PURCHASED):
            put_plane_alliance(self.plane.plane_id)
        elif isinstance(self.plane, CommercialPlane) and isinstance(self.plane, COMMERCIAL_MODEL_TO_BE_PURCHASED):
            put_plane_alliance(self.plane.plane_id)

def put_plane_alliance(plane_id):
    response = post_request(ALLIANCE_PUT_PLANE, {'cq': 1, 'la_variete': str(plane_id)})
    return ALLIANCE_PUT_PLANE_SUCCESSFUL in response

def take_planes_alliance(nb_planes_required):
    alliance_page = get_request(ALLIANCE_PAGE)
    available_plane_types = get_values_from_regex(u'Détails', alliance_page)
    planes_available = []
    for plane_type in available_plane_types:
        page = get_request('{}/{}'.format(SITE, plane_type))
        planes_available = get_values_from_regex(u'Retirer', page)
    nb_planes_available = len(planes_available)
    for i in range(0, min(nb_planes_required, nb_planes_available)):
        get_request('{}/{}'.format(SITE, planes_available[i]))
<commit_msg>Refresh plane list after putting plane to scrap<commit_after># -*- coding: utf-8 -*-
from app.common.constants_strategy import SUPERSONIC_MODEL_TO_BE_PURCHASED, JET_MODEL_TO_BE_PURCHASED, \
    COMMERCIAL_MODEL_TO_BE_PURCHASED
from app.common.logger import logger
from app.common.email_methods import notify
from app.common.http_methods import get_request, post_request
from app.common.string_methods import string_contains, exception_if_not_contains, get_values_from_regex
from app.common.target_strings import ALLIANCE_PUT_PLANE_SUCCESSFUL
from app.common.target_urls import CHANGE_ENGINES_URL, FILL_FUEL_URL, SCRAP_PLANE_URL, MAINTENANCE_URL, \
    ALLIANCE_PUT_PLANE, ALLIANCE_PAGE, SITE
from app.planes.commercial_plane import CommercialPlane
from app.planes.jet_plane import JetPlane
from app.planes.supersonic_plane import SupersonicPlane

class PlaneMaintainer(object):
    def __init__(self, plane, airport):
        self.plane = plane
        self.__ready = True
        self.airport = airport
        self.refresh_needed = False
        # TODO make sure airport contains enough resources before maintenance

    def __change_engines(self):
        result = post_request(CHANGE_ENGINES_URL.format(plane_id=self.plane.plane_id),
                              {'id_moteur': self.plane.replacement_engines_type})
        if not string_contains(u"L'avion va bien recevoir ses nouveaux moteurs, durée : 2 heures.", result):
            # TODO parse the answer
            logger.warning('Error while changing engines')
        self.__ready = False

    def __fill_fuel(self):
        fuel_qty = self.plane.fuel_capacity - self.plane.kerosene
        confirm_page = post_request(FILL_FUEL_URL.format(plane_id=self.plane.plane_id),
                                    {'cq': fuel_qty})
        if not string_contains(u'Vous avez ajouté .+ litres? de kérosène dans votre avion !',
                               confirm_page):
            logger.warning('Error when filling fuel')
            self.__ready = False

    def __scrap_plane(self):
        get_request(SCRAP_PLANE_URL.format(plane_id=self.plane.plane_id))
        self.__ready = False
        self.refresh_needed = True

    def __do_maintenance(self):
        page = None
        try:
            page = get_request(MAINTENANCE_URL.format(plane_id=self.plane.plane_id))
            exception_if_not_contains(u'Votre avion est maintenant en maintenance', page)
        except:
            logger.error('Problem sending to maintenance')
            if string_contains(u"en mission, en maintenance ou n'a pas plus de 100,000 km sans maintenance", page):
                # case plane maintenance was over
                logger.warning("Maintenance over, should refresh plane list")
                self.refresh_needed = True
            else:
                # case:
                # - not enough mechanics
                # - current airport has changed
                notify('FM : could not send to maintenance', page)
        self.__ready = False

    def prepare_plane(self):
        # if self.airport.airport_name == MAIN_AIRPORT_NAME:
        #     self.removing_planes()
        # else:
        #     self.removing_planes_minor_airports()
        if self.plane.endlife:
            self.__scrap_plane()
            return False
        if self.plane.required_maintenance:
            self.__do_maintenance()
            return False
        if self.plane.engines_to_be_changed():
            self.__change_engines()
            return False
        if not self.plane.is_fuel_full():
            self.__fill_fuel()
        return self.__ready

    def removing_planes(self):
        if isinstance(self.plane, SupersonicPlane) and not isinstance(self.plane, SUPERSONIC_MODEL_TO_BE_PURCHASED):
            put_plane_alliance(self.plane.plane_id)
        elif isinstance(self.plane, JetPlane) and not isinstance(self.plane, JET_MODEL_TO_BE_PURCHASED):
            put_plane_alliance(self.plane.plane_id)
        elif isinstance(self.plane, CommercialPlane) and not isinstance(self.plane, COMMERCIAL_MODEL_TO_BE_PURCHASED):
            put_plane_alliance(self.plane.plane_id)

    def removing_planes_minor_airports(self):
        if isinstance(self.plane, SupersonicPlane) and isinstance(self.plane, SUPERSONIC_MODEL_TO_BE_PURCHASED):
            put_plane_alliance(self.plane.plane_id)
        elif isinstance(self.plane, JetPlane) and isinstance(self.plane, JET_MODEL_TO_BE_PURCHASED):
            put_plane_alliance(self.plane.plane_id)
        elif isinstance(self.plane, CommercialPlane) and isinstance(self.plane, COMMERCIAL_MODEL_TO_BE_PURCHASED):
            put_plane_alliance(self.plane.plane_id)

def put_plane_alliance(plane_id):
    response = post_request(ALLIANCE_PUT_PLANE, {'cq': 1, 'la_variete': str(plane_id)})
    return ALLIANCE_PUT_PLANE_SUCCESSFUL in response

def take_planes_alliance(nb_planes_required):
    alliance_page = get_request(ALLIANCE_PAGE)
    available_plane_types = get_values_from_regex(u'Détails', alliance_page)
    planes_available = []
    for plane_type in available_plane_types:
        page = get_request('{}/{}'.format(SITE, plane_type))
        planes_available = get_values_from_regex(u'Retirer', page)
    nb_planes_available = len(planes_available)
    for i in range(0, min(nb_planes_required, nb_planes_available)):
        get_request('{}/{}'.format(SITE, planes_available[i]))
<|endoftext|>


<commit_before>#!/usr/bin/python2.5
#
# Copyright 2008 the Melange authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""This module contains the Organization Model.
"""

__authors__ = [
  '"Pawel Solyga" <pawel.solyga@gmail.com>',
]

from google.appengine.ext import db

from django.utils.translation import ugettext

import soc.models.group

class Organization(soc.models.group.Group):
  """Organization details.
  """

  #: Optional development mailing list.
  dev_mailing_list = db.StringProperty(required=False,
    verbose_name=ugettext('Development Mailing List'))
  dev_mailing_list.help_text = ugettext(
    'Mailing list email address, URL to sign-up page, etc.')

  contrib_template = db.TextProperty(required=False, verbose_name=ugettext(
      'Application template'))
  contrib_template.help_text = ugettext(
      'This template can be used by contributors, such as students'
      ' and other non-member participants, when they apply to contribute'
      ' to the organization.')

  ideas = db.LinkProperty(required=False, verbose_name=ugettext('Idea list'))
  ideas.help_text = ugettext(
      'The URL to the ideas list of your organization.')
  ideas.example_text = ugettext('For instance a link to a Melange public '
      'document or some other URL')
<commit_msg>Add slots to the organization model<commit_after>#!/usr/bin/python2.5
#
# Copyright 2008 the Melange authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""This module contains the Organization Model.
"""

__authors__ = [
  '"Pawel Solyga" <pawel.solyga@gmail.com>',
]

from google.appengine.ext import db

from django.utils.translation import ugettext

import soc.models.group

class Organization(soc.models.group.Group):
  """Organization details.
  """

  #: Optional development mailing list.
  dev_mailing_list = db.StringProperty(required=False,
    verbose_name=ugettext('Development Mailing List'))
  dev_mailing_list.help_text = ugettext(
    'Mailing list email address, URL to sign-up page, etc.')

  contrib_template = db.TextProperty(required=False, verbose_name=ugettext(
      'Application template'))
  contrib_template.help_text = ugettext(
      'This template can be used by contributors, such as students'
      ' and other non-member participants, when they apply to contribute'
      ' to the organization.')

  ideas = db.LinkProperty(required=False, verbose_name=ugettext('Idea list'))
  ideas.help_text = ugettext(
      'The URL to the ideas list of your organization.')
  ideas.example_text = ugettext('For instance a link to a Melange public '
      'document or some other URL')

  slots = db.IntegerProperty(required=False,
      verbose_name=ugettext('Slots allocated'))
  slots.help_text = ugettext(
      'The amount of slots allocated to this organization.')
<|endoftext|>


<commit_before>from __future__ import print_function

__author__    = 'Viktor Kerkez <alefnula@gmail.com>'
__date__      = '25 July 2013'
__copyright__ = 'Copyright (c) 2013 Viktor Kerkez'

import os
import io
import copy
import logging
from StringIO import StringIO

logger = logging.getLogger(__name__)

class ConfigType:
    DICT = 'dict'
    JSON = 'json' # json files
    YAML = 'yaml' # yaml files
    INI = 'ini'   # ini files
    NA = 'na'     # not available

class ConfigObject(object):
    def __init__(self, data, fmt=ConfigType.NA, encoding='utf-8'):
        if isinstance(data, (dict, list, tuple)):
            self.filename = None
            self.fmt = ConfigType.DICT
            self.encofing = encoding
            self.data = copy.deepcopy(data)
        elif isinstance(data, basestring):
            if os.path.isfile(data):
                self.filename = os.path.abspath(data)
                self.fmt = self.__get_fmt(fmt, filename=self.filename)
                self.encoding = encoding
                self.data = self.__load()
            else:
                self.filename = None
                self.encoding = encoding
                if isinstance(data, str):
                    data = str.decode(encoding)
                self.fmt = self.__get_fmt(fmt, data=data)
                self.data = self.__load(data)
        else:
            self.filename = None
            self.fmt = fmt
            self.encofing = encoding
            self.data = {}

    def __get_fmt(self, fmt, filename=None, data=None):
        # First check if type is provided and if it's valid
        if fmt in (ConfigType.JSON, ConfigType.YAML, ConfigType.INI):
            return fmt
        if filename is not None:
            ext = os.path.splitext(data)[-1].lower()
            return {
                '.json': ConfigType.JSON,
                '.yaml': ConfigType.YAML,
                '.ini': ConfigType.INI,
            }.get(ext, ConfigType.NA)
        if data is not None:
            try:
                import json
                json.loads(data)
                return ConfigType.JSON
            except: pass
            try:
                import yaml
                yaml.safe_load(data)
                return ConfigType.YAML
            except: pass
            try:
                from ConfigParser import ConfigParser
                ConfigParser.readfp(StringIO(data))
                return ConfigType.INI
            except: pass
        return ConfigType.NA

    def __load(self, data=None):
        if self.fmt == ConfigType.JSON:
            import json
            if data is not None:
                return json.loads(data)
            else:
                with io.open(self.filename, 'r', encoding=self.encoding) as f:
                    return json.load(f)
        elif self.fmt == ConfigType.YAML:
            import yaml
            if data is not None:
                return yaml.safe_load(data)
            else:
                with io.open(self.filename, 'r', encoding=self.encoding) as f:
                    return yaml.safe_load(f)
        return {}

    def __dump(self):
        if self.filename is not None:
            if self.fmt == ConfigType.JSON:
                import json
                with io.open(self.filename, 'w', encoding=self.encoding) as f:
                    json.dump(self.data, f)
            elif self.fmt == ConfigType.YAML:
                import yaml
                with io.open(self.filename, 'w', encoding=self.encofing) as f:
                    yaml.safe_dump(self.data, f)

    def contains(self, var):
        current = self.data
        for part in var.split('.'):
            if part in current:
                current = current[part]
            else:
                return False
        return True

    def get(self, var, default=None):
        current = self.data
        for part in var.split('.'):
            if part in current:
                current = current[part]
            else:
                return default
        return current

    def set(self, var, value):
        current = self.data
        parts = var.split('.')
        for part in parts[:-1]:
            current = current.setdefault(part, {})
        current[parts[-1]] = value
        self.__dump()

    def delete(self, var):
        current = self.data
        parts = var.split('.')
        for part in parts[:-1]:
            if part in current:
                current = current[part]
            else:
                return
        del current[parts[-1]]
        self.__dump()

    def add(self, var, value, index=None):
        current = self.data
        parts = var.split('.')
        for part in parts[:-1]:
            current = current.setdefault(part, {})
        last = parts[-1]
        if last in current:
            if not isinstance(current[last], list):
                current[last] = [current[last]]
            if index is not None:
                current[last].insert(int(index), value)
            else:
                current[last].append(value)
        else:
            current[last] = [value]
        self.__dump()

    def remove(self, var, index):
        current = self.__data
        parts = var.split('.')
        for part in parts[:-1]:
            if part in current:
                current = current[part]
            else:
                return
        if isinstance(current[parts[-1]], list):
            try:
                current[parts[-1]].pop(int(index))
            except: pass
        self.__dump()

class Config(object):
    '''Base class for configuration management'''
    def __init__(self, data, fmt=ConfigType.NA, encoding='utf-8'):
        self.__configs = []
        self.attach(data, fmt, encoding)

    @property
    def current(self):
        return self.__configs[0]

    def attach(self, data, fmt=ConfigType.NA, encoding='utf-8'):
        self.__configs.insert(0, ConfigObject(data, fmt, encoding))

    def get(self, var, default=None):
        for config in self.__configs:
            if config.contains(var):
                return config.get(var)
        return default

    def set(self, var, value):
        self.current.set(var, value)

if __name__ == '__main__':
    c = Config({'foo': {'bar' : 3}})
    print(c.get('foo'))
    print(c.get('foo.bar'))
<commit_msg>Basic list support<commit_after>from __future__ import print_function

__author__    = 'Viktor Kerkez <alefnula@gmail.com>'
__date__      = '25 July 2013'
__copyright__ = 'Copyright (c) 2013 Viktor Kerkez'

import os
import io
import copy
import pprint
import logging
from StringIO import StringIO

logger = logging.getLogger(__name__)

class ConfigType:
    DICT = 'dict'
    JSON = 'json' # json files
    YAML = 'yaml' # yaml files
    INI = 'ini'   # ini files
    NA = 'na'     # not available

class ConfigError(Exception):
    pass

class Cfg(object):
    class NotFound(Exception):
        pass

    def __init__(self, data, fmt=ConfigType.NA, encoding='utf-8'):
        if isinstance(data, (dict, list, tuple)):
            self.filename = None
            self.fmt = ConfigType.DICT
            self.encofing = encoding
            self.data = copy.deepcopy(data)
        elif isinstance(data, basestring):
            if os.path.isfile(data):
                self.filename = os.path.abspath(data)
                self.fmt = self.__get_fmt(fmt, filename=self.filename)
                self.encoding = encoding
                self.data = self.__load()
            else:
                self.filename = None
                self.encoding = encoding
                if isinstance(data, str):
                    data = str.decode(encoding)
                self.fmt = self.__get_fmt(fmt, data=data)
                self.data = self.__load(data)
        else:
            self.filename = None
            self.fmt = fmt
            self.encofing = encoding
            self.data = {}

    def __get_fmt(self, fmt, filename=None, data=None):
        # First check if type is provided and if it's valid
        if fmt in (ConfigType.JSON, ConfigType.YAML, ConfigType.INI):
            return fmt
        if filename is not None:
            ext = os.path.splitext(data)[-1].lower()
            return {
                '.json': ConfigType.JSON,
                '.yaml': ConfigType.YAML,
                '.ini': ConfigType.INI,
            }.get(ext, ConfigType.NA)
        if data is not None:
            try:
                import json
                json.loads(data)
                return ConfigType.JSON
            except: pass
            try:
                import yaml
                yaml.safe_load(data)
                return ConfigType.YAML
            except: pass
            try:
                from ConfigParser import ConfigParser
                ConfigParser.readfp(StringIO(data))
                return ConfigType.INI
            except: pass
        return ConfigType.NA

    def __load(self, data=None):
        if self.fmt == ConfigType.JSON:
            import json
            if data is not None:
                return json.loads(data)
            else:
                with io.open(self.filename, 'r', encoding=self.encoding) as f:
                    return json.load(f)
        elif self.fmt == ConfigType.YAML:
            import yaml
            if data is not None:
                return yaml.safe_load(data)
            else:
                with io.open(self.filename, 'r', encoding=self.encoding) as f:
                    return yaml.safe_load(f)
        return {}

    def __dump(self):
        if self.filename is not None:
            if self.fmt == ConfigType.JSON:
                import json
                with io.open(self.filename, 'w', encoding=self.encoding) as f:
                    json.dump(self.data, f)
            elif self.fmt == ConfigType.YAML:
                import yaml
                with io.open(self.filename, 'w', encoding=self.encofing) as f:
                    yaml.safe_dump(self.data, f)

    def _get(self, var, create=False):
        current = self.data
        for part in var.split('.'):
            if isinstance(current, dict):
                if part in current:
                    current = current[part]
                elif create:
                    current = current.setdefault(part, {})
                else:
                    raise Cfg.NotFound(var)
            elif isinstance(current, list):
                try:
                    part = int(part, 10)
                    current = current[part]
                except:
                    raise Cfg.NotFound(var)
            else:
                raise Cfg.NotFound(var)
        return current

    def get(self, var):
        return self._get(var)

    def set(self, var, value):
        if '.' in var:
            path, _, item = var.rpartition('.')
            current = self._get(path, create=True)
        else:
            current = self.data
            item = var
        if isinstance(current, dict):
            current[item] = value
        elif isinstance(current, list):
            item = int(item, 10)
            current[item] = value
        self.__dump()

    def delete(self, var):
        try:
            if '.' in var:
                path, _, item = var.rpartition('.')
                current = self._get(path)
            else:
                current = self.data
                item = var
            if isinstance(current, dict):
                del current[item]
            elif isinstance(current, list):
                item = int(item, 10)
                current.pop(item)
            self.__dump()
        except Cfg.NotFound:
            pass

    def insert(self, var, value, index=None):
        '''Inserts at the index, and if the index is not provided
        appends to the end of the list
        '''
        current = self._get(var)
        if not isinstance(current, list):
            raise ConfigError('Item is not a list')
        if index is None:
            current.append(value)
        else:
            current.insert(index, value)
        self.__dump()

    def __repr__(self):
        return 'Cfg(%s)' % pprint.saferepr(self.data)

class Config(object):
    '''Base class for configuration management'''
    def __init__(self, data, fmt=ConfigType.NA, encoding='utf-8'):
        self.__cfgs = []
        self.attach(data, fmt, encoding)

    @property
    def current(self):
        return self.__cfgs[0]

    def attach(self, data, fmt=ConfigType.NA, encoding='utf-8'):
        self.__cfgs.insert(0, Cfg(data, fmt, encoding))

    def get(self, var, default=None):
        for cfg in self.__cfgs:
            try:
                return cfg.get(var)
            except Cfg.NotFound:
                pass
        return default

    def set(self, var, value):
        self.current.set(var, value)

    def delete(self, var):
        for cfg in self.__cfgs:
            cfg.delete(var)

    def insert(self, var, value, index=None):
        self.current.insert(var, value, index)

    def __repr__(self):
        def merge(d1, d2):
            for key in d2:
                if key not in d1:
                    d1[key] = copy.deepcopy(d2[key])
                elif isinstance(d2[key], dict):
                    merge(d1[key], d2[key])
                else:
                    d1[key] = copy.deepcopy(d2[key])
        d = {}
        for cfg in reversed(self.__cfgs):
            merge(d, cfg.data)
        return 'Config(%s)' % pprint.saferepr(d)

if __name__ == '__main__':
    c = Config({'foo': {'bar' : 3}})
    print(c.get('foo'))
    print(c.get('foo.bar'))
<|endoftext|>


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

import sys
import time
import socketserver
from multiprocessing import Process, Queue
from turret_tcphandler import TurretTCPHandler
from turret_command import TurretCommand as command
from servo import ServoClass
from laser import LaserClass
from camera import CameraClass

class TurretClass(object):
    '''
        docstring for TurretClass
    '''
    def __init__(self):
        super(TurretClass, self).__init__()
        self.laser = LaserClass()
        self.servo_x = ServoClass(0)
        self.servo_y = ServoClass(1)
        self.camera = CameraClass()
        self.manualmode = False

    def turn_left(self):
        '''
            Turns the turret left
        '''
        self.servo_x.decrease()

    def turn_right(self):
        '''
            Turns the turret right
        '''
        self.servo_x.increase()

    def vertical_reset(self):
        '''
            Returns turret to initial vertical state
        '''
        self.servo_x.reset()

    def turn_up(self):
        '''
            Turns the turret up
        '''
        self.servo_y.increase()

    def turn_down(self):
        '''
            Turns the turret down
        '''
        self.servo_y.decrease()

    def horizontal_reset(self):
        '''
            Returns turret to initial horizontal state
        '''
        self.servo_y.reset()

    def get_angle(self):
        '''
            TODO: Is this function needed?
        '''
        return {'x': self.servo_x.angle, 'y': self.servo_y.angle}

    def fire_laser(self):
        '''
            Fire the laser
        '''
        self.laser.fire()

    def restart(self):
        '''
            Resets the turret
        '''
        print("Restarting software...")
        self.vertical_reset()
        self.horizontal_reset()
        self.laser.turn_off()

    def toggle_mode(self):
        '''
            TODO: Decide if this is needed?
        '''
        self.manualmode = not self.manualmode
        print("Manualmode: " + str(self.manualmode))

    def run(self):
        '''
            Main loop that handles the turret.
        '''
        HOST, PORT = "0.0.0.0", 9999
        server = socketserver.TCPServer((HOST, PORT), TurretTCPHandler)
        try:
            servostate = command.ServoState
            laserstate = command.LaserState
            server.command_queue = Queue()
            server.connected_clients = 0
            p = Process(target=server.serve_forever)
            p.start()
            while True:
                #TODO: This code is fugly.
                #will fix after some refactoring
                msg = server.command_queue.get()
                if servostate(msg.servo_x) == servostate.inc:
                    self.turn_right()
                elif servostate(msg.servo_x) == servostate.dec:
                    self.turn_left()
                elif servostate(msg.servo_x) == servostate.off:
                    pass
                elif servostate(msg.servo_x) == servostate.reset:
                    self.horizontal_reset()
                if servostate(msg.servo_y) == servostate.inc:
                    self.turn_up()
                elif servostate(msg.servo_y) == servostate.dec:
                    self.turn_down()
                elif servostate(msg.servo_y) == servostate.off:
                    pass
                elif servostate(msg.servo_y) == servostate.reset:
                    self.vertical_reset()
                if laserstate(msg.laser) == laserstate.on:
                    self.laser.turn_on()
                elif laserstate(msg.laser) == laserstate.off:
                    self.laser.turn_off()
        except KeyboardInterrupt:
            print("Exiting server loop")
        finally:
            server.server_close()

if __name__ == '__main__':
    turret = TurretClass()
    turret.run()
<commit_msg>Removed unused import<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import socketserver
from multiprocessing import Process, Queue
from turret_tcphandler import TurretTCPHandler
from turret_command import TurretCommand as command
from servo import ServoClass
from laser import LaserClass
from camera import CameraClass

class TurretClass(object):
    '''
        docstring for TurretClass
    '''
    def __init__(self):
        super(TurretClass, self).__init__()
        self.laser = LaserClass()
        self.servo_x = ServoClass(0)
        self.servo_y = ServoClass(1)
        self.camera = CameraClass()
        self.manualmode = False

    def turn_left(self):
        '''
            Turns the turret left
        '''
        self.servo_x.decrease()

    def turn_right(self):
        '''
            Turns the turret right
        '''
        self.servo_x.increase()

    def vertical_reset(self):
        '''
            Returns turret to initial vertical state
        '''
        self.servo_x.reset()

    def turn_up(self):
        '''
            Turns the turret up
        '''
        self.servo_y.increase()

    def turn_down(self):
        '''
            Turns the turret down
        '''
        self.servo_y.decrease()

    def horizontal_reset(self):
        '''
            Returns turret to initial horizontal state
        '''
        self.servo_y.reset()

    def get_angle(self):
        '''
            TODO: Is this function needed?
        '''
        return {'x': self.servo_x.angle, 'y': self.servo_y.angle}

    def fire_laser(self):
        '''
            Fire the laser
        '''
        self.laser.fire()

    def restart(self):
        '''
            Resets the turret
        '''
        print("Restarting software...")
        self.vertical_reset()
        self.horizontal_reset()
        self.laser.turn_off()

    def toggle_mode(self):
        '''
            TODO: Decide if this is needed?
        '''
        self.manualmode = not self.manualmode
        print("Manualmode: " + str(self.manualmode))

    def run(self):
        '''
            Main loop that handles the turret.
        '''
        HOST, PORT = "0.0.0.0", 9999
        server = socketserver.TCPServer((HOST, PORT), TurretTCPHandler)
        try:
            servostate = command.ServoState
            laserstate = command.LaserState
            server.command_queue = Queue()
            server.connected_clients = 0
            p = Process(target=server.serve_forever)
            p.start()
            while True:
                #TODO: This code is fugly.
                #will fix after some refactoring
                msg = server.command_queue.get()
                if servostate(msg.servo_x) == servostate.inc:
                    self.turn_right()
                elif servostate(msg.servo_x) == servostate.dec:
                    self.turn_left()
                elif servostate(msg.servo_x) == servostate.off:
                    pass
                elif servostate(msg.servo_x) == servostate.reset:
                    self.horizontal_reset()
                if servostate(msg.servo_y) == servostate.inc:
                    self.turn_up()
                elif servostate(msg.servo_y) == servostate.dec:
                    self.turn_down()
                elif servostate(msg.servo_y) == servostate.off:
                    pass
                elif servostate(msg.servo_y) == servostate.reset:
                    self.vertical_reset()
                if laserstate(msg.laser) == laserstate.on:
                    self.laser.turn_on()
                elif laserstate(msg.laser) == laserstate.off:
                    self.laser.turn_off()
        except KeyboardInterrupt:
            print("Exiting server loop")
        finally:
            server.server_close()

if __name__ == '__main__':
    turret = TurretClass()
    turret.run()
<|endoftext|>