<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
#    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/>.
#
##############################################################################

from osv import fields, osv
import tools
import time

class res_log(osv.osv_memory):
    _name = 'res.log'
    _columns = {
        'name': fields.char('Message', size=128, help='The logging message.', required=True),
        'user_id': fields.many2one('res.users','User', required=True),
        'res_model': fields.char('Object', size=128),
        'context': fields.char('Context', size=250),
        'res_id': fields.integer('Object ID'),
        'secondary': fields.boolean('Secondary Log', help='Do not display this log if it belongs to the same object the user is working on'),
        'create_date': fields.datetime('Created Date', readonly=True),
        'read': field.boolean('Read status', help="If this log item has been read, get() should not send it to the client")
    }
    _defaults = {
        'user_id': lambda self,cr,uid,ctx: uid,
        'create_date': time.strftime('%Y-%m-%d %H:%M:%S'),
        'context': lambda *args: "{}",
        'read': False
    }
    _order='create_date desc'

    # TODO: do not return secondary log if same object than in the model (but unlink it)
    def get(self, cr, uid, context=None):
        unread_log_ids = self.search(cr, uid, [('user_id','=',uid),
                                               ('read', '=', False)],
                                     context=context)
        unread_logs = self.read(cr, uid, unread_log_ids,
                                ['name','res_model','res_id'],
                                context=context)
        self.write(cr, uid, ids, {'read': True}, context=context)
        return unread_logs

    def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
        res = []
        log_ids = super(res_log, self).search(cr, uid, args, offset, limit, order, context, count)
        logs = {}
        for log in self.browse(cr, uid, log_ids, context=context):
            res_dict = logs.get(log.res_model, {})
            res_dict.update({log.res_id: log.id})
            logs.update({log.res_model: res_dict})
        res = map(lambda x: x.values(), logs.values())
        return tools.flatten(res)

res_log()

<commit_msg>[IMP] res.log: no need to use lambda for a constant in trunk<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
#    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/>.
#
##############################################################################

from osv import fields, osv
import tools
import time

class res_log(osv.osv_memory):
    _name = 'res.log'
    _columns = {
        'name': fields.char('Message', size=128, help='The logging message.', required=True),
        'user_id': fields.many2one('res.users','User', required=True),
        'res_model': fields.char('Object', size=128),
        'context': fields.char('Context', size=250),
        'res_id': fields.integer('Object ID'),
        'secondary': fields.boolean('Secondary Log', help='Do not display this log if it belongs to the same object the user is working on'),
        'create_date': fields.datetime('Created Date', readonly=True),
        'read': field.boolean('Read status', help="If this log item has been read, get() should not send it to the client")
    }
    _defaults = {
        'user_id': lambda self,cr,uid,ctx: uid,
        'create_date': time.strftime('%Y-%m-%d %H:%M:%S'),
        'context': "{}",
        'read': False
    }
    _order='create_date desc'

    # TODO: do not return secondary log if same object than in the model (but unlink it)
    def get(self, cr, uid, context=None):
        unread_log_ids = self.search(cr, uid, [('user_id','=',uid),
                                               ('read', '=', False)],
                                     context=context)
        unread_logs = self.read(cr, uid, unread_log_ids,
                                ['name','res_model','res_id'],
                                context=context)
        self.write(cr, uid, ids, {'read': True}, context=context)
        return unread_logs

    def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
        res = []
        log_ids = super(res_log, self).search(cr, uid, args, offset, limit, order, context, count)
        logs = {}
        for log in self.browse(cr, uid, log_ids, context=context):
            res_dict = logs.get(log.res_model, {})
            res_dict.update({log.res_id: log.id})
            logs.update({log.res_model: res_dict})
        res = map(lambda x: x.values(), logs.values())
        return tools.flatten(res)

res_log()
<|endoftext|>


<commit_before># vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright (c) 2015 John Dewey
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

from ddt import data
from ddt import ddt
from ddt import unpack
from flask import json
import unittest2 as unittest

from demeter.app import api as app
from tests import helper

@ddt
class TestApi(unittest.TestCase):
    def setUp(self):
        self._app = app.app.test_client()
        self._ns_name, self._ns_cidr, self._family = helper.namespace_data()

    def _create_namespace(self, ns_name, cidr, family):
        url = self.namespace_url(ns_name)
        return self._post(url, {'cidr': cidr, 'family': family})

    def _delete_namespace(self, url):
        url = self.namespace_url(self._ns_name)
        return self._app.delete(url)

    def _post(self, url, data):
        return self._app.post(url,
                              content_type='application/json',
                              data=json.dumps(data))

    def setup_teardown_namespace(func):
        def wrapper(self, *args, **kwargs):
            self._create_namespace(self._ns_name, self._ns_cidr, self._family)

            func(self, *args, **kwargs)

            self._delete_namespace(self._ns_name)
        return wrapper

    def namespace_url(self, ns_name):
        return '/v1.0/namespace/{0}'.format(ns_name)

    def test_app_index(self):
        response = self._app.get('/v1.0/status')
        data = json.loads(response.data)

        self.assertEquals(200, response.status_code)
        self.assertEquals(True, data['success'])

    @setup_teardown_namespace
    def test_app_all_namespaces(self):
        response = self._app.get('/v1.0/namespaces')
        data = json.loads(response.data)

        self.assertEquals(200, response.status_code)
        assert self._ns_name in data['namespace']

    @unpack
    @data(helper.namespace_data())
    def test_app_create_namespace(self, ns_name, cidr, family):
        response = self._create_namespace(ns_name, cidr, family)
        data = json.loads(response.data)

        self.assertEquals(200, response.status_code)
        self.assertEquals(ns_name, data['namespace']['name'])
        self.assertEquals(cidr, data['namespace']['cidr'])
        self.assertEquals('inet', data['namespace']['family'])

        self._delete_namespace(ns_name)

    @unpack
    @data(helper.namespace_data())
    def test_app_create_namespace_returns_409_when_exists(self,
                                                          ns_name,
                                                          cidr,
                                                          family):
        self._create_namespace(ns_name, cidr, family)
        response = self._create_namespace(ns_name, cidr, family)

        self.assertEquals(409, response.status_code)

        self._delete_namespace(ns_name)

    @setup_teardown_namespace
    def test_app_show_namespace(self):
        url = self.namespace_url(self._ns_name)
        # TODO(retr0h): populate address
        response = self._app.get(url)
        data = json.loads(response.data)

        self.assertEquals(200, response.status_code)
        self.assertEquals(self._ns_name, data['namespace']['name'])
        self.assertEquals('198.51.100.0/24', data['namespace']['cidr'])
        self.assertEquals('inet', data['namespace']['family'])
<commit_msg>Use url_for to construct urls<commit_after># vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright (c) 2015 John Dewey
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

from ddt import data
from ddt import ddt
from ddt import unpack
from flask import json
from flask import url_for
import unittest2 as unittest

from demeter.app import api as app
from tests import helper

@ddt
class TestApi(unittest.TestCase):
    def setUp(self):
        self._app = app.app.test_client()
        self._ns_name, self._ns_cidr, self._family = helper.namespace_data()

    def _create_namespace(self, ns_name, cidr, family):
        url = self._namespace_url('create_namespace', ns_name)
        return self._post(url, {'cidr': cidr, 'family': family})

    def _delete_namespace(self, ns_name):
        url = self._namespace_url('delete_namespace', ns_name)
        return self._app.delete(url)

    def _get_namespace(self, ns_name):
        url = self._namespace_url('show_namespace', ns_name)
        return self._app.get(url)

    def _post(self, url, data):
        return self._app.post(url,
                              content_type='application/json',
                              data=json.dumps(data))

    def _namespace_url(self, endpoint, name):
        with app.app.test_request_context():
            return url_for(endpoint, name=name)

    def setup_teardown_namespace(func):
        def wrapper(self, *args, **kwargs):
            self._create_namespace(self._ns_name, self._ns_cidr, self._family)

            func(self, *args, **kwargs)

            self._delete_namespace(self._ns_name)
        return wrapper

    def test_app_index(self):
        response = self._app.get('/v1.0/status')
        data = json.loads(response.data)

        self.assertEquals(200, response.status_code)
        self.assertEquals(True, data['success'])

    @setup_teardown_namespace
    def test_app_all_namespaces(self):
        response = self._app.get('/v1.0/namespaces')
        data = json.loads(response.data)

        self.assertEquals(200, response.status_code)
        assert self._ns_name in data['namespace']

    @setup_teardown_namespace
    def test_app_create_namespace(self):
        response = self._get_namespace(self._ns_name)
        data = json.loads(response.data)

        self.assertEquals(200, response.status_code)
        self.assertEquals(self._ns_name, data['namespace']['name'])
        self.assertEquals(self._ns_cidr, data['namespace']['cidr'])
        self.assertEquals('inet', data['namespace']['family'])

    @unpack
    @data(helper.namespace_data())
    def test_app_create_namespace_returns_409_when_exists(self,
                                                          ns_name,
                                                          cidr,
                                                          family):
        self._create_namespace(ns_name, cidr, family)
        response = self._create_namespace(ns_name, cidr, family)

        self.assertEquals(409, response.status_code)

        self._delete_namespace(ns_name)

    @setup_teardown_namespace
    def test_app_show_namespace(self):
        response = self._get_namespace(self._ns_name)
        data = json.loads(response.data)

        self.assertEquals(200, response.status_code)
        self.assertEquals(self._ns_name, data['namespace']['name'])
        self.assertEquals('198.51.100.0/24', data['namespace']['cidr'])
        self.assertEquals('inet', data['namespace']['family'])
<|endoftext|>


<commit_before># Copyright (c) 2014-2015, Ruslan Baratov
# All rights reserved.

import os
import sys

import detail.call

def run(generate_command, build_dir, polly_temp_dir, reconfig, logging):
  if not os.path.exists(polly_temp_dir):
    os.makedirs(polly_temp_dir)
  saved_arguments_path = os.path.join(polly_temp_dir, 'saved-arguments')
  cache_file = os.path.join(build_dir, 'CMakeCache.txt')

  generate_command_oneline = ' '.join(
      [ '"{}"'.format(x) for x in generate_command]
  )

  if reconfig or not os.path.exists(saved_arguments_path):
    detail.call.call(generate_command, logging, cache_file=cache_file)
    open(saved_arguments_path, 'w').write(generate_command_oneline)
    return

  # No need to generate project, just check that arguments not changed
  expected = open(saved_arguments_path, 'r').read()
  if expected != generate_command_oneline:
    sys.exit(
        "\n== WARNING ==\n"
        "\nLooks like cmake arguments changed."
        " You have two options to fix it:\n"
        "  * Remove build directory completely"
        " by adding '--clear' (works 100%)\n"
        "  * Run configure again by adding '--reconfigure'"
        " (you must understand how CMake cache variables works/updated)\n\n"
        "  Expected: {}\n\n"
        "  Current: {}\n\n".format(expected, generate_command_oneline)
    )
<commit_msg>Use difflib to print difference<commit_after># Copyright (c) 2014-2015, Ruslan Baratov
# All rights reserved.

import difflib
import os
import sys

import detail.call

def run(generate_command, build_dir, polly_temp_dir, reconfig, logging):
  if not os.path.exists(polly_temp_dir):
    os.makedirs(polly_temp_dir)
  saved_arguments_path = os.path.join(polly_temp_dir, 'saved-arguments')
  cache_file = os.path.join(build_dir, 'CMakeCache.txt')

  generate_command_oneline = ' '.join(
      [ '"{}"'.format(x) for x in generate_command]
  )

  if reconfig or not os.path.exists(saved_arguments_path):
    detail.call.call(generate_command, logging, cache_file=cache_file)
    open(saved_arguments_path, 'w').write(generate_command_oneline)
    return

  # No need to generate project, just check that arguments not changed
  expected = open(saved_arguments_path, 'r').read()
  if expected != generate_command_oneline:
    sys.exit(
        "\n== WARNING ==\n"
        "\nLooks like cmake arguments changed."
        " You have two options to fix it:\n"
        "  * Remove build directory completely"
        " by adding '--clear' (works 100%)\n"
        "  * Run configure again by adding '--reconfigure'"
        " (you must understand how CMake cache variables works/updated)\n\n"
        "{}".format("\n".join(difflib.ndiff([expected], [generate_command_oneline])))
    )
<|endoftext|>


<commit_before>import unittest
import ml
import numpy as np

class TestDataset(unittest.TestCase):
    def setUp(self):
        NUM_FEATURES = 10
        self.X = np.append(np.zeros((5, NUM_FEATURES)), np.ones((5, NUM_FEATURES)), axis=0)
        self.Y = (np.sum(self.X, axis=1) / 10).astype(int)
        self.dataset = ml.ds.DataSetBuilder(
            "test",
            dataset_path="/tmp/",
            transforms=[('scale', None)],
            train_size=.5,
            valid_size=.2,
            validator="cross")
        self.dataset.build_dataset(self.X, self.Y)

    def test_build_dataset_dim_7_1_2(self):
        dataset = ml.ds.DataSetBuilder(
            "test",
            dataset_path="/tmp/",
            transforms=[('scale', None)],
            validator="cross")
        dataset.build_dataset(self.X, self.Y)
        self.assertEqual(dataset.train_labels.shape, (7,))
        self.assertEqual(dataset.valid_labels.shape, (1,))
        self.assertEqual(dataset.test_labels.shape, (2,))

    def test_build_dataset_dim_5_2_3(self):
        dataset = ml.ds.DataSetBuilder(
            "test",
            dataset_path="/tmp/",
            transforms=[('scale', None)],
            train_size=.5,
            valid_size=.2,
            validator="cross")
        dataset.build_dataset(self.X, self.Y)
        self.assertEqual(dataset.train_labels.shape, (5,))
        self.assertEqual(dataset.valid_labels.shape, (2,))
        self.assertEqual(dataset.test_labels.shape, (3,))

    def test_only_labels(self):
        dataset0, label0 = dataset.only_labels([0])
        self.assertTrue((dataset0 == (np.ones((5, 10))*-1)).all())
        self.assertItemsEqual(label0, np.zeros(5))
        dataset1, label1 = dataset.only_labels([1])
        self.assertTrue((dataset1 == np.ones((5, 10))).all())
        self.assertItemsEqual(label1, np.ones(5))

    def test_labels_info(self):
        labels_counter = self.dataset.labels_info()
        self.assertEqual(labels_counter[0], 5)
        self.assertEqual(labels_counter[1], 5)

    def test_density(self):
        self.assertEqual(self.dataset.density(), 1)
        self.assertEqual(self.dataset.density(axis=1), 1)

if __name__ == '__main__':
    unittest.main()
<commit_msg>added more tests<commit_after>import unittest
import ml
import numpy as np
import csv

class TestDataset(unittest.TestCase):
    def setUp(self):
        NUM_FEATURES = 10
        self.X = np.append(np.zeros((5, NUM_FEATURES)), np.ones((5, NUM_FEATURES)), axis=0)
        self.Y = (np.sum(self.X, axis=1) / 10).astype(int)
        self.dataset = ml.ds.DataSetBuilder(
            "test",
            dataset_path="/tmp/",
            transforms=[('scale', None)],
            train_size=.5,
            valid_size=.2,
            validator="cross")
        self.dataset.build_dataset(self.X, self.Y)

    def test_build_dataset_dim_7_1_2(self):
        dataset = ml.ds.DataSetBuilder(
            "test",
            dataset_path="/tmp/",
            transforms=[('scale', None)],
            validator="cross")
        dataset.build_dataset(self.X, self.Y)
        self.assertEqual(dataset.train_labels.shape, (7,))
        self.assertEqual(dataset.valid_labels.shape, (1,))
        self.assertEqual(dataset.test_labels.shape, (2,))

    def test_build_dataset_dim_5_2_3(self):
        self.assertEqual(self.dataset.train_labels.shape, (5,))
        self.assertEqual(self.dataset.valid_labels.shape, (2,))
        self.assertEqual(self.dataset.test_labels.shape, (3,))

    def test_only_labels(self):
        dataset0, label0 = dataset.only_labels([0])
        self.assertTrue((dataset0 == (np.ones((5, 10))*-1)).all())
        self.assertItemsEqual(label0, np.zeros(5))
        dataset1, label1 = dataset.only_labels([1])
        self.assertTrue((dataset1 == np.ones((5, 10))).all())
        self.assertItemsEqual(label1, np.ones(5))

    def test_labels_info(self):
        labels_counter = self.dataset.labels_info()
        self.assertEqual(labels_counter[0], 5)
        self.assertEqual(labels_counter[1], 5)

    def test_density(self):
        self.assertEqual(self.dataset.density(), 1)
        self.assertEqual(self.dataset.density(axis=1), 1)

class TestDatasetFile(unittest.TestCase):
    def setUp(self):
        NUM_FEATURES = 10
        self.X = np.append(np.zeros((5, NUM_FEATURES)), np.ones((5, NUM_FEATURES)), axis=0)
        self.Y = (np.sum(self.X, axis=1) / 10).astype(int)
        dataset = np.c_[self.X, self.Y]
        with open('test.csv', 'wb') as csvfile:
            csv_writer = csv.writer(csvfile, delimiter=',', quoting=csv.QUOTE_MINIMAL)
            csv_writer.writerow(map(str, range(10)) + ['target'])
            for row in dataset:
                csv_writer.writerow(row)

    def test_load(self):
        dataset = ml.ds.DataSetBuilderFile(
            "test",
            dataset_path="/tmp/",
            transforms=[('scale', None)],
            validator="cross")
        data, labels = dataset.from_csv('test.csv', 'target')
        self.assertItemsEqual(self.Y, labels.astype(int))

if __name__ == '__main__':
    unittest.main()
<|endoftext|>


<commit_before>from __future__ import print_function, division

import sys,os
quspin_path = os.path.join(os.getcwd(),"../")
sys.path.insert(0,quspin_path)

from quspin.operators import hamiltonian
from quspin.basis import spin_basis_general, boson_basis_general, spinless_fermion_basis_general, spinful_fermion_basis_general
from quspin.basis.transformations import square_lattice_trans
import numpy as np

#
###### define model parameters ######
Lx, Ly = 4, 4 # linear dimension of 2d lattice
N_2d = Lx*Ly # number of sites
#
###### setting up user-defined symmetry transformations for 2d lattice ######
s = np.arange(N_2d) # sites [0,1,2,....]
x = s%Lx # x positions for sites
y = s//Lx # y positions for sites

T_x = (x+1)%Lx + Lx*y # translation along x-direction
T_y = x +Lx*((y+1)%Ly) # translation along y-direction
Z   = -(s+1) # spin inversion

J_p=[[+np.sqrt(7),i,T_x[i]] for i in range(N_2d)] + [[+np.sqrt(7),i,T_y[i]] for i in range(N_2d)]
J_n=[[-np.sqrt(7),i,T_x[i]] for i in range(N_2d)] + [[-np.sqrt(7),i,T_y[i]] for i in range(N_2d)]

lattice_trans=square_lattice_trans(Lx,Ly)
allowed_sectors=lattice_trans.allowed_blocks_iter()

for ii,basis_dict in enumerate(allowed_sectors):

	###### setting up bases ######

	basis_boson = boson_basis_general(N_2d, make_basis=False,
										Nb=N_2d//4,sps=2,
										**basis_dict,
									)

	basis_boson_full = boson_basis_general(N_2d, make_basis=False,
										Nb=N_2d//4,sps=2,
									)

	basis_spin = spin_basis_general(N_2d, pauli=False, make_basis=False,
										Nup=N_2d//2,
										**basis_dict,
										zblock=(Z,0)
									)

	basis_spin_full = spin_basis_general(N_2d, pauli=False, make_basis=False,
										Nup=N_2d//2,
									)

	basis_fermion = spinless_fermion_basis_general(N_2d, make_basis=False,
										Nf=N_2d//2,
										**basis_dict,
									)

	basis_fermion_full = spinless_fermion_basis_general(N_2d, make_basis=False,
										Nf=N_2d//2,
									)

	basis_spinful_fermion = spinful_fermion_basis_general(N_2d, make_basis=False,
										Nf=(N_2d//8,N_2d//8),
										**basis_dict,
									)

	basis_spinful_fermion_full = spinful_fermion_basis_general(N_2d, make_basis=False,
										Nf=(N_2d//8,N_2d//8),
									)

	bases_2d=[basis_boson,basis_spin,basis_fermion,basis_spinful_fermion]
	bases_2d_full=[basis_boson_full,basis_spin_full,basis_fermion_full,basis_spinful_fermion_full]

	for i,(basis_2d,basis_2d_full,basis_2d_made,basis_2d_full_made) in enumerate(zip(bases_2d,bases_2d_full,bases_2d,bases_2d_full)):

		basis_2d_made.make(Ns_block_est=16000)
		basis_2d_full_made.make(Ns_block_est=16000)

		if i in [2,6]: # spinless fermions
			static=[['zz',J_p],['+-',J_p],['-+',J_n]]
		elif i in [3,7]: # spinful fermions
			static=[['zz|',J_p],['|zz',J_p],['+-|',J_p],['-+|',J_n],['|+-',J_p],['|-+',J_n]]
		else: # boson, spin
			static=[['zz',J_p],['+-',J_p],['-+',J_p]]

		print('# of states', i, basis_2d_made.Ns, basis_2d_full_made.Ns)

		H=hamiltonian(static,[],basis=basis_2d_made,dtype=np.complex128)
		E_GS,V_GS=H.eigsh(k=1,which='SA')

		states=basis_2d_made.states.copy()
		inds=[np.where(basis_2d_full.states==r)[0][0] for r in states]
		psi_GS=V_GS[:,0].copy()
		out=basis_2d.get_amp(states,amps=psi_GS,mode='representative')
		psi_tmp=basis_2d_made.get_vec(V_GS[:,0],pcon=True,sparse=False)[inds]
		np.testing.assert_allclose(psi_GS - psi_tmp,0.0,atol=1E-14,err_msg='failed representative mode comparison!')

		states_full=basis_2d_full_made.states.copy()
		psi_GS_full=basis_2d_made.get_vec(V_GS[:,0],pcon=True,sparse=False) #V_GS_full[:,0].astype(np.complex128)
		basis_2d.get_amp(states_full,amps=psi_GS_full,mode='full_basis')
		ref_states=np.sort( np.unique(states_full) )[::-1]
		psi_GS_full=psi_GS_full[inds]
		np.testing.assert_allclose(psi_GS_full - V_GS[:,0],0.0,atol=1E-14,err_msg='failed full_basis mode comparison!')

		print('test {0}/{1} passed'.format(ii,i))

<commit_msg>updating test<commit_after>from __future__ import print_function, division

import sys,os
quspin_path = os.path.join(os.getcwd(),"../")
sys.path.insert(0,quspin_path)

from quspin.operators import hamiltonian
from quspin.basis import spin_basis_general, boson_basis_general, spinless_fermion_basis_general, spinful_fermion_basis_general
from quspin.basis.transformations import square_lattice_trans
import numpy as np

#
###### define model parameters ######
Lx, Ly = 4, 4 # linear dimension of 2d lattice
N_2d = Lx*Ly # number of sites
#
###### setting up user-defined symmetry transformations for 2d lattice ######
s = np.arange(N_2d) # sites [0,1,2,....]
x = s%Lx # x positions for sites
y = s//Lx # y positions for sites

T_x = (x+1)%Lx + Lx*y # translation along x-direction
T_y = x +Lx*((y+1)%Ly) # translation along y-direction
Z   = -(s+1) # spin inversion

J_p=[[+np.sqrt(7),i,T_x[i]] for i in range(N_2d)] + [[+np.sqrt(7),i,T_y[i]] for i in range(N_2d)]
J_n=[[-np.sqrt(7),i,T_x[i]] for i in range(N_2d)] + [[-np.sqrt(7),i,T_y[i]] for i in range(N_2d)]

lattice_trans=square_lattice_trans(Lx,Ly)
allowed_sectors=lattice_trans.allowed_blocks_iter()

for ii,basis_dict in enumerate(allowed_sectors):

	###### setting up bases ######

	basis_boson = boson_basis_general(N_2d, make_basis=False,
										Nb=N_2d//4,sps=2,
										**basis_dict,
									)

	basis_boson_full = boson_basis_general(N_2d, make_basis=False,
										Nb=N_2d//4,sps=2,
									)

	basis_spin = spin_basis_general(N_2d, pauli=False, make_basis=False,
										Nup=N_2d//2,
										**basis_dict,
										zblock=(Z,0)
									)

	basis_spin_full = spin_basis_general(N_2d, pauli=False, make_basis=False,
										Nup=N_2d//2,
									)

	basis_fermion = spinless_fermion_basis_general(N_2d, make_basis=False,
										Nf=N_2d//2,
										**basis_dict,
									)

	basis_fermion_full = spinless_fermion_basis_general(N_2d, make_basis=False,
										Nf=N_2d//2,
									)

	basis_spinful_fermion = spinful_fermion_basis_general(N_2d, make_basis=False,
										Nf=(N_2d//8,N_2d//8),
										**basis_dict,
									)

	basis_spinful_fermion_full = spinful_fermion_basis_general(N_2d, make_basis=False,
										Nf=(N_2d//8,N_2d//8),
									)

	bases_2d=[basis_boson,basis_spin,basis_fermion,basis_spinful_fermion]
	bases_2d_full=[basis_boson_full,basis_spin_full,basis_fermion_full,basis_spinful_fermion_full]

	for i,(basis_2d,basis_2d_full,basis_2d_made,basis_2d_full_made) in enumerate(zip(bases_2d,bases_2d_full,bases_2d,bases_2d_full)):

		basis_2d_made.make(Ns_block_est=16000)
		basis_2d_full_made.make(Ns_block_est=16000)

		if i in [2,6]: # spinless fermions
			static=[['zz',J_p],['+-',J_p],['-+',J_n]]
		elif i in [3,7]: # spinful fermions
			static=[['zz|',J_p],['|zz',J_p],['+-|',J_p],['-+|',J_n],['|+-',J_p],['|-+',J_n]]
		else: # boson, spin
			static=[['zz',J_p],['+-',J_p],['-+',J_p]]

		print('# of states', i, basis_2d_made.Ns, basis_2d_full_made.Ns)

		H=hamiltonian(static,[],basis=basis_2d_made,dtype=np.complex128)
		E_GS,V_GS=H.eigsh(k=1,which='SA')

		states=basis_2d_made.states.copy()
		inds=[np.where(basis_2d_full.states==r)[0][0] for r in states]
		psi_GS=V_GS[:,0].copy()
		out=basis_2d.get_amp(states,amps=psi_GS,mode='representative')
		psi_tmp=basis_2d_made.get_vec(V_GS[:,0],pcon=True,sparse=False)[inds]
		np.testing.assert_allclose(psi_GS - psi_tmp,0.0,atol=1E-14,err_msg='failed representative mode comparison!')

		states_full=basis_2d_full_made.states.copy()
		psi_GS_full=basis_2d_made.get_vec(V_GS[:,0],pcon=True,sparse=False) #V_GS_full[:,0].astype(np.complex128)
		basis_2d.get_amp(states_full,amps=psi_GS_full,mode='full_basis')
		rep_states=basis_2d_made.representative(basis_2d_full_made.states)
		psi_GS_full=psi_GS_full[inds]
		np.testing.assert_allclose(psi_GS_full - V_GS[:,0],0.0,atol=1E-14,err_msg='failed full_basis mode comparison!')
		np.testing.assert_allclose(rep_states - states_full,0.0,atol=1E-14,err_msg='failed full_basis mode states comparison!')

		print('test {0}/{1} passed'.format(ii,i))

<|endoftext|>


<commit_before>"""
State module for restconf Proxy minions

:codeauthor: Jamie (Bear) Murphy <jamiemurphyit@gmail.com>
:maturity:   new
:platform:   any

"""

import json  # noqa: F401

from deepdiff import DeepDiff

# from salt.utils.odict import OrderedDict  # noqa: F401

def __virtual__():
    if "restconf.set_data" in __salt__:  # noqa: F821
        return True
    return (False, "restconf module could not be loaded")

def config_manage(name, uri, method, config, init_uri=None, init_method="PATCH"):
    """
    Ensure a specific value exists at a given path
    :param name: The name for this rule
    :type  name: ``str``
    :param uri: The restconf uri to set / get config
    :type  uri: ``str``
    :param method: rest method to use eg GET, PUT, POST, PATCH, DELETE
    :type method: ``str``
    :param config: The new value at the given path
    :type  config: ``dict``
    :param init_uri: Alternative URI incase the URI doesnt exist on first pass
    :type init_uri: ``str``
    :param init_method: Method to use on alternative URI when setting config, default: PATCH
    :type init_method: ``str``
    Examples:
    .. code-block:: yaml
        random name here:
          restconf.config_manage:
            - name: random_name_here
            - uri: restconf/data/Cisco-IOS-XE-native:native/interface/GigabitEthernet=1%2F0%2F3
            - config:
                Cisco-IOS-XE-native:GigabitEthernet:
                    description:
                        harro
                    name:
                        1/0/3
    """
    # TODO: add template function so that config var does not need to be passed
    ret = {"name": name, "result": False, "changes": {}, "comment": ""}
    found_working_uri = False
    uri_used = ""
    existing_raw = __salt__["restconf.get_data"](uri)  # noqa: F821
    request_uri = ""
    request_method = ""
    # TODO: this could probaby be a loop
    if existing_raw["status"] in [200]:
        existing = existing_raw["dict"]
        found_working_uri = True
        uri_used = "Primary"
        request_uri = uri
        request_method = method

    if not found_working_uri:
        existing_raw_init = __salt__["restconf.get_data"](init_uri)  # noqa: F821
        if existing_raw_init["status"] in [200]:
            existing = existing_raw_init["dict"]
            found_working_uri = True
            uri_used = "init"
            request_uri = init_uri
            request_method = init_method

    if not found_working_uri:
        ret["result"] = False
        ret["comment"] = "restconf could not find a working URI to get initial config"
        return ret
    # TODO: END

    dict_config = json.loads(
        json.dumps(config)
    )  # convert from orderedDict to Dict (which is now ordered by default in python3.8)

    if existing == dict_config:
        ret["result"] = True
        ret["comment"] = "Config is already set"

    elif __opts__["test"] is True:  # noqa: F821
        ret["result"] = None
        ret["comment"] = "Config will be added"
        diff = _restDiff(existing, dict_config)
        ret["changes"]["new"] = diff.added()
        ret["changes"]["removed"] = diff.removed()
        ret["changes"]["changed"] = diff.changed()

    else:
        resp = __salt__["restconf.set_data"](
            request_uri, request_method, dict_config
        )  # noqa: F821
        # Success
        if resp["status"] in [201, 200, 204]:
            ret["result"] = True
            ret["comment"] = "Successfully added config"
            diff = _restDiff(existing, dict_config)
            ret["changes"]["new"] = diff.added()
            ret["changes"]["removed"] = diff.removed()
            ret["changes"]["changed"] = diff.changed()
            if method == "PATCH":
                ret["changes"]["removed"] = None
        # full failure
        else:
            ret["result"] = False
            if "dict" in resp:
                why = resp["dict"]
            elif "body" in resp:
                why = resp["body"]
            else:
                why = None
            ret[
                "comment"
            ] = "failed to add / modify config. API Statuscode: {s}, API Response: {w}, URI:{u}".format(
                w=why, s=resp["status"], u=uri_used
            )
            print("post_content: {b}".format(b=json.dumps(dict_config)))

    return ret

class _restDiff:
    """
    Calculate the difference between two dictionaries as:
    (1) items added
    (2) items removed
    (3) keys same in both but changed values
    (4) keys same in both and unchanged values
    """

    def __init__(self, current_dict, past_dict):
        self.current_dict = current_dict
        self.past_dict = past_dict
        self.diff = DeepDiff(current_dict, past_dict)
        print("DeepDiff:")
        print(self.diff)
        self.diff_pretty = self.diff.pretty()

    def added(self):
        # TODO: Potential for new adds to get missed here.
        # need to dig into deepdiff more
        if "dictionary_item_added" in self.diff.keys():
            return str(self.diff["dictionary_item_added"])
        return None

    def removed(self):
        if "dictionary_item_removed" in self.diff.keys():
            return str(self.diff["dictionary_item_removed"])
        return None

    def changed(self):
        if "values_changed" in self.diff.keys():
            return str(self.diff["values_changed"])
        return None

    def unchanged(self):
        return None  # TODO: not implemented
<commit_msg>add requirements chefk to states module<commit_after>"""
State module for restconf Proxy minions

:codeauthor: Jamie (Bear) Murphy <jamiemurphyit@gmail.com>
:maturity:   new
:platform:   any

"""

import json  # noqa: F401

# from salt.utils.odict import OrderedDict  # noqa: F401

try:
    HAS_DEEPDIFF = True
    from deepdiff import DeepDiff
except ImportError:
    HAS_DEEPDIFF = False

def __virtual__():
    if not HAS_DEEPDIFF:
        return (
            False,
            "Missing dependency: The restconf states method requires the 'deepdiff' Python module.",
        )
    if "restconf.set_data" in __salt__:  # noqa: F821
        return True
    return (False, "restconf module could not be loaded")

def config_manage(name, uri, method, config, init_uri=None, init_method="PATCH"):
    """
    Ensure a specific value exists at a given path
    :param name: The name for this rule
    :type  name: ``str``
    :param uri: The restconf uri to set / get config
    :type  uri: ``str``
    :param method: rest method to use eg GET, PUT, POST, PATCH, DELETE
    :type method: ``str``
    :param config: The new value at the given path
    :type  config: ``dict``
    :param init_uri: Alternative URI incase the URI doesnt exist on first pass
    :type init_uri: ``str``
    :param init_method: Method to use on alternative URI when setting config, default: PATCH
    :type init_method: ``str``
    Examples:
    .. code-block:: yaml
        random name here:
          restconf.config_manage:
            - name: random_name_here
            - uri: restconf/data/Cisco-IOS-XE-native:native/interface/GigabitEthernet=1%2F0%2F3
            - config:
                Cisco-IOS-XE-native:GigabitEthernet:
                    description:
                        harro
                    name:
                        1/0/3
    """
    # TODO: add template function so that config var does not need to be passed
    ret = {"name": name, "result": False, "changes": {}, "comment": ""}
    found_working_uri = False
    uri_used = ""
    existing_raw = __salt__["restconf.get_data"](uri)  # noqa: F821
    request_uri = ""
    request_method = ""
    # TODO: this could probaby be a loop
    if existing_raw["status"] in [200]:
        existing = existing_raw["dict"]
        found_working_uri = True
        uri_used = "Primary"
        request_uri = uri
        request_method = method

    if not found_working_uri:
        existing_raw_init = __salt__["restconf.get_data"](init_uri)  # noqa: F821
        if existing_raw_init["status"] in [200]:
            existing = existing_raw_init["dict"]
            found_working_uri = True
            uri_used = "init"
            request_uri = init_uri
            request_method = init_method

    if not found_working_uri:
        ret["result"] = False
        ret["comment"] = "restconf could not find a working URI to get initial config"
        return ret
    # TODO: END

    dict_config = json.loads(
        json.dumps(config)
    )  # convert from orderedDict to Dict (which is now ordered by default in python3.8)

    if existing == dict_config:
        ret["result"] = True
        ret["comment"] = "Config is already set"

    elif __opts__["test"] is True:  # noqa: F821
        ret["result"] = None
        ret["comment"] = "Config will be added"
        diff = _restDiff(existing, dict_config)
        ret["changes"]["new"] = diff.added()
        ret["changes"]["removed"] = diff.removed()
        ret["changes"]["changed"] = diff.changed()

    else:
        resp = __salt__["restconf.set_data"](
            request_uri, request_method, dict_config
        )  # noqa: F821
        # Success
        if resp["status"] in [201, 200, 204]:
            ret["result"] = True
            ret["comment"] = "Successfully added config"
            diff = _restDiff(existing, dict_config)
            ret["changes"]["new"] = diff.added()
            ret["changes"]["removed"] = diff.removed()
            ret["changes"]["changed"] = diff.changed()
            if method == "PATCH":
                ret["changes"]["removed"] = None
        # full failure
        else:
            ret["result"] = False
            if "dict" in resp:
                why = resp["dict"]
            elif "body" in resp:
                why = resp["body"]
            else:
                why = None
            ret[
                "comment"
            ] = "failed to add / modify config. API Statuscode: {s}, API Response: {w}, URI:{u}".format(
                w=why, s=resp["status"], u=uri_used
            )
            print("post_content: {b}".format(b=json.dumps(dict_config)))

    return ret

class _restDiff:
    """
    Calculate the difference between two dictionaries as:
    (1) items added
    (2) items removed
    (3) keys same in both but changed values
    (4) keys same in both and unchanged values
    """

    def __init__(self, current_dict, past_dict):
        self.current_dict = current_dict
        self.past_dict = past_dict
        self.diff = DeepDiff(current_dict, past_dict)
        print("DeepDiff:")
        print(self.diff)
        self.diff_pretty = self.diff.pretty()

    def added(self):
        # TODO: Potential for new adds to get missed here.
        # need to dig into deepdiff more
        if "dictionary_item_added" in self.diff.keys():
            return str(self.diff["dictionary_item_added"])
        return None

    def removed(self):
        if "dictionary_item_removed" in self.diff.keys():
            return str(self.diff["dictionary_item_removed"])
        return None

    def changed(self):
        if "values_changed" in self.diff.keys():
            return str(self.diff["values_changed"])
        return None

    def unchanged(self):
        return None  # TODO: not implemented
<|endoftext|>


<commit_before>"""Allows to get all data about a given GitHub City.

This module allow to developers to get all users of GitHub that have a
given city in their profile. For example, if I want getting all users
from London,. I will get all users that have London in their
profiles (they could live in London or not)

Author: Israel Blancas @iblancasa
Original idea: https://github.com/JJ/github-city-rankings
License:

The MIT License (MIT)
    Copyright (c) 2015-2017 Israel Blancas @iblancasa (http://iblancasa.com/)

    Permission is hereby granted, free of charge, to any person
    obtaining a copy of this software and associated documentation
    files (the Software), to deal in the Software
    without restriction, including without
    limitation the rights to use, copy, modify, merge,
    publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
    WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
    PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
    OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
    USE OR OTHER DEALINGS IN THE SOFTWARE.
"""

from __future__ import absolute_import
import sys
import os
import unittest
import httpretty
sys.path.append(os.path.join(os.path.dirname(sys.path[0]), 'src'))
print(os.path.join(os.path.dirname(sys.path[0]), 'src'))
from githubcity.ghuser import GitHubUser

class ghcityTester(unittest.TestCase):
    """Tester of the class GitHubUser."""

    def test_init(self):
        """Test the creation of the class with its configuration."""
        pass

    def test_getData(self):
        # Given
        with open("tests/resources/user.html") as userWeb:
            reply = userWeb.read()

        httpretty.enable()
        httpretty.register_uri(httpretty.GET, "https://github.com/iblancasa",
                               body=reply,
                               content_type="text/html")

        # When
        user = GitHubUser("iblancasa")
        user.getData()

        # Then
        self.assertEqual(user.numberOfRepos, 141)
        self.assertEqual(user.bio, "")
        self.assertEqual(user.private, 0)
        self.assertEqual(user.public, 0)
        self.assertEqual(user.contributions, 490)
        self.assertEqual(user.name, "iblancasa")
        self.assertEqual(user.join, "2013-06-24")
        self.assertEqual(user.followers, 107)
        self.assertEqual(user.organizations, 7)
        self.assertEqual(user.avatar,
                         "https://avatars0.githubusercontent.com/u/4806311")

if __name__ == "__main__":
    unittest.main()
<commit_msg>Test export() from ghsuer #119<commit_after>"""Allows to get all data about a given GitHub City.

This module allow to developers to get all users of GitHub that have a
given city in their profile. For example, if I want getting all users
from London,. I will get all users that have London in their
profiles (they could live in London or not)

Author: Israel Blancas @iblancasa
Original idea: https://github.com/JJ/github-city-rankings
License:

The MIT License (MIT)
    Copyright (c) 2015-2017 Israel Blancas @iblancasa (http://iblancasa.com/)

    Permission is hereby granted, free of charge, to any person
    obtaining a copy of this software and associated documentation
    files (the Software), to deal in the Software
    without restriction, including without
    limitation the rights to use, copy, modify, merge,
    publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
    WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
    PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
    OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
    USE OR OTHER DEALINGS IN THE SOFTWARE.
"""

from __future__ import absolute_import
import sys
import os
import unittest
import httpretty
sys.path.append(os.path.join(os.path.dirname(sys.path[0]), 'src'))
print(os.path.join(os.path.dirname(sys.path[0]), 'src'))
from githubcity.ghuser import GitHubUser

class ghcityTester(unittest.TestCase):
    """Tester of the class GitHubUser."""

    def test_init(self):
        """Test the creation of the class with its configuration."""
        pass

    def test_getData(self):
        # Given
        with open("tests/resources/user.html") as userWeb:
            reply = userWeb.read()

        httpretty.enable()
        httpretty.register_uri(httpretty.GET, "https://github.com/iblancasa",
                               body=reply,
                               content_type="text/html")

        # When
        user = GitHubUser("iblancasa")
        user.getData()

        # Then
        self.assertEqual(user.numberOfRepos, 141)
        self.assertEqual(user.bio, "")
        self.assertEqual(user.private, 0)
        self.assertEqual(user.public, 0)
        self.assertEqual(user.contributions, 490)
        self.assertEqual(user.name, "iblancasa")
        self.assertEqual(user.join, "2013-06-24")
        self.assertEqual(user.followers, 107)
        self.assertEqual(user.organizations, 7)
        self.assertEqual(user.avatar,
                         "https://avatars0.githubusercontent.com/u/4806311")

    def test_export(self):
        # When
        user = GitHubUser("iblancasa")

        user.numberOfRepos = 141
        user.bio = ""
        user.private = 0
        user.public = 0
        user.location = 'Granada, Andalucía, Spain'
        user.contributions = 490
        user.name = "iblancasa"
        user.join = "2013-06-24"
        user.followers = 107
        user.organizations = 7
        user.avatar = "https://avatars0.githubusercontent.com/u/4806311"

        # Given
        exportedUser = {'name': 'iblancasa',
                        'bio': '',
                        'join': '2013-06-24',
                        'organizations': 7,
                        'private': 0,
                        'contributions':490,
                        'public': 0,
                        'location': 'Granada, Andalucía, Spain',
                        'avatar':
                            'https://avatars0.githubusercontent.com/u/4806311',
                        'repositories': 141,
                        'followers': 107
                        }

        # Then
        self.assertEqual(user.export(), exportedUser)

if __name__ == "__main__":
    unittest.main()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
'''
Control of entries in SSH authorized_key files.
===============================================

The information stored in a user's ssh authorized key file can be easily
controlled via the ssh_auth state. Defaults can be set by the enc, options,
and comment keys. These defaults can be overridden by including them in the
name.

Since the YAML specification limits the length of simple keys to 1024
characters, and since SSH keys are often longer than that, you may have
to use a YAML 'explicit key', as demonstrated in the second example below.

.. code-block:: yaml

    AAAAB3NzaC1kc3MAAACBAL0sQ9fJ5bYTEyY==:
      ssh_auth:
        - present
        - user: root
        - enc: ssh-dss

    ? AAAAB3NzaC1kc3MAAACBAL0sQ9fJ5bYTEyY==...
    :
      ssh_auth:
        - present
        - user: root
        - enc: ssh-dss

    thatch:
      ssh_auth:
        - present
        - user: root
        - source: salt://ssh_keys/thatch.id_rsa.pub

    sshkeys:
      ssh_auth:
        - present
        - user: root
        - enc: ssh-rsa
        - options:
          - option1="value1"
          - option2="value2 flag2"
        - comment: myuser
        - names:
          - AAAAB3NzaC1kc3MAAACBAL0sQ9fJ5bYTEyY==
          - ssh-dss AAAAB3NzaCL0sQ9fJ5bYTEyY== user@domain
          - option3="value3" ssh-dss AAAAB3NzaC1kcQ9J5bYTEyY== other@testdomain
          - AAAAB3NzaC1kcQ9fJFF435bYTEyY== newcomment
'''

# Import python libs
import re
import sys

def _present_test(user, name, enc, comment, options, source, config, env):
    '''
    Run checks for "present"
    '''
    result = None
    if source:
        keys = __salt__['ssh.check_key_file'](
                user,
                source,
                config,
                env)
        if keys:
            comment = ''
            for key, status in keys.items():
                if status == 'exists':
                    continue
                comment += 'Set to {0}: {1}\n'.format(status, key)
            if comment:
                return result, comment
        err = sys.modules[
            __salt__['test.ping'].__module__
        ].__context__.pop('ssh_auth.error', None)
        if err:
            return False, err
        else:
            return (
                True,
                'All host keys in file {0} are already present'.format(source)
            )
    check = __salt__['ssh.check_key'](
            user,
            name,
            enc,
            comment,
            options,
            config)
    if check == 'update':
        comment = (
                'Key {0} for user {1} is set to be updated'
                ).format(name, user)
    elif check == 'add':
        comment = (
                'Key {0} for user {1} is set to be added'
                ).format(name, user)
    elif check == 'exists':
        result = True
        comment = ('The authorized host key {0} is already present '
                          'for user {1}'.format(name, user))

    return result, comment

def present(
        name,
        user,
        enc='ssh-rsa',
        comment='',
        source='',
        options=None,
        config='.ssh/authorized_keys',
        **kwargs):
    '''
    Verifies that the specified ssh key is present for the specified user

    name
        The ssh key to manage

    user
        The user who owns the ssh authorized keys file to modify

    enc
        Defines what type of key is being used, can be ecdsa ssh-rsa, ssh-dss

    comment
        The comment to be placed with the ssh public key

    source
        The source file for the key(s). Can contain any number of public keys,
        in standard "authorized_keys" format. If this is set, comment, enc,
        and options will be ignored.

    .. note::
        The source file must contain keys in the format ``<enc> <key>
        <comment>``. If you have generated a keypair using PuTTYgen, then you
        will need to do the following to retrieve an OpenSSH-compatible public
        key.

        1. In PuTTYgen, click ``Load``, and select the *private* key file (not
           the public key), and click ``Open``.
        2. Copy the public key from the box labeled ``Public key for pasting
           into OpenSSH authorized_keys file``.
        3. Paste it into a new file.

    options
        The options passed to the key, pass a list object

    config
        The location of the authorized keys file relative to the user's home
        directory, defaults to ".ssh/authorized_keys"
    '''
    ret = {'name': name,
           'changes': {},
           'result': True,
           'comment': ''}

    if __opts__['test']:
        ret['result'], ret['comment'] = _present_test(
                user,
                name,
                enc,
                comment,
                options or [],
                source,
                config,
                kwargs.get('__env__', 'base')
                )
        return ret

    if source != '':
        data = __salt__['ssh.set_auth_key_from_file'](
                user,
                source,
                config,
                kwargs.get('__env__', 'base'))
    else:
        # check if this is of form {options} {enc} {key} {comment}
        sshre = re.compile(r'^(.*?)\s?((?:ssh\-|ecds)[\w-]+\s.+)$')
        fullkey = sshre.search(name)
        # if it is {key} [comment]
        if not fullkey:
            key_and_comment = name.split()
            name = key_and_comment[0]
            if len(key_and_comment) == 2:
                comment = key_and_comment[1]
        else:
            # if there are options, set them
            if fullkey.group(1):
                options = fullkey.group(1).split(',')
            # key is of format: {enc} {key} [comment]
            comps = fullkey.group(2).split()
            enc = comps[0]
            name = comps[1]
            if len(comps) == 3:
                comment = comps[2]

        data = __salt__['ssh.set_auth_key'](
                user,
                name,
                enc,
                comment,
                options or [],
                config)

    if data == 'replace':
        ret['changes'][name] = 'Updated'
        ret['comment'] = ('The authorized host key {0} for user {1} was '
                          'updated'.format(name, user))
        return ret
    elif data == 'no change':
        ret['comment'] = ('The authorized host key {0} is already present '
                          'for user {1}'.format(name, user))
    elif data == 'new':
        ret['changes'][name] = 'New'
        ret['comment'] = ('The authorized host key {0} for user {1} was added'
                          .format(name, user))
    elif data == 'fail':
        ret['result'] = False
        err = sys.modules[
            __salt__['test.ping'].__module__
        ].__context__.pop('ssh_auth.error', None)
        if err:
            ret['comment'] = err
        else:
            ret['comment'] = ('Failed to add the ssh key. Is the home '
                              'directory available, and/or does the key file '
                              'exist?')
    elif data == 'invalid':
        ret['result'] = False
        ret['comment'] = 'Invalid public ssh key, most likely has spaces'

    return ret

def absent(name,
           user,
           enc='ssh-rsa',
           comment='',
           options=None,
           config='.ssh/authorized_keys'):
    '''
    Verifies that the specified ssh key is absent

    name
        The ssh key to manage

    user
        The user who owns the ssh authorized keys file to modify

    config
        The location of the authorized keys file relative to the user's home
        directory, defaults to ".ssh/authorized_keys"
    '''
    ret = {'name': name,
           'changes': {},
           'result': True,
           'comment': ''}

    # Get just the key
    name = name.split(' ')[0]

    if __opts__['test']:
        check = __salt__['ssh.check_key'](
                user,
                name,
                enc,
                comment,
                options or [],
                config)
        if check == 'update' or check == 'exists':
            ret['result'] = None
            ret['comment'] = 'Key {0} is set for removal'.format(name)
            return ret
        else:
            ret['comment'] = 'Key is already absent'
            return ret

    ret['comment'] = __salt__['ssh.rm_auth_key'](user, name, config)

    if ret['comment'] == 'User authorized keys file not present':
        ret['result'] = False
        return ret
    elif ret['comment'] == 'Key removed':
        ret['changes'][name] = 'Removed'

    return ret
<commit_msg>Argument documentation<commit_after># -*- coding: utf-8 -*-
'''
Control of entries in SSH authorized_key files.
===============================================

The information stored in a user's ssh authorized key file can be easily
controlled via the ssh_auth state. Defaults can be set by the enc, options,
and comment keys. These defaults can be overridden by including them in the
name.

Since the YAML specification limits the length of simple keys to 1024
characters, and since SSH keys are often longer than that, you may have
to use a YAML 'explicit key', as demonstrated in the second example below.

.. code-block:: yaml

    AAAAB3NzaC1kc3MAAACBAL0sQ9fJ5bYTEyY==:
      ssh_auth:
        - present
        - user: root
        - enc: ssh-dss

    ? AAAAB3NzaC1kc3MAAACBAL0sQ9fJ5bYTEyY==...
    :
      ssh_auth:
        - present
        - user: root
        - enc: ssh-dss

    thatch:
      ssh_auth:
        - present
        - user: root
        - source: salt://ssh_keys/thatch.id_rsa.pub

    sshkeys:
      ssh_auth:
        - present
        - user: root
        - enc: ssh-rsa
        - options:
          - option1="value1"
          - option2="value2 flag2"
        - comment: myuser
        - names:
          - AAAAB3NzaC1kc3MAAACBAL0sQ9fJ5bYTEyY==
          - ssh-dss AAAAB3NzaCL0sQ9fJ5bYTEyY== user@domain
          - option3="value3" ssh-dss AAAAB3NzaC1kcQ9J5bYTEyY== other@testdomain
          - AAAAB3NzaC1kcQ9fJFF435bYTEyY== newcomment
'''

# Import python libs
import re
import sys

def _present_test(user, name, enc, comment, options, source, config, env):
    '''
    Run checks for "present"
    '''
    result = None
    if source:
        keys = __salt__['ssh.check_key_file'](
                user,
                source,
                config,
                env)
        if keys:
            comment = ''
            for key, status in keys.items():
                if status == 'exists':
                    continue
                comment += 'Set to {0}: {1}\n'.format(status, key)
            if comment:
                return result, comment
        err = sys.modules[
            __salt__['test.ping'].__module__
        ].__context__.pop('ssh_auth.error', None)
        if err:
            return False, err
        else:
            return (
                True,
                'All host keys in file {0} are already present'.format(source)
            )
    check = __salt__['ssh.check_key'](
            user,
            name,
            enc,
            comment,
            options,
            config)
    if check == 'update':
        comment = (
                'Key {0} for user {1} is set to be updated'
                ).format(name, user)
    elif check == 'add':
        comment = (
                'Key {0} for user {1} is set to be added'
                ).format(name, user)
    elif check == 'exists':
        result = True
        comment = ('The authorized host key {0} is already present '
                          'for user {1}'.format(name, user))

    return result, comment

def present(
        name,
        user,
        enc='ssh-rsa',
        comment='',
        source='',
        options=None,
        config='.ssh/authorized_keys',
        **kwargs):
    '''
    Verifies that the specified SSH key is present for the specified user

    name
        The SSH key to manage

    user
        The user who owns the SSH authorized keys file to modify

    enc
        Defines what type of key is being used; can be ecdsa, ssh-rsa or ssh-dss

    comment
        The comment to be placed with the SSH public key

    source
        The source file for the key(s). Can contain any number of public keys,
        in standard "authorized_keys" format. If this is set, comment, enc,
        and options will be ignored.

    .. note::
        The source file must contain keys in the format ``<enc> <key>
        <comment>``. If you have generated a keypair using PuTTYgen, then you
        will need to do the following to retrieve an OpenSSH-compatible public
        key.

        1. In PuTTYgen, click ``Load``, and select the *private* key file (not
           the public key), and click ``Open``.
        2. Copy the public key from the box labeled ``Public key for pasting
           into OpenSSH authorized_keys file``.
        3. Paste it into a new file.

    options
        The options passed to the key, pass a list object

    config
        The location of the authorized keys file relative to the user's home
        directory, defaults to ".ssh/authorized_keys"
    '''
    ret = {'name': name,
           'changes': {},
           'result': True,
           'comment': ''}

    if __opts__['test']:
        ret['result'], ret['comment'] = _present_test(
                user,
                name,
                enc,
                comment,
                options or [],
                source,
                config,
                kwargs.get('__env__', 'base')
                )
        return ret

    if source != '':
        data = __salt__['ssh.set_auth_key_from_file'](
                user,
                source,
                config,
                kwargs.get('__env__', 'base'))
    else:
        # check if this is of form {options} {enc} {key} {comment}
        sshre = re.compile(r'^(.*?)\s?((?:ssh\-|ecds)[\w-]+\s.+)$')
        fullkey = sshre.search(name)
        # if it is {key} [comment]
        if not fullkey:
            key_and_comment = name.split()
            name = key_and_comment[0]
            if len(key_and_comment) == 2:
                comment = key_and_comment[1]
        else:
            # if there are options, set them
            if fullkey.group(1):
                options = fullkey.group(1).split(',')
            # key is of format: {enc} {key} [comment]
            comps = fullkey.group(2).split()
            enc = comps[0]
            name = comps[1]
            if len(comps) == 3:
                comment = comps[2]

        data = __salt__['ssh.set_auth_key'](
                user,
                name,
                enc,
                comment,
                options or [],
                config)

    if data == 'replace':
        ret['changes'][name] = 'Updated'
        ret['comment'] = ('The authorized host key {0} for user {1} was '
                          'updated'.format(name, user))
        return ret
    elif data == 'no change':
        ret['comment'] = ('The authorized host key {0} is already present '
                          'for user {1}'.format(name, user))
    elif data == 'new':
        ret['changes'][name] = 'New'
        ret['comment'] = ('The authorized host key {0} for user {1} was added'
                          .format(name, user))
    elif data == 'fail':
        ret['result'] = False
        err = sys.modules[
            __salt__['test.ping'].__module__
        ].__context__.pop('ssh_auth.error', None)
        if err:
            ret['comment'] = err
        else:
            ret['comment'] = ('Failed to add the ssh key. Is the home '
                              'directory available, and/or does the key file '
                              'exist?')
    elif data == 'invalid':
        ret['result'] = False
        ret['comment'] = 'Invalid public ssh key, most likely has spaces'

    return ret

def absent(name,
           user,
           enc='ssh-rsa',
           comment='',
           options=None,
           config='.ssh/authorized_keys'):
    '''
    Verifies that the specified SSH key is absent

    name
        The SSH key to manage

    user
        The user who owns the SSH authorized keys file to modify

    enc
        Defines what type of key is being used; can be ecdsa, ssh-rsa or ssh-dss

    comment
        The comment to be placed with the SSH public key

    options
        The options passed to the key, pass a list object

    config
        The location of the authorized keys file relative to the user's home
        directory, defaults to ".ssh/authorized_keys"
    '''
    ret = {'name': name,
           'changes': {},
           'result': True,
           'comment': ''}

    # Get just the key
    name = name.split(' ')[0]

    if __opts__['test']:
        check = __salt__['ssh.check_key'](
                user,
                name,
                enc,
                comment,
                options or [],
                config)
        if check == 'update' or check == 'exists':
            ret['result'] = None
            ret['comment'] = 'Key {0} is set for removal'.format(name)
            return ret
        else:
            ret['comment'] = 'Key is already absent'
            return ret

    ret['comment'] = __salt__['ssh.rm_auth_key'](user, name, config)

    if ret['comment'] == 'User authorized keys file not present':
        ret['result'] = False
        return ret
    elif ret['comment'] == 'Key removed':
        ret['changes'][name] = 'Removed'

    return ret
<|endoftext|>


<commit_before># encoding: utf-8
'''
A collection of hashing and encoding utils.
'''
from __future__ import absolute_import, unicode_literals, print_function

# Import python libs
import base64
import hashlib
import hmac
import random
import os

# Import Salt libs
from salt.ext import six
import salt.utils.files
import salt.utils.platform
import salt.utils.stringutils

from salt.utils.decorators.jinja import jinja_filter

@jinja_filter('base64_encode')
def base64_b64encode(instr):
    '''
    Encode a string as base64 using the "modern" Python interface.

    Among other possible differences, the "modern" encoder does not include
    newline ('\\n') characters in the encoded output.
    '''
    return salt.utils.stringutils.to_unicode(
        base64.b64encode(salt.utils.stringutils.to_bytes(instr)),
        encoding='utf8' if salt.utils.platform.is_windows() else None
    )

@jinja_filter('base64_decode')
def base64_b64decode(instr):
    '''
    Decode a base64-encoded string using the "modern" Python interface.
    '''
    decoded = base64.b64decode(salt.utils.stringutils.to_bytes(instr))
    try:
        return salt.utils.stringutils.to_unicode(
            decoded,
            encoding='utf8' if salt.utils.platform.is_windows() else None
        )
    except UnicodeDecodeError:
        return decoded

def base64_encodestring(instr):
    '''
    Encode a byte-like object as base64 using the "modern" Python interface.

    Among other possible differences, the "modern" encoder includes
    a newline ('\\n') character after every 76 characters and always
    at the end of the encoded string.
    '''
    return salt.utils.stringutils.to_unicode(
        base64.encodebytes(salt.utils.stringutils.to_bytes(instr)),
        encoding='utf8' if salt.utils.platform.is_windows() else None
    )

def base64_decodestring(instr):
    '''
    Decode a base64-encoded byte-like object using the "modern" Python interface.
    '''
    bvalue = salt.utils.stringutils.to_bytes(instr)
    decoded = base64.decodebytes(bvalue)
    try:
        return salt.utils.stringutils.to_unicode(
            decoded,
            encoding='utf8' if salt.utils.platform.is_windows() else None
        )
    except UnicodeDecodeError:
        return decoded

@jinja_filter('md5')
def md5_digest(instr):
    '''
    Generate an md5 hash of a given string.
    '''
    return salt.utils.stringutils.to_unicode(
        hashlib.md5(salt.utils.stringutils.to_bytes(instr)).hexdigest()
    )

@jinja_filter('sha1')
def sha1_digest(instr):
    '''
    Generate an sha1 hash of a given string.
    '''
    if six.PY3:
        b = salt.utils.stringutils.to_bytes(instr)
        return hashlib.sha1(b).hexdigest()
    return hashlib.sha1(instr).hexdigest()

@jinja_filter('sha256')
def sha256_digest(instr):
    '''
    Generate a sha256 hash of a given string.
    '''
    return salt.utils.stringutils.to_unicode(
        hashlib.sha256(salt.utils.stringutils.to_bytes(instr)).hexdigest()
    )

@jinja_filter('sha512')
def sha512_digest(instr):
    '''
    Generate a sha512 hash of a given string
    '''
    return salt.utils.stringutils.to_unicode(
        hashlib.sha512(salt.utils.stringutils.to_bytes(instr)).hexdigest()
    )

@jinja_filter('hmac')
def hmac_signature(string, shared_secret, challenge_hmac):
    '''
    Verify a challenging hmac signature against a string / shared-secret
    Returns a boolean if the verification succeeded or failed.
    '''
    msg = salt.utils.stringutils.to_bytes(string)
    key = salt.utils.stringutils.to_bytes(shared_secret)
    challenge = salt.utils.stringutils.to_bytes(challenge_hmac)
    hmac_hash = hmac.new(key, msg, hashlib.sha256)
    valid_hmac = base64.b64encode(hmac_hash.digest())
    return valid_hmac == challenge

@jinja_filter('hmac_compute')
def hmac_compute(string, shared_secret):
    '''
    Create an hmac digest.
    '''
    msg = salt.utils.stringutils.to_bytes(string)
    key = salt.utils.stringutils.to_bytes(shared_secret)
    hmac_hash = hmac.new(key, msg, hashlib.sha256).hexdigest()
    return hmac_hash

@jinja_filter('random_hash')
def random_hash(size=9999999999, hash_type=None):
    '''
    Return a hash of a randomized data from random.SystemRandom()
    '''
    if not hash_type:
        hash_type = 'md5'
    hasher = getattr(hashlib, hash_type)
    return hasher(salt.utils.stringutils.to_bytes(six.text_type(random.SystemRandom().randint(0, size)))).hexdigest()

@jinja_filter('file_hashsum')
def get_hash(path, form='sha256', chunk_size=65536):
    '''
    Get the hash sum of a file

    This is better than ``get_sum`` for the following reasons:
        - It does not read the entire file into memory.
        - It does not return a string on error. The returned value of
            ``get_sum`` cannot really be trusted since it is vulnerable to
            collisions: ``get_sum(..., 'xyz') == 'Hash xyz not supported'``
    '''
    hash_type = hasattr(hashlib, form) and getattr(hashlib, form) or None
    if hash_type is None:
        raise ValueError('Invalid hash type: {0}'.format(form))

    with salt.utils.files.fopen(path, 'rb') as ifile:
        hash_obj = hash_type()
        # read the file in in chunks, not the entire file
        for chunk in iter(lambda: ifile.read(chunk_size), b''):
            hash_obj.update(chunk)
        return hash_obj.hexdigest()

class DigestCollector(object):
    '''
    Class to collect digest of the file tree.
    '''

    def __init__(self, form='sha256', buff=0x10000):
        '''
        Constructor of the class.
        :param form:
        '''
        self.__digest = hasattr(hashlib, form) and getattr(hashlib, form)() or None
        if self.__digest is None:
            raise ValueError('Invalid hash type: {0}'.format(form))
        self.__buff = buff

    def add(self, path):
        '''
        Update digest with the file content by path.

        :param path:
        :return:
        '''
        with salt.utils.files.fopen(path, 'rb') as ifile:
            for chunk in iter(lambda: ifile.read(self.__buff), b''):
                self.__digest.update(chunk)

    def digest(self):
        '''
        Get digest.

        :return:
        '''

        return salt.utils.stringutils.to_str(self.__digest.hexdigest() + os.linesep)
<commit_msg>Adds PY2 support<commit_after># encoding: utf-8
'''
A collection of hashing and encoding utils.
'''
from __future__ import absolute_import, unicode_literals, print_function

# Import python libs
import base64
import hashlib
import hmac
import random
import os

# Import Salt libs
from salt.ext import six
import salt.utils.files
import salt.utils.platform
import salt.utils.stringutils

from salt.utils.decorators.jinja import jinja_filter

@jinja_filter('base64_encode')
def base64_b64encode(instr):
    '''
    Encode a string as base64 using the "modern" Python interface.

    Among other possible differences, the "modern" encoder does not include
    newline ('\\n') characters in the encoded output.
    '''
    return salt.utils.stringutils.to_unicode(
        base64.b64encode(salt.utils.stringutils.to_bytes(instr)),
        encoding='utf8' if salt.utils.platform.is_windows() else None
    )

@jinja_filter('base64_decode')
def base64_b64decode(instr):
    '''
    Decode a base64-encoded string using the "modern" Python interface.
    '''
    decoded = base64.b64decode(salt.utils.stringutils.to_bytes(instr))
    try:
        return salt.utils.stringutils.to_unicode(
            decoded,
            encoding='utf8' if salt.utils.platform.is_windows() else None
        )
    except UnicodeDecodeError:
        return decoded

def base64_encodestring(instr):
    '''
    Encode a byte-like object as base64 using the "modern" Python interface.

    Among other possible differences, the "modern" encoder includes
    a newline ('\\n') character after every 76 characters and always
    at the end of the encoded string.
    '''
    # Handles PY2
    if six.PY2:
        return salt.utils.stringutils.to_unicode(
            base64.encodestring(salt.utils.stringutils.to_bytes(instr)),
            encoding='utf8' if salt.utils.platform.is_windows() else None
        )

    # Handles PY3
    return salt.utils.stringutils.to_unicode(
        base64.encodebytes(salt.utils.stringutils.to_bytes(instr)),
        encoding='utf8' if salt.utils.platform.is_windows() else None
    )

def base64_decodestring(instr):
    '''
    Decode a base64-encoded byte-like object using the "modern" Python interface.
    '''
    bvalue = salt.utils.stringutils.to_bytes(instr)

    # Handles PY2
    if six.PY2:
        decoded = base64.decodestring(bvalue)

    # Handles PY3
    if six.PY3:
        decoded = base64.decodebytes(bvalue)
    try:
        return salt.utils.stringutils.to_unicode(
            decoded,
            encoding='utf8' if salt.utils.platform.is_windows() else None
        )
    except UnicodeDecodeError:
        return decoded

@jinja_filter('md5')
def md5_digest(instr):
    '''
    Generate an md5 hash of a given string.
    '''
    return salt.utils.stringutils.to_unicode(
        hashlib.md5(salt.utils.stringutils.to_bytes(instr)).hexdigest()
    )

@jinja_filter('sha1')
def sha1_digest(instr):
    '''
    Generate an sha1 hash of a given string.
    '''
    if six.PY3:
        b = salt.utils.stringutils.to_bytes(instr)
        return hashlib.sha1(b).hexdigest()
    return hashlib.sha1(instr).hexdigest()

@jinja_filter('sha256')
def sha256_digest(instr):
    '''
    Generate a sha256 hash of a given string.
    '''
    return salt.utils.stringutils.to_unicode(
        hashlib.sha256(salt.utils.stringutils.to_bytes(instr)).hexdigest()
    )

@jinja_filter('sha512')
def sha512_digest(instr):
    '''
    Generate a sha512 hash of a given string
    '''
    return salt.utils.stringutils.to_unicode(
        hashlib.sha512(salt.utils.stringutils.to_bytes(instr)).hexdigest()
    )

@jinja_filter('hmac')
def hmac_signature(string, shared_secret, challenge_hmac):
    '''
    Verify a challenging hmac signature against a string / shared-secret
    Returns a boolean if the verification succeeded or failed.
    '''
    msg = salt.utils.stringutils.to_bytes(string)
    key = salt.utils.stringutils.to_bytes(shared_secret)
    challenge = salt.utils.stringutils.to_bytes(challenge_hmac)
    hmac_hash = hmac.new(key, msg, hashlib.sha256)
    valid_hmac = base64.b64encode(hmac_hash.digest())
    return valid_hmac == challenge

@jinja_filter('hmac_compute')
def hmac_compute(string, shared_secret):
    '''
    Create an hmac digest.
    '''
    msg = salt.utils.stringutils.to_bytes(string)
    key = salt.utils.stringutils.to_bytes(shared_secret)
    hmac_hash = hmac.new(key, msg, hashlib.sha256).hexdigest()
    return hmac_hash

@jinja_filter('random_hash')
def random_hash(size=9999999999, hash_type=None):
    '''
    Return a hash of a randomized data from random.SystemRandom()
    '''
    if not hash_type:
        hash_type = 'md5'
    hasher = getattr(hashlib, hash_type)
    return hasher(salt.utils.stringutils.to_bytes(six.text_type(random.SystemRandom().randint(0, size)))).hexdigest()

@jinja_filter('file_hashsum')
def get_hash(path, form='sha256', chunk_size=65536):
    '''
    Get the hash sum of a file

    This is better than ``get_sum`` for the following reasons:
        - It does not read the entire file into memory.
        - It does not return a string on error. The returned value of
            ``get_sum`` cannot really be trusted since it is vulnerable to
            collisions: ``get_sum(..., 'xyz') == 'Hash xyz not supported'``
    '''
    hash_type = hasattr(hashlib, form) and getattr(hashlib, form) or None
    if hash_type is None:
        raise ValueError('Invalid hash type: {0}'.format(form))

    with salt.utils.files.fopen(path, 'rb') as ifile:
        hash_obj = hash_type()
        # read the file in in chunks, not the entire file
        for chunk in iter(lambda: ifile.read(chunk_size), b''):
            hash_obj.update(chunk)
        return hash_obj.hexdigest()

class DigestCollector(object):
    '''
    Class to collect digest of the file tree.
    '''

    def __init__(self, form='sha256', buff=0x10000):
        '''
        Constructor of the class.
        :param form:
        '''
        self.__digest = hasattr(hashlib, form) and getattr(hashlib, form)() or None
        if self.__digest is None:
            raise ValueError('Invalid hash type: {0}'.format(form))
        self.__buff = buff

    def add(self, path):
        '''
        Update digest with the file content by path.

        :param path:
        :return:
        '''
        with salt.utils.files.fopen(path, 'rb') as ifile:
            for chunk in iter(lambda: ifile.read(self.__buff), b''):
                self.__digest.update(chunk)

    def digest(self):
        '''
        Get digest.

        :return:
        '''

        return salt.utils.stringutils.to_str(self.__digest.hexdigest() + os.linesep)
<|endoftext|>


<commit_before>'''
The generic libcloud template used to create the connections and deploy the
cloud virtual machines
'''

# Import python libs
import os

# Import libcloud
from libcloud.compute.types import Provider
from libcloud.compute.providers import get_driver
from libcloud.compute.deployment import MultiStepDeployment, ScriptDeployment, SSHKeyDeployment

# Import salt libs
import saltcloud.utils

def get_conn(vm_):
    '''
    Return a conn object for the passed vm data
    '''
    prov = 'EC2'
    if 'location' in vm_:
        prov += '_{0}'.format(vm_['location'])
    elif 'location' in __opts__:
        if __opts__['location']:
            prov += '_{0}'.format(__opts__['location'])
    if not hasattr(Provider, prov):
        return None
    driver = get_driver(getattr(Provider, 'EC2'))
    return driver(
            __opts__['EC2.id'],
            __opts__['EC2.key'],
            )

def ssh_pub(vm_):
    '''
    Deploy the primary ssh authentication key
    '''
    ssh = ''
    if 'ssh_auth' in vm_:
        if not os.path.isfile(vm_['ssh_auth']):
            return None
        ssh = vm_['ssh_auth']
    if not ssh:
        if not os.path.isfile(__opts__['ssh_auth']):
            return None
        ssh = __opts__['ssh_auth']

    return SSHKeyDeployment(open(os.path.expanduser(ssh)).read())

def script(vm_):
    '''
    Return the deployment object for managing a script
    '''
    os_ = ''
    if 'os' in vm_:
        os_ = vm_['os']
    if not os_:
        os_ = __opts__['os']
    return ScriptDeployment(saltcloud.utils.os_script(os_))

def get_image(conn, vm_):
    '''
    Return the image object to use
    '''
    images = conn.list_images()
    if not 'image' in vm_:
        return images[0]
    if isinstance(vm_['image'], int):
        return images[vm_['image']]
    for img in images:
        if img.id == vm_['image']:
            return img

def get_size(conn, vm_):
    '''
    Return the vm's size object
    '''
    sizes = conn.list_sizes()
    if not 'size' in vm_:
        return sizes[0]
    if isinstance(vm_['size'], int):
        return sizes[vm_['size']]
    for size in sizes:
        if size.id == vm_['size']:
            return size
        if size.name == vm_['size']:
            return size

def keyname(vm_):
    '''
    Return the keyname
    '''
    return vm_.get('EC2.keyname', __opts__.get('EC2.keyname', ''))

def securitygroup(vm_):
    '''
    Return the keyname
    '''
    return vm_.get(
            'EC2.securitygroup',
            __opts__.get('EC2.securitygroup', 'default')
            )

def create(vm_):
    '''
    Create a single vm from a data dict
    '''
    conn = get_conn(vm_)
    kwargs = {}
    kwargs['name'] = vm_['name']
    kwargs['deploy'] = MultiStepDeployment([ssh_pub(vm_), script(vm_)])
    kwargs['image'] = get_image(conn, vm_)
    kwargs['size'] = get_size(conn, vm_)
    ex_keyname = keyname(vm_)
    if ex_keyname:
        kwargs['ex_keyname'] = ex_keyname
    ex_securitygroup = securitygroup(vm_)
    if ex_securitygroup:
        kwargs['ex_securitygroup'] = ex_securitygroup
    return conn.deploy_node(**kwargs)

<commit_msg>Fix components of scipted deployment.<commit_after>'''
The generic libcloud template used to create the connections and deploy the
cloud virtual machines
'''

# Import python libs
import os

# Import libcloud
from libcloud.compute.types import Provider
from libcloud.compute.providers import get_driver
from libcloud.compute.deployment import MultiStepDeployment, ScriptDeployment, SSHKeyDeployment

# Import salt libs
import saltcloud.utils

def get_conn(vm_):
    '''
    Return a conn object for the passed vm data
    '''
    prov = 'EC2'
    if 'location' in vm_:
        prov += '_{0}'.format(vm_['location'])
    elif 'location' in __opts__:
        if __opts__['location']:
            prov += '_{0}'.format(__opts__['location'])
    if not hasattr(Provider, prov):
        return None
    driver = get_driver(getattr(Provider, 'EC2'))
    return driver(
            __opts__['EC2.id'],
            __opts__['EC2.key'],
            )

def ssh_pub(vm_):
    '''
    Deploy the primary ssh authentication key
    '''
    ssh = ''
    if 'ssh_auth' in vm_:
        if not os.path.isfile(vm_['ssh_auth']):
            return None
        ssh = vm_['ssh_auth']
    if not ssh:
        if not os.path.isfile(__opts__['ssh_auth']):
            return None
        ssh = __opts__['ssh_auth']

    return SSHKeyDeployment(open(os.path.expanduser(ssh)).read())

def script(vm_):
    '''
    Return the deployment object for managing a script
    '''
    os_ = ''
    if 'os' in vm_:
        os_ = vm_['os']
    if not os_:
        os_ = __opts__['os']
    return ScriptDeployment(
            saltcloud.utils.os_script(os_),
            name='/home/ec2-user/deployment.sh'
            )

def get_image(conn, vm_):
    '''
    Return the image object to use
    '''
    images = conn.list_images()
    if not 'image' in vm_:
        return images[0]
    if isinstance(vm_['image'], int):
        return images[vm_['image']]
    for img in images:
        if img.id == vm_['image']:
            return img

def get_size(conn, vm_):
    '''
    Return the vm's size object
    '''
    sizes = conn.list_sizes()
    if not 'size' in vm_:
        return sizes[0]
    if isinstance(vm_['size'], int):
        return sizes[vm_['size']]
    for size in sizes:
        if size.id == vm_['size']:
            return size
        if size.name == vm_['size']:
            return size

def keyname(vm_):
    '''
    Return the keyname
    '''
    return vm_.get('EC2.keyname', __opts__.get('EC2.keyname', ''))

def securitygroup(vm_):
    '''
    Return the keyname
    '''
    return vm_.get(
            'EC2.securitygroup',
            __opts__.get('EC2.securitygroup', 'default')
            )

def create(vm_):
    '''
    Create a single vm from a data dict
    '''
    conn = get_conn(vm_)
    kwargs = {'ssh_username': 'ec2-user',
              'ssh_key': '/root/.ssh/id_rsa'}
    kwargs['name'] = vm_['name']
    print('Setting up deployment script')
    kwargs['deploy'] = script(vm_)
    print('Getting the image')
    kwargs['image'] = get_image(conn, vm_)
    print('Getting the size')
    kwargs['size'] = get_size(conn, vm_)
    print('Getting security data')
    ex_keyname = keyname(vm_)
    if ex_keyname:
        kwargs['ex_keyname'] = ex_keyname
    ex_securitygroup = securitygroup(vm_)
    if ex_securitygroup:
        kwargs['ex_securitygroup'] = ex_securitygroup
    print('Running deploy')
    return conn.deploy_node(**kwargs)

<|endoftext|>