<commit_before># No shebang line, this module is meant to be imported
#
# Copyright 2013 <NAME>
#
# 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.

import re
import os
from warnings import warn

from sqlalchemy.engine.url import URL
from sqlalchemy.engine import create_engine
from sqlalchemy.exc import OperationalError

from pyfarm.ext.config.core.loader import Loader
from pyfarm.ext.config.core.errors import PreferencesError
from pyfarm.ext.config.core.warning import MissingConfigWaring


class DBConfigError(PreferencesError):
    """raised when there's trouble either parsing or finding a db config"""


class DBConfig(Loader):
    """
    Custom class which allows for specific behaviors when working
    with the database.yml config.
    """
    REGEX_CONFIG = re.compile("^configs[.].+$")
    FILENAME = "database.yml"

    def engines(self, config_name, test=True):
        """
        Generator which yields all engines for the provided configuration.

        :param string config_name:
            The configuration name to use.  Using `production` would search
            database configurations matching `configs.production`.

        :param bool test:
            if True then iterate over each configuration but only
            yield those that we can successfully connect to
        """
        for url in self.get("configs.%s" % config_name):
            engine = create_engine(url)

            if test:
                try:
                    engine.connect()

                except OperationalError:  # TODO: add warning logger
                    warn(
                        "failed to connect to %s" % str(url),
                        SQLConnectionWarning
                    )
                    continue

            yield engine
    # end engines

    def engine(self, config_name, test=True):
        """
        convenience method which returns a single engine from :meth:`engines`
        """
        for engine in self.engines(config_name, test=test):
            return engine
    # end engine

    def get(self, key, failobj=None):
        """
        Same as :meth:`Loader.get` except for database configurations
        which will return a a list of :class:`URL` object.
        """
        value = Loader.get(self, key, failobj=failobj)

        if self.REGEX_CONFIG.match(key):
            configs = [value] if isinstance(value, basestring) else value
            value = []

            if configs is None:
                raise DBConfigError("no configurations for `%s`" % key)

            for config_name in configs:
                try:
                    config = self[config_name].copy()

                except KeyError:  # TODO: add warning logger
                    msg = "database configuration `%s` " % config_name
                    msg += "does not exist, skipping"
                    warn(msg, MissingConfigWaring)

                else:
                    if "database" in config:
                        config["database"] = os.path.expandvars(
                            config["database"]
                        )

                    # attempt to get the engine otherwise
                    # fail (required key)
                    try:
                        engine = config.pop("engine")
                    except KeyError:
                        raise DBConfigError(
                            "missing `engine` in configs.%s" % config_name
                        )

                    driver_parts = [engine]
                    driver = config.pop("driver", None)

                    if driver is not None:
                        driver_parts.append(driver)

                    # TODO: engine does NOT properly handle sqlite urls

                    value.append(URL("+".join(driver_parts), **config))

        return value
    # end get
# end Database<commit_msg>now only returns the database url (flask handles the engine for us)<commit_after># No shebang line, this module is meant to be imported
#
# Copyright 2013 <NAME>
#
# 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.

import re
import os

from sqlalchemy.engine.url import URL

from pyfarm.ext.config.core.loader import Loader
from pyfarm.config.core.errors import PreferencesError


class DBConfigError(PreferencesError):
    """raised when there's trouble either parsing or finding a db config"""


class DBConfig(Loader):
    """
    Custom class which allows for specific behaviors when working
    with the database.yml config.
    """
    REGEX_CONFIG = re.compile("^configs[.].+$")
    FILENAME = "database.yml"

    def url(self, config_name):
        """
        convenience method which returns the url for the given configuration
        name
        """
        return self.get("configs.%s" % config_name)

    def get(self, key, failobj=None):
        """
        Same as :meth:`Loader.get` except for database configurations
        which will return a a list of :class:`URL` object.
        """
        if not self.REGEX_CONFIG.match(key):
            return Loader.get(self, key, failobj=failobj)

        else:
            config_value = Loader.get(self, key, failobj=failobj)


            if config_value is None:
                raise DBConfigError("no configurations for `%s`" % key)

            try:
                config = self[config_value].copy()

            except KeyError:
                msg = "database configuration `%s` " % config_value
                msg += "does not exist, skipping"
                raise DBConfigError(msg)

            # expand any environment variables in the database name
            if "database" in config:
                config["database"] = os.path.expandvars(config["database"])

            # attempt to get the engine otherwise
            # fail (required key)
            try:
                engine = config.pop("engine")
            except KeyError:
                raise DBConfigError("missing `engine` in configs.%s" %
                                    config_value)

            driver_parts = [engine]
            driver = config.pop("driver", None)

            if driver is not None:
                driver_parts.append(driver)

            return str(URL("+".join(driver_parts), **config))
{'fraction_non_alphanumeric': 0.07948397836038286, 'fraction_numerical': 0.0022194479123318076, 'mean_word_length': 1.9781082197439075, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7346595', 'n_tokens_mistral': 1841, 'n_tokens_neox': 1722, 'n_words': 656}