<commit_before># Copyright 2016-2017 Canonical Ltd.
#
# This file is part of the Snap layer for Juju.
#
# 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 os
import subprocess

from charmhelpers.core import hookenv
from charms import layer
from charms import reactive
from charms.reactive.helpers import any_file_changed, data_changed
from time import sleep


def install(snapname, **kw):
    '''Install a snap.

    Snap will be installed from the coresponding resource if available,
    otherwise from the Snap Store.

    Sets the snap.installed.{snapname} state.

    If the snap.installed.{snapname} state is already set then the refresh()
    function is called.
    '''
    installed_state = 'snap.installed.{}'.format(snapname)
    if reactive.is_state(installed_state):
        refresh(snapname, **kw)
    else:
        if hookenv.has_juju_version('2.0'):
            res_path = _resource_get(snapname)
            if res_path is False:
                _install_store(snapname, **kw)
            else:
                _install_local(res_path, **kw)
        else:
            _install_store(snapname, **kw)
        reactive.set_state(installed_state)


def refresh(snapname, **kw):
    '''Update a snap.

    Snap will be pulled from the coresponding resource if available
    and reinstalled if it has changed. Otherwise a 'snap refresh' is
    run updating the snap from the Snap Store, potentially switching
    channel and changing confinement options.
    '''
    # Note that once you upload a resource, you can't remove it.
    # This means we don't need to cope with an operator switching
    # from a resource provided to a store provided snap, because there
    # is no way for them to do that. Well, actually the operator could
    # upload a zero byte resource, but then we would need to uninstall
    # the snap before reinstalling from the store and that has the
    # potential for data loss.
    if hookenv.has_juju_version('2.0'):
        res_path = _resource_get(snapname)
        if res_path is False:
            _refresh_store(snapname, **kw)
        else:
            _install_local(res_path, **kw)
    else:
        _refresh_store(snapname, **kw)


def remove(snapname):
    hookenv.log('Removing snap {}'.format(snapname))
    subprocess.check_call(['snap', 'remove', snapname],
                          universal_newlines=True)
    reactive.remove_state('snap.installed.{}'.format(snapname))


def connect(plug, slot):
    '''Connect or reconnect a snap plug with a slot.

    Each argument must be a two element tuple, corresponding to
    the two arguments to the 'snap connect' command.
    '''
    hookenv.log('Connecting {} to {}'.format(plug, slot), hookenv.DEBUG)
    subprocess.check_call(['snap', 'connect', plug, slot],
                          universal_newlines=True)


def connect_all():
    '''Connect or reconnect all interface connections defined in layer.yaml.

    This method will fail if called before all referenced snaps have been
    installed.
    '''
    opts = layer.options('snap')
    for snapname, snap_opts in opts.items():
        for plug, slot in snap_opts.get('connect', []):
            connect(plug, slot)


def disable(snapname):
    '''Disables a snap in the system
    '''
    hookenv.log('Disabling {} snap'.format(snapname))
    subprocess.check_call(['snap', 'disable', snapname], 
                          universal_newlines=True)
    reactive.set_state('snap.disabled.{}'.format(snapname))


def enable(snapname):
    '''Enables a snap in the system
    '''
    hookenv.log('Enabling {} snap'.format(snapname))
    subprocess.check_call(['snap', 'enable', snapname], 
                          universal_newlines=True)
    reactive.remove_state('snap.disabled.{}'.format(snapname))


def _snap_args(channel='stable', devmode=False, jailmode=False,
               dangerous=False, force_dangerous=False, connect=None,
               classic=False, revision=None):
    if channel != 'stable':
        yield '--channel={}'.format(channel)
    if devmode is True:<commit_msg>Added set and get config functions<commit_after># Copyright 2016-2017 Canonical Ltd.
#
# This file is part of the Snap layer for Juju.
#
# 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 os
import subprocess

from charmhelpers.core import hookenv
from charms import layer
from charms import reactive
from charms.reactive.helpers import any_file_changed, data_changed
from time import sleep


def install(snapname, **kw):
    '''Install a snap.

    Snap will be installed from the coresponding resource if available,
    otherwise from the Snap Store.

    Sets the snap.installed.{snapname} state.

    If the snap.installed.{snapname} state is already set then the refresh()
    function is called.
    '''
    installed_state = 'snap.installed.{}'.format(snapname)
    if reactive.is_state(installed_state):
        refresh(snapname, **kw)
    else:
        if hookenv.has_juju_version('2.0'):
            res_path = _resource_get(snapname)
            if res_path is False:
                _install_store(snapname, **kw)
            else:
                _install_local(res_path, **kw)
        else:
            _install_store(snapname, **kw)
        reactive.set_state(installed_state)


def refresh(snapname, **kw):
    '''Update a snap.

    Snap will be pulled from the coresponding resource if available
    and reinstalled if it has changed. Otherwise a 'snap refresh' is
    run updating the snap from the Snap Store, potentially switching
    channel and changing confinement options.
    '''
    # Note that once you upload a resource, you can't remove it.
    # This means we don't need to cope with an operator switching
    # from a resource provided to a store provided snap, because there
    # is no way for them to do that. Well, actually the operator could
    # upload a zero byte resource, but then we would need to uninstall
    # the snap before reinstalling from the store and that has the
    # potential for data loss.
    if hookenv.has_juju_version('2.0'):
        res_path = _resource_get(snapname)
        if res_path is False:
            _refresh_store(snapname, **kw)
        else:
            _install_local(res_path, **kw)
    else:
        _refresh_store(snapname, **kw)


def remove(snapname):
    hookenv.log('Removing snap {}'.format(snapname))
    subprocess.check_call(['snap', 'remove', snapname],
                          universal_newlines=True)
    reactive.remove_state('snap.installed.{}'.format(snapname))


def connect(plug, slot):
    '''Connect or reconnect a snap plug with a slot.

    Each argument must be a two element tuple, corresponding to
    the two arguments to the 'snap connect' command.
    '''
    hookenv.log('Connecting {} to {}'.format(plug, slot), hookenv.DEBUG)
    subprocess.check_call(['snap', 'connect', plug, slot],
                          universal_newlines=True)


def connect_all():
    '''Connect or reconnect all interface connections defined in layer.yaml.

    This method will fail if called before all referenced snaps have been
    installed.
    '''
    opts = layer.options('snap')
    for snapname, snap_opts in opts.items():
        for plug, slot in snap_opts.get('connect', []):
            connect(plug, slot)


def disable(snapname):
    '''Disables a snap in the system

    This method doesn't affect any snap state if requested snap does not
    exist
    '''
    hookenv.log('Disabling {} snap'.format(snapname))
    subprocess.check_call(['snap', 'disable', snapname], 
                          universal_newlines=True)
    reactive.set_state('snap.disabled.{}'.format(snapname))


def enable(snapname):
    '''Enables a snap in the system

    This method doesn't affect any snap state if requeted snap does not
    exist
    '''
    hookenv.log('Enabling {} snap'.format(snapname))
    subprocess.check_call(['snap', 'enable', snapname], 
                          universal_newlines=True)
    reactive.remove_state('snap.disabled.{}'.format(snapname))


def set(snapname, key, value):
    '''Changes configuration options in a snap

    This method will fail if snapname is not an installed snap
    '''
    hookenv.log('Set config {}={} for snap {}'.format(key, value, snapname))
    subprocess.check_call(
        ['snap', 'set', snapname, '{}={}'.format(key, value)])


def get(snapname, key):
    '''Gets configuration options for a snap

    This method returns the output that snactl get command prints out.
    This method will fail if snapname is not an installed snap
    '''
    hookenv.log('Get config {} for snap {}'.format(key, snapname))
    return subprocess.check_output(['snap', 'get', snapname, key])


def _snap_args(channel='stable', devmode=False, jailmode=False,
               dangerous=False, force_dangerous=False, connect=None,
               classic=False, revision=None):
    if channel != 'stable':
        yield '--channel={}'.format(channel)
    if devmode is True:
{'fraction_non_alphanumeric': 0.09556828459451311, 'fraction_numerical': 0.00321575721033062, 'mean_word_length': 3.072013093289689, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2325822', 'n_tokens_mistral': 2802, 'n_tokens_neox': 2690, 'n_words': 1000}