<commit_before># -*- coding: utf-8 -*-
"""
The core parsing function of RDFa. Some details are
put into other modules to make it clearer to update/modify (eg, generation of literals, or managing the current state).

@summary: RDFa core parser processing step
@requires: U{RDFLib package<http://rdflib.net>}
@organization: U{World Wide Web Consortium<http://www.w3.org>}
@author: U{Ivan Herman}
@license: This software is available for use under the
U{W3C® SOFTWARE NOTICE AND LICENSE<href="http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231">}
"""

"""
$Id: parse.py,v 1.2 2011/09/01 11:06:13 ivan Exp $
$Date: 2011/09/01 11:06:13 $

Added a reaction on the RDFaStopParsing exception: if raised while setting up the local execution context, parsing
is stopped (on the whole subtree)
"""

import sys

from pyRdfa.state   		import ExecutionContext
from pyRdfa.literal 		import generate_literal
from pyRdfa.embeddedRDF	 	import handle_embeddedRDF
from pyRdfa.host			import HostLanguage, host_dom_transforms, accept_embedded_rdf

import rdflib
from rdflib	import URIRef
from rdflib	import Literal
from rdflib	import BNode
from rdflib	import Namespace
if rdflib.__version__ >= "3.0.0" :
	from rdflib	import Graph
	from rdflib	import RDF  as ns_rdf
	from rdflib	import RDFS as ns_rdfs
else :
	from rdflib.Graph	import Graph
	from rdflib.RDFS	import RDFSNS as ns_rdfs
	from rdflib.RDF		import RDFNS  as ns_rdf

from pyRdfa import IncorrectBlankNodeUsage, err_no_blank_node
from pyRdfa.utils import has_one_of_attributes

#######################################################################
def parse_one_node(node, graph, parent_object, incoming_state, parent_incomplete_triples) :
	"""The (recursive) step of handling a single node. See the
	U{RDFa syntax document<http://www.w3.org/TR/rdfa-syntax>} for further details.

	@param node: the DOM node to handle
	@param graph: the RDF graph
	@type graph: RDFLib's Graph object instance
	@param parent_object: the parent's object, as an RDFLib URIRef
	@param incoming_state: the inherited state (namespaces, lang, etc)
	@type incoming_state: L{state.ExecutionContext}
	@param parent_incomplete_triples: list of hanging triples (the missing resource set to None) to be handled (or not)
	by the current node.
	@return: whether the caller has to complete it's parent's incomplete triples
	@rtype: Boolean
	"""

	# Update the state. This means, for example, the possible local settings of
	# namespaces and lang
	state = None
	state = ExecutionContext(node, graph, inherited_state=incoming_state)

	#---------------------------------------------------------------------------------
	# Handle the special case for embedded RDF, eg, in SVG1.2.
	# This may add some triples to the target graph that does not originate from RDFa parsing
	# If the function return TRUE, that means that an rdf:RDF has been found. No
	# RDFa parsing should be done on that subtree, so we simply return...
	if state.options.host_language in accept_embedded_rdf and node.nodeType == node.ELEMENT_NODE and handle_embeddedRDF(node, graph, state) :
		return

	#---------------------------------------------------------------------------------
	# calling the host specific massaging of the DOM
	if state.options.host_language in host_dom_transforms and node.nodeType == node.ELEMENT_NODE :
		for func in host_dom_transforms[state.options.host_language] : func(node, state)

	#---------------------------------------------------------------------------------
	# First, let us check whether there is anything to do at all. Ie,
	# whether there is any relevant RDFa specific attribute on the element
	#
	if not has_one_of_attributes(node, "href", "resource", "about", "property", "rel", "rev", "typeof", "src", "vocab", "prefix") :
		# nop, there is nothing to do here, just go down the tree and return...
		for n in node.childNodes :
			if n.nodeType == node.ELEMENT_NODE : parse_one_node(n, graph, parent_object, state, parent_incomplete_triples)
		return

	#-----------------------------------------------------------------
	# The goal is to establish the subject and object for local processing
	# The behaviour is slightly different depending on the presense or not
	# of the @rel/@rev attributes
	current_subject = None
	current_object  = None
	new_collection  = False

	if has_one_of_attributes(node, "rel", "rev")  :
		# in this case there is the notion of 'left' and 'right' of @rel/@rev
		# in establishing the new Subject and the objectResource

		# set first the subject
		if node.hasAttribute("about") :
			current_subject = state.getURI("about")
		elif node.hasAttribute("src") :
			current_subject = state.getURI("src")
		elif node.hasAttribute("typeof") :
			current_subject = BNode()

		# get_URI may return None in case of an illegal CURIE, so
		# we have to be careful here, not use only an 'else'
		if current_subject == None :
			current_subject = parent_object
		else :
			state.reset_collection_mapping()
			new_collection  = True

		# set the object resource
		if node.hasAttribute("resource") :
			current_object = state.getURI("resource")
		elif node.hasAttribute("href") :
			current_object = state.getURI("href")
	else :
		# in this case all the various 'resource' setting attributes
		# behave identically, though they also have their own priority
		if node.hasAttribute("about") :
			current_subject = state.getURI("about")
		elif node.hasAttribute("src") :
			current_subject = state.getURI("src")
		elif node.hasAttribute("resource") :
			current_subject = state.getURI("resource")
		elif node.hasAttribute("href") :
			current_subject = state.getURI("href")
		elif node.hasAttribute("typeof") :
			current_subject = BNode()

		# get_URI_ref may return None in case of an illegal CURIE, so
		# we have to be careful here, not use only an 'else'
		if current_subject == None :
			current_subject = parent_object
		else :
			state.reset_collection_mapping()
			new_collection  = True

		# in this case no non-literal triples will be generated, so the
		# only role of the current_object Resource is to be transferred to
		# the children node
		current_object = current_subject

	# ---------------------------------------------------------------------
	## The possible typeof indicates a number of type statements on the new Subject
	for defined_type in state.getURI("typeof") :
		graph.add((current_subject, ns_rdf["type"], defined_type))

	# ---------------------------------------------------------------------
	# In case of @rel/@rev, either triples or incomplete triples are generated
	# the (possible) incomplete triples are collected, to be forwarded to the children
	incomplete_triples  = []
	for prop in state.getURI("rel") :
		if not isinstance(prop,BNode) :
			if node.hasAttribute("member") :
				if current_object != None :
					state.add_to_collection_mapping(prop, current_object)
				else :
					incomplete_triples.append((None, prop, None))
			else :
				theTriple = (current_subject, prop, current_object)
				if current_object != None :
					graph.add(theTriple)
				else :
					incomplete_triples.append(theTriple)
		else :
			state.options.add_warning(err_no_blank_node % "rel", warning_type=IncorrectBlankNodeUsage, node=node.nodeName)

	for prop in state.getURI("rev") :
		if not isinstance(prop,BNode) :
			theTriple = (current_object,prop,current_subject)
			if current_object != None :
				graph.add(theTriple)
			else :
				incomplete_triples.append(theTriple)
		else :
			state.options.add_warning(err_no_blank_node % "rev", warning_type=IncorrectBlankNodeUsage, node=node.nodeName)

	# ----------------------------------------------------------------------
	# Generation of the literal values. The newSubject is the subject
	# A particularity of property is that it stops the parsing down the DOM tree if an XML Literal is generated,
	# because everything down there is part of the generated literal.
	if node.hasAttribute("property") :
		# Generate the literal. It has been put it into a separate module to make it more managable
		generate_literal(node, graph, current_subject, state)
		# LIST: if @member, then collection_mapping[property].append(Literal), ie, there may be a need
		# for restructuring the handling of a literal

	# ----------------------------------------------------------------------
	# Setting the current object to a bnode is setting up a possible resource
	# for the incomplete triples downwards
	if current_object == None :
		object_to_children = BNode()
	else :
		object_to_children = current_object

	#-----------------------------------------------------------------------
	# Here is the recursion step for all the children
	for n in node.childNodes :
		if n.nodeType == node.ELEMENT_NODE :
			parse_one_node(n, graph, object_to_children, state, incomplete_triples)

	# ---------------------------------------------------------------------
	# At this point, the parent's incomplete triples may be completed
	for (s,p,o) in parent_incomplete_triples :
		if s == None and o == None :
			# This is an encoded version of a hanging rel for a collection:
			state.add_to_collection_mapping( p, current_subject )
		else :
			if s == None : s = current_subject
			if o == None : o = current_subject
			graph.add((s,p,o))

	# Generate the lists, if any...
	if new_collection and len(state.collection_mapping) != 0 :
		for prop in state.collection_mapping :
			bnodes = [ (BNode(), i) for i in state.collection_mapping[prop] ]
			if len(bnodes) == 0 :
				# should not happen, though
				continue
			for (b,r) in bnodes :
				graph.add( (b, ns_rdf["first"], r) )
			for i in range(0, len(bnodes)-1) :
				graph.add( (bnodes[i][0], ns_rdf["rest"], bnodes[i+1][0]) )

			graph.add( (bnodes[-1][0], ns_rdf["rest"], ns_rdf["nil"]) )
			graph.add( (current_subject, prop, bnodes[0][0]) )

	# -------------------------------------------------------------------
	# This should be it...
	# -------------------------------------------------------------------
	return

<commit_msg>All the test cases work now with the list management<commit_after># -*- coding: utf-8 -*-
"""
The core parsing function of RDFa. Some details are
put into other modules to make it clearer to update/modify (eg, generation of literals, or managing the current state).

@summary: RDFa core parser processing step
@requires: U{RDFLib package<http://rdflib.net>}
@organization: U{World Wide Web Consortium<http://www.w3.org>}
@author: U{Ivan Herman}
@license: This software is available for use under the
U{W3C® SOFTWARE NOTICE AND LICENSE<href="http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231">}
"""

"""
$Id: parse.py,v 1.2 2011/09/01 11:06:13 ivan Exp $
$Date: 2011/09/01 11:06:13 $

Added a reaction on the RDFaStopParsing exception: if raised while setting up the local execution context, parsing
is stopped (on the whole subtree)
"""

import sys

from pyRdfa.state   		import ExecutionContext
from pyRdfa.literal 		import generate_literal
from pyRdfa.embeddedRDF	 	import handle_embeddedRDF
from pyRdfa.host			import HostLanguage, host_dom_transforms, accept_embedded_rdf

import rdflib
from rdflib	import URIRef
from rdflib	import Literal
from rdflib	import BNode
from rdflib	import Namespace
if rdflib.__version__ >= "3.0.0" :
	from rdflib	import Graph
	from rdflib	import RDF  as ns_rdf
	from rdflib	import RDFS as ns_rdfs
else :
	from rdflib.Graph	import Graph
	from rdflib.RDFS	import RDFSNS as ns_rdfs
	from rdflib.RDF		import RDFNS  as ns_rdf

from pyRdfa import IncorrectBlankNodeUsage, err_no_blank_node
from pyRdfa.utils import has_one_of_attributes

#######################################################################
def parse_one_node(node, graph, parent_object, incoming_state, parent_incomplete_triples) :
	"""The (recursive) step of handling a single node. See the
	U{RDFa syntax document<http://www.w3.org/TR/rdfa-syntax>} for further details.

	@param node: the DOM node to handle
	@param graph: the RDF graph
	@type graph: RDFLib's Graph object instance
	@param parent_object: the parent's object, as an RDFLib URIRef
	@param incoming_state: the inherited state (namespaces, lang, etc)
	@type incoming_state: L{state.ExecutionContext}
	@param parent_incomplete_triples: list of hanging triples (the missing resource set to None) to be handled (or not)
	by the current node.
	@return: whether the caller has to complete it's parent's incomplete triples
	@rtype: Boolean
	"""

	# Update the state. This means, for example, the possible local settings of
	# namespaces and lang
	state = None
	state = ExecutionContext(node, graph, inherited_state=incoming_state)

	#---------------------------------------------------------------------------------
	# Handle the special case for embedded RDF, eg, in SVG1.2.
	# This may add some triples to the target graph that does not originate from RDFa parsing
	# If the function return TRUE, that means that an rdf:RDF has been found. No
	# RDFa parsing should be done on that subtree, so we simply return...
	if state.options.host_language in accept_embedded_rdf and node.nodeType == node.ELEMENT_NODE and handle_embeddedRDF(node, graph, state) :
		return

	#---------------------------------------------------------------------------------
	# calling the host specific massaging of the DOM
	if state.options.host_language in host_dom_transforms and node.nodeType == node.ELEMENT_NODE :
		for func in host_dom_transforms[state.options.host_language] : func(node, state)

	#---------------------------------------------------------------------------------
	# First, let us check whether there is anything to do at all. Ie,
	# whether there is any relevant RDFa specific attribute on the element
	#
	if not has_one_of_attributes(node, "href", "resource", "about", "property", "rel", "rev", "typeof", "src", "vocab", "prefix") :
		# nop, there is nothing to do here, just go down the tree and return...
		for n in node.childNodes :
			if n.nodeType == node.ELEMENT_NODE : parse_one_node(n, graph, parent_object, state, parent_incomplete_triples)
		return

	#-----------------------------------------------------------------
	# The goal is to establish the subject and object for local processing
	# The behaviour is slightly different depending on the presense or not
	# of the @rel/@rev attributes
	current_subject = None
	current_object  = None
	new_collection  = False

	if has_one_of_attributes(node, "rel", "rev")  :
		# in this case there is the notion of 'left' and 'right' of @rel/@rev
		# in establishing the new Subject and the objectResource

		# set first the subject
		if node.hasAttribute("about") :
			current_subject = state.getURI("about")
		elif node.hasAttribute("src") :
			current_subject = state.getURI("src")
		elif node.hasAttribute("typeof") :
			current_subject = BNode()

		# get_URI may return None in case of an illegal CURIE, so
		# we have to be careful here, not use only an 'else'
		if current_subject == None :
			current_subject = parent_object
		else :
			state.reset_collection_mapping()
			new_collection  = True

		# set the object resource
		if node.hasAttribute("resource") :
			current_object = state.getURI("resource")
		elif node.hasAttribute("href") :
			current_object = state.getURI("href")
	else :
		# in this case all the various 'resource' setting attributes
		# behave identically, though they also have their own priority
		if node.hasAttribute("about") :
			current_subject = state.getURI("about")
		elif node.hasAttribute("src") :
			current_subject = state.getURI("src")
		elif node.hasAttribute("resource") :
			current_subject = state.getURI("resource")
		elif node.hasAttribute("href") :
			current_subject = state.getURI("href")
		elif node.hasAttribute("typeof") :
			current_subject = BNode()

		# get_URI_ref may return None in case of an illegal CURIE, so
		# we have to be careful here, not use only an 'else'
		if current_subject == None :
			current_subject = parent_object
		else :
			state.reset_collection_mapping()
			new_collection  = True

		# in this case no non-literal triples will be generated, so the
		# only role of the current_object Resource is to be transferred to
		# the children node
		current_object = current_subject

	# ---------------------------------------------------------------------
	## The possible typeof indicates a number of type statements on the new Subject
	for defined_type in state.getURI("typeof") :
		graph.add((current_subject, ns_rdf["type"], defined_type))

	# ---------------------------------------------------------------------
	# In case of @rel/@rev, either triples or incomplete triples are generated
	# the (possible) incomplete triples are collected, to be forwarded to the children
	incomplete_triples  = []
	for prop in state.getURI("rel") :
		if not isinstance(prop,BNode) :
			if node.hasAttribute("member") :
				if current_object != None :
					state.add_to_collection_mapping(prop, current_object)
				else :
					incomplete_triples.append((None, prop, None))
			else :
				theTriple = (current_subject, prop, current_object)
				if current_object != None :
					graph.add(theTriple)
				else :
					incomplete_triples.append(theTriple)
		else :
			state.options.add_warning(err_no_blank_node % "rel", warning_type=IncorrectBlankNodeUsage, node=node.nodeName)

	for prop in state.getURI("rev") :
		if not isinstance(prop,BNode) :
			theTriple = (current_object,prop,current_subject)
			if current_object != None :
				graph.add(theTriple)
			else :
				incomplete_triples.append(theTriple)
		else :
			state.options.add_warning(err_no_blank_node % "rev", warning_type=IncorrectBlankNodeUsage, node=node.nodeName)

	# ----------------------------------------------------------------------
	# Generation of the literal values. The newSubject is the subject
	# A particularity of property is that it stops the parsing down the DOM tree if an XML Literal is generated,
	# because everything down there is part of the generated literal.
	if node.hasAttribute("property") :
		# Generate the literal. It has been put it into a separate module to make it more managable
		generate_literal(node, graph, current_subject, state)
		# LIST: if @member, then collection_mapping[property].append(Literal), ie, there may be a need
		# for restructuring the handling of a literal

	# ----------------------------------------------------------------------
	# Setting the current object to a bnode is setting up a possible resource
	# for the incomplete triples downwards
	if current_object == None :
		object_to_children = BNode()
	else :
		object_to_children = current_object

	#-----------------------------------------------------------------------
	# Here is the recursion step for all the children
	for n in node.childNodes :
		if n.nodeType == node.ELEMENT_NODE :
			parse_one_node(n, graph, object_to_children, state, incomplete_triples)

	# ---------------------------------------------------------------------
	# At this point, the parent's incomplete triples may be completed
	for (s,p,o) in parent_incomplete_triples :
		if s == None and o == None :
			# This is an encoded version of a hanging rel for a collection:
			incoming_state.add_to_collection_mapping( p, current_subject )
		else :
			if s == None : s = current_subject
			if o == None : o = current_subject
			graph.add((s,p,o))

	# Generate the lists, if any...
	if new_collection and len(state.collection_mapping) != 0 :
		for prop in state.collection_mapping :
			bnodes = [ (BNode(), i) for i in state.collection_mapping[prop] ]
			if len(bnodes) == 0 :
				# should not happen, though
				continue
			for (b,r) in bnodes :
				graph.add( (b, ns_rdf["first"], r) )
			for i in range(0, len(bnodes)-1) :
				graph.add( (bnodes[i][0], ns_rdf["rest"], bnodes[i+1][0]) )

			graph.add( (bnodes[-1][0], ns_rdf["rest"], ns_rdf["nil"]) )
			graph.add( (current_subject, prop, bnodes[0][0]) )

	# -------------------------------------------------------------------
	# This should be it...
	# -------------------------------------------------------------------
	return

<|endoftext|>


<commit_before>#!/usr/bin/env python3

"""
Conda based provider.

https://conda.io/docs/

Conda is an open source package management system and environment management
system that runs on Windows, macOS and Linux. Conda quickly installs, runs and
updates packages and their dependencies. Conda easily creates, saves, loads and
switches between environments on your local computer. It was created for Python
programs, but it can package and distribute software for any language.
"""

import os
import re
import platform
import requests
from collections import namedtuple

from . import Provider

CondaVersionTuple = namedtuple("CondaVersionTuple", ("version", "system", "machine", "file"))

def _parse_version(filename):
    """Parse a Miniconda file name into a CondaVersionTuple object.

    >>> _parse_version('Miniconda-1.9.1-Linux-x86_64.sh')
    CondaVersionTuple(version=(1, 9, 1), system='Linux', machine='x86_64', file='Miniconda-1.9.1-Linux-x86_64.sh')
    >>> _parse_version('Miniconda3-2.2.8-Windows-x86.exe')
    CondaVersionTuple(version=(2, 2, 8), system='Windows', machine='x86', file='Miniconda3-2.2.8-Windows-x86.exe')
    >>> _parse_version('Miniconda-3.16.0-Linux-armv7l.sh')
    CondaVersionTuple(version=(3, 16, 0), system='Linux', machine='armv7l', file='Miniconda-3.16.0-Linux-armv7l.sh')
    """
    s = os.path.splitext(filename)[0]
    assert '-' in s, s
    m, version, system, arch = s.split('-')
    if version != 'latest':
        assert '.' in version, version
        version = tuple(int(v) for v in version.split('.'))
    assert m.startswith('Miniconda')
    return CondaVersionTuple(version, system, arch, filename)

def _extract_versions(s):
    """Extract the available Miniconda version tuples from index page.

    >>> versions = _extract_versions('''
    ...

    ...       Miniconda-1.9.1-Linux-x86_64.sh
    ...      18.9M
    ...      2013-09-06 15:52:09
    ...      7e446886360e48bf937c3b6eca610790
    ...

    ...

    ...      Miniconda-1.6.0-Linux-x86_64.sh
    ...      18.7M
    ...      2013-06-21 15:30:53
    ...      892d6abdfe274765036ff174f2b360b0
    ...

    ...

    ...  <address>Updated: 2018-06-07 00:11:09 CDT - Files: 376</address>
    ...

    ... ''')
    >>> for v in versions:
    ...     print(v)
    CondaVersionTuple(version=(1, 9, 1), system='Linux', machine='x86_64', file='Miniconda3-1.9.1-Linux-x86_64.sh')
    CondaVersionTuple(version=(1, 6, 0), system='Linux', machine='x86_64', file='Miniconda3-1.6.0-Linux-x86_64.sh')

    """
    for x in re.findall('a href="([^"]*)"', s):
        if not x.startswith('Miniconda3'):
            continue
        v = _parse_version(x)
        if v.version == "latest":
            continue
        yield v

# FIXME: Cache the live_versions in some way?
def live_versions():
    """Get the versions currently live on conda website."""
    versions = {}
    for ver in _extract_versions(requests.get('https://repo.continuum.io/miniconda').text):
        if ver.system not in versions:
            versions[ver.system] = {}
        system_versions = versions[ver.system]
        if ver.machine not in system_versions:
            system_versions[ver.machine] = []
        machine_versions = system_versions[ver.machine]
        machine_versions.append(ver)
        machine_versions.sort()
    return versions

def installed_version():
    """
    ~/conda/bin/conda --version
    conda 4.5.9
    """
    pass

class Conda(Provider):
    """

    The Conda provider can provide;
     * Python environment which modules can be installed into.
     * Tools (such as gcc / openocd)

    """

    def __init__(self, download_dir):
        self.installer_url = self.INSTALLER_URL[platform.system()][platform.machine()]
        pass

    def install_module(self, module):
        """
# lite
for LITE in $LITE_REPOS; do
	LITE_DIR=$THIRD_DIR/$LITE
	(
		echo
		cd $LITE_DIR
		echo "Installing $LITE from $LITE_DIR (local python module)"
		python setup.py develop
	)
	check_import $LITE
done
        """
        pass

    def install_tool(self, toolname):
        """
# binutils for the target
echo
echo "Installing binutils for ${CPU} (assembler, linker, and other tools)"
conda install -y $CONDA_FLAGS binutils-${CPU}-elf=$BINUTILS_VERSION
check_version ${CPU}-elf-ld $BINUTILS_VERSION

# gcc for the target
echo
echo "Installing gcc for ${CPU} ('bare metal' C cross compiler)"
conda install -y $CONDA_FLAGS gcc-${CPU}-elf-nostdc=$GCC_VERSION
check_version ${CPU}-elf-gcc $GCC_VERSION

# gdb for the target
#echo
#echo "Installing gdb for ${CPU} (debugger)"
#conda install -y $CONDA_FLAGS gdb-${CPU}-elf=$GDB_VERSION
#check_version ${CPU}-elf-gdb $GDB_VERSION

# openocd for programming via Cypress FX2
echo
echo "Installing openocd (jtag tool for programming and debug)"
conda install -y $CONDA_FLAGS openocd=$OPENOCD_VERSION
check_version openocd $OPENOCD_VERSION
        """
        pass

    def setup(self):
        """

# Hot patch conda so to not use the systems environments.
function fix_conda {
	for py in $(find $CONDA_DIR -name envs_manager.py); do
		START_SUM=$(sha256sum $py | sed -e's/ .*//')
		sed -i -e"s^expand(join('~', '.conda', 'environments.txt'))^join('$CONDA_DIR', 'environments.txt')^" $py
		END_SUM=$(sha256sum $py | sed -e's/ .*//')
		if [ $START_SUM != $END_SUM ]; then
			sed -i -e"s/$START_SUM/$END_SUM/" $(find $CONDA_DIR -name paths.json)
		fi
	done
}

if [[ ! -e $CONDA_DIR/bin/conda ]]; then
    wget -c https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh
    chmod a+x Miniconda3-latest-Linux-x86_64.sh
    # -p to specify the install location
    # -b to enable batch mode (no prompts)
    # -f to not return an error if the location specified by -p already exists
    ./Miniconda3-latest-Linux-x86_64.sh -p $CONDA_DIR -b -f
    fix_conda
    conda config --system --set always_yes yes
    conda config --system --set changeps1 no
    conda config --system --add envs_dirs $CONDA_DIR/envs
    conda config --system --add pkgs_dirs $CONDA_DIR/pkgs
    conda update -q conda
fi
fix_conda
conda config --system --add channels timvideos
conda info
        """
        pass

if __name__ == "__main__":
    import doctest
    doctest.testmod()

    import pprint
    print()
    print("Current live conda versions")
    print("-"*75)
    pprint.pprint(live_versions())
<commit_msg>conda: Adding notes about architectures.<commit_after>#!/usr/bin/env python3

"""
Conda based provider.

https://conda.io/docs/

Conda is an open source package management system and environment management
system that runs on Windows, macOS and Linux. Conda quickly installs, runs and
updates packages and their dependencies. Conda easily creates, saves, loads and
switches between environments on your local computer. It was created for Python
programs, but it can package and distribute software for any language.
"""

import os
import re
import platform
import requests
from collections import namedtuple

from . import Provider

CondaVersionTuple = namedtuple("CondaVersionTuple", ("version", "system", "machine", "file"))

def _parse_version(filename):
    """Parse a Miniconda file name into a CondaVersionTuple object.

    >>> _parse_version('Miniconda-1.9.1-Linux-x86_64.sh')
    CondaVersionTuple(version=(1, 9, 1), system='Linux', machine='x86_64', file='Miniconda-1.9.1-Linux-x86_64.sh')
    >>> _parse_version('Miniconda3-2.2.8-Windows-x86.exe')
    CondaVersionTuple(version=(2, 2, 8), system='Windows', machine='x86', file='Miniconda3-2.2.8-Windows-x86.exe')
    >>> _parse_version('Miniconda-3.16.0-Linux-armv7l.sh')
    CondaVersionTuple(version=(3, 16, 0), system='Linux', machine='armv7l', file='Miniconda-3.16.0-Linux-armv7l.sh')
    """
    s = os.path.splitext(filename)[0]
    assert '-' in s, s
    m, version, system, arch = s.split('-')
    if version != 'latest':
        assert '.' in version, version
        version = tuple(int(v) for v in version.split('.'))
    assert m.startswith('Miniconda')
    return CondaVersionTuple(version, system, arch, filename)

def _extract_versions(s):
    """Extract the available Miniconda version tuples from index page.

    >>> versions = _extract_versions('''
    ...

    ...       Miniconda-1.9.1-Linux-x86_64.sh
    ...      18.9M
    ...      2013-09-06 15:52:09
    ...      7e446886360e48bf937c3b6eca610790
    ...

    ...

    ...      Miniconda-1.6.0-Linux-x86_64.sh
    ...      18.7M
    ...      2013-06-21 15:30:53
    ...      892d6abdfe274765036ff174f2b360b0
    ...

    ...

    ...  <address>Updated: 2018-06-07 00:11:09 CDT - Files: 376</address>
    ...

    ... ''')
    >>> for v in versions:
    ...     print(v)
    CondaVersionTuple(version=(1, 9, 1), system='Linux', machine='x86_64', file='Miniconda3-1.9.1-Linux-x86_64.sh')
    CondaVersionTuple(version=(1, 6, 0), system='Linux', machine='x86_64', file='Miniconda3-1.6.0-Linux-x86_64.sh')

    """
    for x in re.findall('a href="([^"]*)"', s):
        if not x.startswith('Miniconda3'):
            continue
        v = _parse_version(x)
        if v.version == "latest":
            continue
        yield v

# FIXME: Cache the live_versions in some way?
def live_versions():
    """Get the versions currently live on conda website."""
    versions = {}
    for ver in _extract_versions(requests.get('https://repo.continuum.io/miniconda').text):
        if ver.system not in versions:
            versions[ver.system] = {}
        system_versions = versions[ver.system]
        if ver.machine not in system_versions:
            system_versions[ver.machine] = []
        machine_versions = system_versions[ver.machine]
        machine_versions.append(ver)
        machine_versions.sort()
    return versions

def installed_version():
    """
    ~/conda/bin/conda --version
    conda 4.5.9
    """
    pass

class Conda(Provider):
    """

    The Conda provider can provide;
     * Python environment which modules can be installed into.
     * Tools (such as gcc / openocd)

    """

    def __init__(self, download_dir):
        # platform.machine() == 'x86'     32bit x86 computer
        # platform.machine() == 'x86_64'  64bit x86 computer
        # platform.machine() == 'armv6l'  Older RPi
        # platform.machine() == 'armv7l'  Newest RPi
        self.installer_url = self.INSTALLER_URL[platform.system()][platform.machine()]
        pass

    def install_module(self, module):
        """
# lite
for LITE in $LITE_REPOS; do
	LITE_DIR=$THIRD_DIR/$LITE
	(
		echo
		cd $LITE_DIR
		echo "Installing $LITE from $LITE_DIR (local python module)"
		python setup.py develop
	)
	check_import $LITE
done
        """
        pass

    def install_tool(self, toolname):
        """
# binutils for the target
echo
echo "Installing binutils for ${CPU} (assembler, linker, and other tools)"
conda install -y $CONDA_FLAGS binutils-${CPU}-elf=$BINUTILS_VERSION
check_version ${CPU}-elf-ld $BINUTILS_VERSION

# gcc for the target
echo
echo "Installing gcc for ${CPU} ('bare metal' C cross compiler)"
conda install -y $CONDA_FLAGS gcc-${CPU}-elf-nostdc=$GCC_VERSION
check_version ${CPU}-elf-gcc $GCC_VERSION

# gdb for the target
#echo
#echo "Installing gdb for ${CPU} (debugger)"
#conda install -y $CONDA_FLAGS gdb-${CPU}-elf=$GDB_VERSION
#check_version ${CPU}-elf-gdb $GDB_VERSION

# openocd for programming via Cypress FX2
echo
echo "Installing openocd (jtag tool for programming and debug)"
conda install -y $CONDA_FLAGS openocd=$OPENOCD_VERSION
check_version openocd $OPENOCD_VERSION
        """
        pass

    def setup(self):
        """

# Hot patch conda so to not use the systems environments.
function fix_conda {
	for py in $(find $CONDA_DIR -name envs_manager.py); do
		START_SUM=$(sha256sum $py | sed -e's/ .*//')
		sed -i -e"s^expand(join('~', '.conda', 'environments.txt'))^join('$CONDA_DIR', 'environments.txt')^" $py
		END_SUM=$(sha256sum $py | sed -e's/ .*//')
		if [ $START_SUM != $END_SUM ]; then
			sed -i -e"s/$START_SUM/$END_SUM/" $(find $CONDA_DIR -name paths.json)
		fi
	done
}

if [[ ! -e $CONDA_DIR/bin/conda ]]; then
    wget -c https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh
    chmod a+x Miniconda3-latest-Linux-x86_64.sh
    # -p to specify the install location
    # -b to enable batch mode (no prompts)
    # -f to not return an error if the location specified by -p already exists
    ./Miniconda3-latest-Linux-x86_64.sh -p $CONDA_DIR -b -f
    fix_conda
    conda config --system --set always_yes yes
    conda config --system --set changeps1 no
    conda config --system --add envs_dirs $CONDA_DIR/envs
    conda config --system --add pkgs_dirs $CONDA_DIR/pkgs
    conda update -q conda
fi
fix_conda
conda config --system --add channels timvideos
conda info
        """
        pass

if __name__ == "__main__":
    import doctest
    doctest.testmod()

    import pprint
    print()
    print("Current live conda versions")
    print("-"*75)
    pprint.pprint(live_versions())
<|endoftext|>


<commit_before>"""proxy.py"""

import json
import logging
import pkgutil

import requests
import jsonschema

from . import rpc
from . import exceptions

class Proxy:
    """This class acts as the remote server"""

    def __init__(self, endpoint):
        self.endpoint = endpoint

    def __getattr__(self, name):
        """Catch undefined methods and handle them as RPC requests.

        The technique is here:
        http://code.activestate.com/recipes/307618/
        """

        def attr_handler(*args, **kwargs):
            return self.request(name, *args, **kwargs)

        return attr_handler

    def request(self, method_name, *args, **kwargs):
        """Send the request and expect a response."""

        kwargs['response'] = True
        return self.handle_response(
            self.send_message(rpc.request(method_name, *args, **kwargs)), True)

    def notify(self, method_name, *args, **kwargs):
        """Really just an alias for _send()"""

        return self.handle_response(
            self.send_message(rpc.request(method_name, *args, **kwargs)), False)

    def send_message(self, request_dict):
        """Send the RPC request to the proxy server.

        Calls a procedure on another server.
        Raises RPCClientException: On any error caught.
        """

        # Log the request
        logging.info('--> '+json.dumps(request_dict))

        try:
            # Send the message
            r = requests.post(
                self.endpoint,
                headers={
                    'Content-Type': 'application/json; charset=utf-8'
                },
                json=request_dict
            )

            logging.info('<-- '+r.text.strip("\n"))

        except (requests.exceptions.InvalidSchema,
                requests.exceptions.RequestException):
            raise exceptions.ConnectionError()

        # Raise exception the HTTP status code was not 200, and there was no
        # response body, because this should be handled.
        if not len(r.text) and r.status_code != 200:
            raise exceptions.StatusCodeError(r.status_code)

        return r.text

    @staticmethod
    def handle_response(response_str, expected_response=True):
        """Processes the response from a request"""

        # A response was expected, but none was given?
        if expected_response and not len(response_str):
            raise exceptions.ReceivedNoResponse()

        # Was response given?
        if len(response_str):

            # Attempt to parse the response
            try:
                response_dict = json.loads(response_str)

            except ValueError:
                raise exceptions.ParseError()

            # A response was *not* expected, but one was given? It may not
            # be necessary to raise here. If we receive a response anyway,
            # can't we just ignore it?
            if not expected_response and 'result' in response_dict:
                raise exceptions.InvalidResponse()

            # Validate the response against the Response schema
            try:
                jsonschema.validate(
                    response_dict,
                    json.loads(pkgutil.get_data(
                        __name__, 'response-schema.json').decode('utf-8')))

            except jsonschema.ValidationError:
                raise exceptions.InvalidResponse()

            # If the response was "error", raise it, to ensure it's handled
            if 'error' in response_dict:
                raise exceptions.ReceivedErrorResponse(
                    response_dict['error']['code'],
                    response_dict['error']['message'])

            # Otherwise, surely we have a result to return
            print(response_dict['result'])

        return None
<commit_msg>Added docstring to appease pylint<commit_after>"""proxy.py"""

import json
import logging
import pkgutil

import requests
import jsonschema

from . import rpc
from . import exceptions

class Proxy:
    """This class acts as the remote server"""

    def __init__(self, endpoint):
        self.endpoint = endpoint

    def __getattr__(self, name):
        """Catch undefined methods and handle them as RPC requests.

        The technique is here:
        http://code.activestate.com/recipes/307618/
        """

        def attr_handler(*args, **kwargs):
            """Call self.request from here"""
            return self.request(name, *args, **kwargs)

        return attr_handler

    def request(self, method_name, *args, **kwargs):
        """Send the request and expect a response."""

        kwargs['response'] = True
        return self.handle_response(
            self.send_message(rpc.request(method_name, *args, **kwargs)), True)

    def notify(self, method_name, *args, **kwargs):
        """Really just an alias for _send()"""

        return self.handle_response(
            self.send_message(rpc.request(method_name, *args, **kwargs)), False)

    def send_message(self, request_dict):
        """Send the RPC request to the proxy server.

        Calls a procedure on another server.
        Raises RPCClientException: On any error caught.
        """

        # Log the request
        logging.info('--> '+json.dumps(request_dict))

        try:
            # Send the message
            r = requests.post(
                self.endpoint,
                headers={
                    'Content-Type': 'application/json; charset=utf-8'
                },
                json=request_dict
            )

            logging.info('<-- '+r.text.strip("\n"))

        except (requests.exceptions.InvalidSchema,
                requests.exceptions.RequestException):
            raise exceptions.ConnectionError()

        # Raise exception the HTTP status code was not 200, and there was no
        # response body, because this should be handled.
        if not len(r.text) and r.status_code != 200:
            raise exceptions.StatusCodeError(r.status_code)

        return r.text

    @staticmethod
    def handle_response(response_str, expected_response=True):
        """Processes the response from a request"""

        # A response was expected, but none was given?
        if expected_response and not len(response_str):
            raise exceptions.ReceivedNoResponse()

        # Was response given?
        if len(response_str):

            # Attempt to parse the response
            try:
                response_dict = json.loads(response_str)

            except ValueError:
                raise exceptions.ParseError()

            # A response was *not* expected, but one was given? It may not
            # be necessary to raise here. If we receive a response anyway,
            # can't we just ignore it?
            if not expected_response and 'result' in response_dict:
                raise exceptions.InvalidResponse()

            # Validate the response against the Response schema
            try:
                jsonschema.validate(
                    response_dict,
                    json.loads(pkgutil.get_data(
                        __name__, 'response-schema.json').decode('utf-8')))

            except jsonschema.ValidationError:
                raise exceptions.InvalidResponse()

            # If the response was "error", raise it, to ensure it's handled
            if 'error' in response_dict:
                raise exceptions.ReceivedErrorResponse(
                    response_dict['error']['code'],
                    response_dict['error']['message'])

            # Otherwise, surely we have a result to return
            print(response_dict['result'])

        return None
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo import api, models, fields, _, SUPERUSER_ID
from odoo.exceptions import AccessError

class User(models.Model):
    _inherit = ['res.users']

    # note: a user can only be linked to one employee per company (see sql constraint in ´hr.employee´)
    employee_ids = fields.One2many('hr.employee', 'user_id', string='Related employee')
    employee_id = fields.Many2one('hr.employee', string="Company employee",
        compute='_compute_company_employee', search='_search_company_employee', store=False)

    job_title = fields.Char(related='employee_id.job_title', readonly=False)
    work_phone = fields.Char(related='employee_id.work_phone', readonly=False)
    mobile_phone = fields.Char(related='employee_id.mobile_phone', readonly=False)
    employee_phone = fields.Char(related='employee_id.phone', readonly=False, related_sudo=False)
    work_email = fields.Char(related='employee_id.work_email', readonly=False, related_sudo=False)
    category_ids = fields.Many2many(related='employee_id.category_ids', string="Employee Tags", readonly=False, related_sudo=False)
    department_id = fields.Many2one(related='employee_id.department_id', readonly=False, related_sudo=False)
    address_id = fields.Many2one(related='employee_id.address_id', readonly=False, related_sudo=False)
    work_location = fields.Char(related='employee_id.work_location', readonly=False, related_sudo=False)
    employee_parent_id = fields.Many2one(related='employee_id.parent_id', related_sudo=False)
    coach_id = fields.Many2one(related='employee_id.coach_id', readonly=False, related_sudo=False)
    address_home_id = fields.Many2one(related='employee_id.address_home_id', readonly=False, related_sudo=False)
    is_address_home_a_company = fields.Boolean(related='employee_id.is_address_home_a_company', readonly=False, related_sudo=False)
    private_email = fields.Char(related='address_home_id.email', string="Private Email", readonly=False)
    km_home_work = fields.Integer(related='employee_id.km_home_work', readonly=False, related_sudo=False)
    # res.users already have a field bank_account_id and country_id from the res.partner inheritance: don't redefine them
    employee_bank_account_id = fields.Many2one(related='employee_id.bank_account_id', string="Employee's Bank Account Number", related_sudo=False, readonly=False)
    employee_country_id = fields.Many2one(related='employee_id.country_id', string="Employee's Country", readonly=False, related_sudo=False)
    identification_id = fields.Char(related='employee_id.identification_id', readonly=False, related_sudo=False)
    passport_id = fields.Char(related='employee_id.passport_id', readonly=False, related_sudo=False)
    gender = fields.Selection(related='employee_id.gender', readonly=False, related_sudo=False)
    birthday = fields.Date(related='employee_id.birthday', readonly=False, related_sudo=False)
    place_of_birth = fields.Char(related='employee_id.place_of_birth', readonly=False, related_sudo=False)
    country_of_birth = fields.Many2one(related='employee_id.country_of_birth', readonly=False, related_sudo=False)
    marital = fields.Selection(related='employee_id.marital', readonly=False, related_sudo=False)
    spouse_complete_name = fields.Char(related='employee_id.spouse_complete_name', readonly=False, related_sudo=False)
    spouse_birthdate = fields.Date(related='employee_id.spouse_birthdate', readonly=False, related_sudo=False)
    children = fields.Integer(related='employee_id.children', readonly=False, related_sudo=False)
    emergency_contact = fields.Char(related='employee_id.emergency_contact', readonly=False, related_sudo=False)
    emergency_phone = fields.Char(related='employee_id.emergency_phone', readonly=False, related_sudo=False)
    visa_no = fields.Char(related='employee_id.visa_no', readonly=False, related_sudo=False)
    permit_no = fields.Char(related='employee_id.permit_no', readonly=False, related_sudo=False)
    visa_expire = fields.Date(related='employee_id.visa_expire', readonly=False, related_sudo=False)
    additional_note = fields.Text(related='employee_id.additional_note', readonly=False, related_sudo=False)
    barcode = fields.Char(related='employee_id.barcode', readonly=False, related_sudo=False)
    pin = fields.Char(related='employee_id.pin', readonly=False, related_sudo=False)
    certificate = fields.Selection(related='employee_id.certificate', readonly=False, related_sudo=False)
    study_field = fields.Char(related='employee_id.study_field', readonly=False, related_sudo=False)
    study_school = fields.Char(related='employee_id.study_school', readonly=False, related_sudo=False)
    employee_count = fields.Integer(compute='_compute_employee_count')
    hr_presence_state = fields.Selection(related='employee_id.hr_presence_state')
    last_activity = fields.Date(related='employee_id.last_activity')
    last_activity_time = fields.Char(related='employee_id.last_activity_time')

    can_edit = fields.Boolean(compute='_compute_can_edit')

    def _compute_can_edit(self):
        can_edit = self.env['ir.config_parameter'].sudo().get_param('hr.hr_employee_self_edit') or self.env.user.has_group('hr.group_hr_user')
        for user in self:
            user.can_edit = can_edit

    @api.depends('employee_ids')
    def _compute_employee_count(self):
        for user in self.with_context(active_test=False):
            user.employee_count = len(user.employee_ids)

    def __init__(self, pool, cr):
        """ Override of __init__ to add access rights.
            Access rights are disabled by default, but allowed
            on some specific fields defined in self.SELF_{READ/WRITE}ABLE_FIELDS.
        """
        hr_readable_fields = [
            'active',
            'child_ids',
            'employee_id',
            'employee_ids',
            'employee_parent_id',
            'hr_presence_state',
            'last_activity',
            'last_activity_time',
            'can_edit',
        ]

        hr_writable_fields = [
            'additional_note',
            'address_home_id',
            'address_id',
            'barcode',
            'birthday',
            'category_ids',
            'children',
            'coach_id',
            'country_of_birth',
            'department_id',
            'display_name',
            'emergency_contact',
            'emergency_phone',
            'employee_bank_account_id',
            'employee_country_id',
            'gender',
            'identification_id',
            'is_address_home_a_company',
            'job_title',
            'private_email',
            'km_home_work',
            'marital',
            'mobile_phone',
            'notes',
            'employee_parent_id',
            'passport_id',
            'permit_no',
            'employee_phone',
            'pin',
            'place_of_birth',
            'spouse_birthdate',
            'spouse_complete_name',
            'visa_expire',
            'visa_no',
            'work_email',
            'work_location',
            'work_phone',
            'certificate',
            'study_field',
            'study_school',
        ]

        init_res = super(User, self).__init__(pool, cr)
        # duplicate list to avoid modifying the original reference
        type(self).SELF_READABLE_FIELDS = type(self).SELF_READABLE_FIELDS + hr_readable_fields + hr_writable_fields
        type(self).SELF_WRITEABLE_FIELDS = type(self).SELF_WRITEABLE_FIELDS + hr_writable_fields
        return init_res

    @api.model
    def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
        # When the front-end loads the views it gets the list of available fields
        # for the user (according to its access rights). Later, when the front-end wants to
        # populate the view with data, it only asks to read those available fields.
        # However, in this case, we want the user to be able to read/write its own data,
        # even if they are protected by groups.
        # We make the front-end aware of those fields by sending all field definitions.
        # Note: limit the `sudo` to the only action of "editing own profile" action in order to
        # avoid breaking `groups` mecanism on res.users form view.
        profile_view = self.env.ref("hr.res_users_view_form_profile")
        if profile_view and view_id == profile_view.id:
            self = self.with_user(SUPERUSER_ID)
        return super(User, self).fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu)

    def write(self, vals):
        """
        Synchronize user and its related employee
        and check access rights if employees are not allowed to update
        their own data (otherwise sudo is applied for self data).
        """
        hr_fields = {
            field
            for field_name, field in self._fields.items()
            if field.related_field and field.related_field.model_name == 'hr.employee' and field_name in vals
        }
        can_edit_self = self.env['ir.config_parameter'].sudo().get_param('hr.hr_employee_self_edit') or self.env.user.has_group('hr.group_hr_user')
        if hr_fields and not can_edit_self:
            # Raise meaningful error message
            raise AccessError(_("You are only allowed to update your preferences. Please contact a HR officer to update other informations."))

        result = super(User, self).write(vals)

        employee_values = {}
        for fname in [f for f in ['name', 'email', 'image_1920', 'tz'] if f in vals]:
            employee_values[fname] = vals[fname]
        if employee_values:
            if 'email' in employee_values:
                employee_values['work_email'] = employee_values.pop('email')
            if 'image_1920' in vals:
                without_image = self.env['hr.employee'].sudo().search([('user_id', 'in', self.ids), ('image_1920', '=', False)])
                with_image = self.env['hr.employee'].sudo().search([('user_id', 'in', self.ids), ('image_1920', '!=', False)])
                without_image.write(employee_values)
                if not can_edit_self:
                    employee_values.pop('image_1920')
                with_image.write(employee_values)
            else:
                self.env['hr.employee'].sudo().search([('user_id', 'in', self.ids)]).write(employee_values)
        return result

    @api.model
    def action_get(self):
        if self.env.user.employee_id:
            return self.sudo().env.ref('hr.res_users_action_my').read()[0]
        return super(User, self).action_get()

    @api.depends('employee_ids')
    @api.depends_context('company')
    def _compute_company_employee(self):
        for user in self:
            user.employee_id = self.env['hr.employee'].search([('id', 'in', user.employee_ids.ids), ('company_id', '=', self.env.company.id)], limit=1)

    def _search_company_employee(self, operator, value):
        employees = self.env['hr.employee'].search([
            ('name', operator, value),
            '|',
            ('company_id', '=', self.env.company.id),
            ('company_id', '=', False)
        ], order='company_id ASC')
        return [('id', 'in', employees.mapped('user_id').ids)]

    def action_create_employee(self):
        self.ensure_one()
        self.env['hr.employee'].create(dict(
            user_id=self.id,
            name=self.name,
            **self.env['hr.employee']._sync_user(self)
        ))
<commit_msg>[FIX] hr: fix employee creation from user form<commit_after># -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo import api, models, fields, _, SUPERUSER_ID
from odoo.exceptions import AccessError

class User(models.Model):
    _inherit = ['res.users']

    # note: a user can only be linked to one employee per company (see sql constraint in ´hr.employee´)
    employee_ids = fields.One2many('hr.employee', 'user_id', string='Related employee')
    employee_id = fields.Many2one('hr.employee', string="Company employee",
        compute='_compute_company_employee', search='_search_company_employee', store=False)

    job_title = fields.Char(related='employee_id.job_title', readonly=False)
    work_phone = fields.Char(related='employee_id.work_phone', readonly=False)
    mobile_phone = fields.Char(related='employee_id.mobile_phone', readonly=False)
    employee_phone = fields.Char(related='employee_id.phone', readonly=False, related_sudo=False)
    work_email = fields.Char(related='employee_id.work_email', readonly=False, related_sudo=False)
    category_ids = fields.Many2many(related='employee_id.category_ids', string="Employee Tags", readonly=False, related_sudo=False)
    department_id = fields.Many2one(related='employee_id.department_id', readonly=False, related_sudo=False)
    address_id = fields.Many2one(related='employee_id.address_id', readonly=False, related_sudo=False)
    work_location = fields.Char(related='employee_id.work_location', readonly=False, related_sudo=False)
    employee_parent_id = fields.Many2one(related='employee_id.parent_id', related_sudo=False)
    coach_id = fields.Many2one(related='employee_id.coach_id', readonly=False, related_sudo=False)
    address_home_id = fields.Many2one(related='employee_id.address_home_id', readonly=False, related_sudo=False)
    is_address_home_a_company = fields.Boolean(related='employee_id.is_address_home_a_company', readonly=False, related_sudo=False)
    private_email = fields.Char(related='address_home_id.email', string="Private Email", readonly=False)
    km_home_work = fields.Integer(related='employee_id.km_home_work', readonly=False, related_sudo=False)
    # res.users already have a field bank_account_id and country_id from the res.partner inheritance: don't redefine them
    employee_bank_account_id = fields.Many2one(related='employee_id.bank_account_id', string="Employee's Bank Account Number", related_sudo=False, readonly=False)
    employee_country_id = fields.Many2one(related='employee_id.country_id', string="Employee's Country", readonly=False, related_sudo=False)
    identification_id = fields.Char(related='employee_id.identification_id', readonly=False, related_sudo=False)
    passport_id = fields.Char(related='employee_id.passport_id', readonly=False, related_sudo=False)
    gender = fields.Selection(related='employee_id.gender', readonly=False, related_sudo=False)
    birthday = fields.Date(related='employee_id.birthday', readonly=False, related_sudo=False)
    place_of_birth = fields.Char(related='employee_id.place_of_birth', readonly=False, related_sudo=False)
    country_of_birth = fields.Many2one(related='employee_id.country_of_birth', readonly=False, related_sudo=False)
    marital = fields.Selection(related='employee_id.marital', readonly=False, related_sudo=False)
    spouse_complete_name = fields.Char(related='employee_id.spouse_complete_name', readonly=False, related_sudo=False)
    spouse_birthdate = fields.Date(related='employee_id.spouse_birthdate', readonly=False, related_sudo=False)
    children = fields.Integer(related='employee_id.children', readonly=False, related_sudo=False)
    emergency_contact = fields.Char(related='employee_id.emergency_contact', readonly=False, related_sudo=False)
    emergency_phone = fields.Char(related='employee_id.emergency_phone', readonly=False, related_sudo=False)
    visa_no = fields.Char(related='employee_id.visa_no', readonly=False, related_sudo=False)
    permit_no = fields.Char(related='employee_id.permit_no', readonly=False, related_sudo=False)
    visa_expire = fields.Date(related='employee_id.visa_expire', readonly=False, related_sudo=False)
    additional_note = fields.Text(related='employee_id.additional_note', readonly=False, related_sudo=False)
    barcode = fields.Char(related='employee_id.barcode', readonly=False, related_sudo=False)
    pin = fields.Char(related='employee_id.pin', readonly=False, related_sudo=False)
    certificate = fields.Selection(related='employee_id.certificate', readonly=False, related_sudo=False)
    study_field = fields.Char(related='employee_id.study_field', readonly=False, related_sudo=False)
    study_school = fields.Char(related='employee_id.study_school', readonly=False, related_sudo=False)
    employee_count = fields.Integer(compute='_compute_employee_count')
    hr_presence_state = fields.Selection(related='employee_id.hr_presence_state')
    last_activity = fields.Date(related='employee_id.last_activity')
    last_activity_time = fields.Char(related='employee_id.last_activity_time')

    can_edit = fields.Boolean(compute='_compute_can_edit')

    def _compute_can_edit(self):
        can_edit = self.env['ir.config_parameter'].sudo().get_param('hr.hr_employee_self_edit') or self.env.user.has_group('hr.group_hr_user')
        for user in self:
            user.can_edit = can_edit

    @api.depends('employee_ids')
    def _compute_employee_count(self):
        for user in self.with_context(active_test=False):
            user.employee_count = len(user.employee_ids)

    def __init__(self, pool, cr):
        """ Override of __init__ to add access rights.
            Access rights are disabled by default, but allowed
            on some specific fields defined in self.SELF_{READ/WRITE}ABLE_FIELDS.
        """
        hr_readable_fields = [
            'active',
            'child_ids',
            'employee_id',
            'employee_ids',
            'employee_parent_id',
            'hr_presence_state',
            'last_activity',
            'last_activity_time',
            'can_edit',
        ]

        hr_writable_fields = [
            'additional_note',
            'address_home_id',
            'address_id',
            'barcode',
            'birthday',
            'category_ids',
            'children',
            'coach_id',
            'country_of_birth',
            'department_id',
            'display_name',
            'emergency_contact',
            'emergency_phone',
            'employee_bank_account_id',
            'employee_country_id',
            'gender',
            'identification_id',
            'is_address_home_a_company',
            'job_title',
            'private_email',
            'km_home_work',
            'marital',
            'mobile_phone',
            'notes',
            'employee_parent_id',
            'passport_id',
            'permit_no',
            'employee_phone',
            'pin',
            'place_of_birth',
            'spouse_birthdate',
            'spouse_complete_name',
            'visa_expire',
            'visa_no',
            'work_email',
            'work_location',
            'work_phone',
            'certificate',
            'study_field',
            'study_school',
        ]

        init_res = super(User, self).__init__(pool, cr)
        # duplicate list to avoid modifying the original reference
        type(self).SELF_READABLE_FIELDS = type(self).SELF_READABLE_FIELDS + hr_readable_fields + hr_writable_fields
        type(self).SELF_WRITEABLE_FIELDS = type(self).SELF_WRITEABLE_FIELDS + hr_writable_fields
        return init_res

    @api.model
    def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
        # When the front-end loads the views it gets the list of available fields
        # for the user (according to its access rights). Later, when the front-end wants to
        # populate the view with data, it only asks to read those available fields.
        # However, in this case, we want the user to be able to read/write its own data,
        # even if they are protected by groups.
        # We make the front-end aware of those fields by sending all field definitions.
        # Note: limit the `sudo` to the only action of "editing own profile" action in order to
        # avoid breaking `groups` mecanism on res.users form view.
        profile_view = self.env.ref("hr.res_users_view_form_profile")
        if profile_view and view_id == profile_view.id:
            self = self.with_user(SUPERUSER_ID)
        return super(User, self).fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu)

    def write(self, vals):
        """
        Synchronize user and its related employee
        and check access rights if employees are not allowed to update
        their own data (otherwise sudo is applied for self data).
        """
        hr_fields = {
            field
            for field_name, field in self._fields.items()
            if field.related_field and field.related_field.model_name == 'hr.employee' and field_name in vals
        }
        can_edit_self = self.env['ir.config_parameter'].sudo().get_param('hr.hr_employee_self_edit') or self.env.user.has_group('hr.group_hr_user')
        if hr_fields and not can_edit_self:
            # Raise meaningful error message
            raise AccessError(_("You are only allowed to update your preferences. Please contact a HR officer to update other informations."))

        result = super(User, self).write(vals)

        employee_values = {}
        for fname in [f for f in ['name', 'email', 'image_1920', 'tz'] if f in vals]:
            employee_values[fname] = vals[fname]
        if employee_values:
            if 'email' in employee_values:
                employee_values['work_email'] = employee_values.pop('email')
            if 'image_1920' in vals:
                without_image = self.env['hr.employee'].sudo().search([('user_id', 'in', self.ids), ('image_1920', '=', False)])
                with_image = self.env['hr.employee'].sudo().search([('user_id', 'in', self.ids), ('image_1920', '!=', False)])
                without_image.write(employee_values)
                if not can_edit_self:
                    employee_values.pop('image_1920')
                with_image.write(employee_values)
            else:
                self.env['hr.employee'].sudo().search([('user_id', 'in', self.ids)]).write(employee_values)
        return result

    @api.model
    def action_get(self):
        if self.env.user.employee_id:
            return self.sudo().env.ref('hr.res_users_action_my').read()[0]
        return super(User, self).action_get()

    @api.depends('employee_ids')
    @api.depends_context('company')
    def _compute_company_employee(self):
        for user in self:
            user.employee_id = self.env['hr.employee'].search([('id', 'in', user.employee_ids.ids), ('company_id', '=', self.env.company.id)], limit=1)

    def _search_company_employee(self, operator, value):
        employees = self.env['hr.employee'].search([
            ('name', operator, value),
            '|',
            ('company_id', '=', self.env.company.id),
            ('company_id', '=', False)
        ], order='company_id ASC')
        return [('id', 'in', employees.mapped('user_id').ids)]

    def action_create_employee(self):
        self.ensure_one()
        self.env['hr.employee'].create(dict(
            name=self.name,
            **self.env['hr.employee']._sync_user(self)
        ))
<|endoftext|>


<commit_before>from django.contrib import messages
from django.core.urlresolvers import reverse
from django.shortcuts import (
    get_object_or_404,
)
from django.views.generic import (
    CreateView,
    DeleteView,
    ListView,
    UpdateView,
    FormView,
)
from django.utils import timezone

from contacts.models import (
    Contact,
    BookOwner,
    Tag,
)

from contacts import forms
from contacts.views import BookOwnerMixin

class ContactListView(BookOwnerMixin, ListView):

    model = Contact
    template_name = 'contact_list.html'

    def get_queryset(self):
        qs = super(ContactListView, self).get_queryset()
        return qs.order_by('name')

    def get_context_data(self, **kwargs):
        context = super(ContactListView, self).get_context_data(**kwargs)
        context['tags'] = Tag.objects.filter(book__bookowner__user=self.request.user)
        return context

class ContactView(BookOwnerMixin, FormView):

    template_name = 'contact.html'
    form_class = forms.LogEntryForm

    def dispatch(self, request, **kwargs):
        self.contact = get_object_or_404(
            Contact.objects,
            pk=self.kwargs.get('pk'),
            book__bookowner__user=self.request.user,
        )
        return super(ContactView, self).dispatch(request, **kwargs)

    def get_success_url(self):
        return reverse(
            'contacts-view',
            kwargs={'pk': self.kwargs.get('pk')},
        )

    def get_context_data(self, **kwargs):
        context = super(ContactView, self).get_context_data(**kwargs)
        context['contact'] = self.contact
        context['logs'] = self.contact.logentry_set.all().order_by('-created')
        return context

    def form_valid(self, form):
        new_log = form.save(commit=False)
        new_log.contact = self.contact
        new_log.logged_by = self.request.user
        if not form.cleaned_data.get('time'):
            form.cleaned_data['time'] = timezone.now()
        form.save()
        messages.success(
            self.request,
            "Log added",
        )
        return super(ContactView, self).form_valid(form)

class CreateContactView(BookOwnerMixin, CreateView):

    model = Contact
    template_name = 'edit_contact.html'
    form_class = forms.ContactForm

    def get_success_url(self):
        return reverse('contacts-view', kwargs={'pk': self.object.id})

    def get_form_kwargs(self):
        kwargs = super(CreateContactView, self).get_form_kwargs()
        kwargs['book'] = BookOwner.objects.get(user=self.request.user).book
        return kwargs

    def get_context_data(self, **kwargs):
        context = super(CreateContactView, self).get_context_data(**kwargs)
        context['action'] = reverse('contacts-new')
        return context

    def form_valid(self, form):
        messages.success(
            self.request,
            "Contact added",
        )
        return super(CreateContactView, self).form_valid(form)

class EditContactView(BookOwnerMixin, UpdateView):
    model = Contact
    template_name = 'edit_contact.html'
    form_class = forms.ContactForm

    def get_success_url(self):
        return reverse(
            'contacts-view',
            kwargs={'pk': self.get_object().id},
        )

    def get_form_kwargs(self):
        kwargs = super(EditContactView, self).get_form_kwargs()
        kwargs['book'] = BookOwner.objects.get(user=self.request.user).book
        return kwargs

    def get_context_data(self, **kwargs):
        context = super(EditContactView, self).get_context_data(**kwargs)
        context['action'] = reverse(
            'contacts-edit',
            kwargs={'pk': self.get_object().id},
        )

        return context

    def form_valid(self, form):
        messages.success(
            self.request,
            "Contact updated",
        )
        return super(EditContactView, self).form_valid(form)

class DeleteContactView(BookOwnerMixin, DeleteView):

    model = Contact
    template_name = 'delete_contact.html'

    def get_success_url(self):
        return reverse('contacts-list')

    def form_valid(self, form):
        messages.success(
            self.request,
            "Contact deleted",
        )
        return super(DeleteContactView, self).form_valid(form)

class CreateTagView(BookOwnerMixin, CreateView):
    model = Tag
    template_name = 'edit_tag.html'
    form_class = forms.TagForm

    def get_success_url(self):
        return reverse('contacts-list')

    def get_context_data(self, **kwargs):
        context = super(CreateTagView, self).get_context_data(**kwargs)
        context['action'] = reverse('tags-new')

        return context

    def form_valid(self, form):
        messages.success(
            self.request,
            "Tag created",
        )
        return super(CreateTagView, self).form_valid(form)

class TaggedContactListView(BookOwnerMixin, ListView):

    model = Contact
    template_name = 'contact_list.html'

    def get_queryset(self):
        return Contact.objects.filter(
            tags__id=self.kwargs.get('pk'),
        ).order_by('name')

    def get_context_data(self, **kwargs):
        context = super(TaggedContactListView, self).get_context_data(**kwargs)
        self.tag = get_object_or_404(
            Tag.objects,
            pk=self.kwargs.get('pk'),
            book__bookowner__user=self.request.user,
        )
        context['tag'] = self.tag
        context['tags'] = Tag.objects.all()

        return context

<commit_msg>Only show tags the user owns<commit_after>from django.contrib import messages
from django.core.urlresolvers import reverse
from django.shortcuts import (
    get_object_or_404,
)
from django.views.generic import (
    CreateView,
    DeleteView,
    ListView,
    UpdateView,
    FormView,
)
from django.utils import timezone

from contacts.models import (
    Contact,
    BookOwner,
    Tag,
)

from contacts import forms
from contacts.views import BookOwnerMixin

class ContactListView(BookOwnerMixin, ListView):

    model = Contact
    template_name = 'contact_list.html'

    def get_queryset(self):
        qs = super(ContactListView, self).get_queryset()
        return qs.order_by('name')

    def get_context_data(self, **kwargs):
        context = super(ContactListView, self).get_context_data(**kwargs)
        context['tags'] = Tag.objects.filter(book__bookowner__user=self.request.user)
        return context

class ContactView(BookOwnerMixin, FormView):

    template_name = 'contact.html'
    form_class = forms.LogEntryForm

    def dispatch(self, request, **kwargs):
        self.contact = get_object_or_404(
            Contact.objects,
            pk=self.kwargs.get('pk'),
            book__bookowner__user=self.request.user,
        )
        return super(ContactView, self).dispatch(request, **kwargs)

    def get_success_url(self):
        return reverse(
            'contacts-view',
            kwargs={'pk': self.kwargs.get('pk')},
        )

    def get_context_data(self, **kwargs):
        context = super(ContactView, self).get_context_data(**kwargs)
        context['contact'] = self.contact
        context['logs'] = self.contact.logentry_set.all().order_by('-created')
        return context

    def form_valid(self, form):
        new_log = form.save(commit=False)
        new_log.contact = self.contact
        new_log.logged_by = self.request.user
        if not form.cleaned_data.get('time'):
            form.cleaned_data['time'] = timezone.now()
        form.save()
        messages.success(
            self.request,
            "Log added",
        )
        return super(ContactView, self).form_valid(form)

class CreateContactView(BookOwnerMixin, CreateView):

    model = Contact
    template_name = 'edit_contact.html'
    form_class = forms.ContactForm

    def get_success_url(self):
        return reverse('contacts-view', kwargs={'pk': self.object.id})

    def get_form_kwargs(self):
        kwargs = super(CreateContactView, self).get_form_kwargs()
        kwargs['book'] = BookOwner.objects.get(user=self.request.user).book
        return kwargs

    def get_context_data(self, **kwargs):
        context = super(CreateContactView, self).get_context_data(**kwargs)
        context['action'] = reverse('contacts-new')
        return context

    def form_valid(self, form):
        messages.success(
            self.request,
            "Contact added",
        )
        return super(CreateContactView, self).form_valid(form)

class EditContactView(BookOwnerMixin, UpdateView):
    model = Contact
    template_name = 'edit_contact.html'
    form_class = forms.ContactForm

    def get_success_url(self):
        return reverse(
            'contacts-view',
            kwargs={'pk': self.get_object().id},
        )

    def get_form_kwargs(self):
        kwargs = super(EditContactView, self).get_form_kwargs()
        kwargs['book'] = BookOwner.objects.get(user=self.request.user).book
        return kwargs

    def get_context_data(self, **kwargs):
        context = super(EditContactView, self).get_context_data(**kwargs)
        context['action'] = reverse(
            'contacts-edit',
            kwargs={'pk': self.get_object().id},
        )

        return context

    def form_valid(self, form):
        messages.success(
            self.request,
            "Contact updated",
        )
        return super(EditContactView, self).form_valid(form)

class DeleteContactView(BookOwnerMixin, DeleteView):

    model = Contact
    template_name = 'delete_contact.html'

    def get_success_url(self):
        return reverse('contacts-list')

    def form_valid(self, form):
        messages.success(
            self.request,
            "Contact deleted",
        )
        return super(DeleteContactView, self).form_valid(form)

class CreateTagView(BookOwnerMixin, CreateView):
    model = Tag
    template_name = 'edit_tag.html'
    form_class = forms.TagForm

    def get_success_url(self):
        return reverse('contacts-list')

    def get_context_data(self, **kwargs):
        context = super(CreateTagView, self).get_context_data(**kwargs)
        context['action'] = reverse('tags-new')

        return context

    def form_valid(self, form):
        messages.success(
            self.request,
            "Tag created",
        )
        return super(CreateTagView, self).form_valid(form)

class TaggedContactListView(BookOwnerMixin, ListView):

    model = Contact
    template_name = 'contact_list.html'

    def get_queryset(self):
        return Contact.objects.filter(
            tags__id=self.kwargs.get('pk'),
        ).order_by('name')

    def get_context_data(self, **kwargs):
        context = super(TaggedContactListView, self).get_context_data(**kwargs)
        self.tag = get_object_or_404(
            Tag.objects,
            pk=self.kwargs.get('pk'),
            book__bookowner__user=self.request.user,
        )
        context['tag'] = self.tag
        context['tags'] = Tag.objects.get_tags_for_user(self.request.user)

        return context

<|endoftext|>


<commit_before># Copyright 2014 Cloudbase Solutions Srl
# All Rights Reserved.
#
#    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 base64
import collections
import contextlib
import logging
import os
import pkgutil
import random
import socket
import struct
import subprocess
import sys
import time

import six

from argus import config
from argus import exceptions
from argus import remote_client

RETRY_COUNT = 15
RETRY_DELAY = 10

__all__ = (
    'WinRemoteClient',
    'decrypt_password',
    'get_config',
    'get_logger',
    'get_resource',
    'cached_property',
    'run_once',
    'rand_name',
    'get_public_keys',
    'get_certificate',
)

DEFAULT_FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
DEFAULT_LOG_FILE = 'argus.log'

NETWORK_KEYS = [
    "mac",
    "address",
    "address6",
    "gateway",
    "gateway6",
    "netmask",
    "netmask6",
    "dns",
    "dns6",
    "dhcp"
]

class WinRemoteClient(remote_client.WinRemoteClient):

    def run_command(self, cmd):
        """Run the given command and return execution details.

        :rtype: tuple
        :returns: stdout, stderr, exit_code
        """

        LOG.info("Running command %s...", cmd)
        return self.run_remote_cmd(cmd)

    def run_command_verbose(self, cmd):
        """Run the given command and log anything it returns.

        Do this with retrying support.

        :rtype: string
        :returns: stdout
        """
        stdout, stderr, exit_code = self.run_command_with_retry(cmd)
        LOG.info("The command returned the output: %s", stdout)
        LOG.info("The stderr of the command was: %s", stderr)
        LOG.info("The exit code of the command was: %s", exit_code)
        return stdout

    def run_command_with_retry(self, cmd, count=RETRY_COUNT,
                               delay=RETRY_DELAY):
        """Run the given `cmd` until succeeds.

        :param cmd:
            A string, representing a command which needs to
            be executed on the underlying remote client.
        :param count:
            The number of retries which this function has.
            If the value is ``None``, then the function will retry *forever*.
        :param delay:
            The number of seconds to sleep when retrying a command.

        :rtype: tuple
        :returns: stdout, stderr, exit_code
        """

        # Countdown normalization.
        if not count or count < 0:
            count = 0

        while True:
            try:
                return self.run_command(cmd)
            except Exception as exc:  # pylint: disable=broad-except
                LOG.debug("Command failed with %r.", exc)
                # A negative `count` means no count at all.
                if count >= 0:
                    count -= 1
                if count == 0:
                    raise exceptions.ArgusTimeoutError(
                        "Command {!r} failed too many times."
                        .format(cmd))
                LOG.debug("Retrying...")
                time.sleep(delay)

    def run_command_until_condition(self, cmd, cond, retry_count=RETRY_COUNT,
                                    delay=RETRY_DELAY):
        """Run the given `cmd` until a condition `cond` occurs.

        :param cond:
            A callable which receives the standard output returned by
            executing the command. It should return a boolean value,
            which tells to this function to stop execution.
        :raises:
            `ArgusCLIError` if there is output found in the standard error.

        This method uses and behaves like `run_command_with_retry` but
        with an additional condition parameter.
        """

        # countdown normalization
        if not retry_count or retry_count < 0:
            retry_count = 0

        while True:
            try:
                stdout, stderr, _ = self.run_command(cmd)
            except Exception as exc:  # pylint: disable=broad-except
                LOG.debug("Command failed with %r.", exc)
            else:
                if stderr:
                    raise exceptions.ArgusCLIError(
                        "Executing command {!r} failed with {!r}."
                        .format(cmd, stderr))
                elif cond(stdout):
                    return
                else:
                    LOG.debug("Condition not met, retrying...")

            if retry_count > 0:
                retry_count -= 1
                LOG.debug("Retrying...")
                time.sleep(delay)
            else:
                raise exceptions.ArgusTimeoutError(
                    "Command {!r} failed too many times."
                    .format(cmd))

def get_local_ip():
    """Get the current machine's IP."""
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.connect(("google.com", 0))
    return sock.getsockname()[0]

def next_ip(ip, step=1):
    """Return the next IP address of the given one.

    :type step: int
    :param step: offset adjustment value
    """
    # Convert IP address to unsigned long.
    data_type = "!L"
    number = struct.unpack(data_type, socket.inet_aton(ip))[0]
    # Get the next one.
    number += step
    # Convert it back and return the ascii value.
    return socket.inet_ntoa(struct.pack(data_type, number))

def cidr2netmask(cidr):
    """Return the net mask deduced from the CIDR format network address."""
    mask_length = int(cidr.split("/")[1])
    mask_bits = "1" * mask_length + "0" * (32 - mask_length)
    mask_number = int(mask_bits, 2)
    mask_bytes = struct.pack("!L", mask_number)
    return socket.inet_ntoa(mask_bytes)

def decrypt_password(private_key, password):
    """Decode password and unencrypts it with private key.

    Requires openssl binary available in the path.
    """
    unencoded = base64.b64decode(password)
    cmd = ['openssl', 'rsautl', '-decrypt', '-inkey', private_key]
    proc = subprocess.Popen(cmd, stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
    out, err = proc.communicate(unencoded)
    proc.stdin.close()
    if proc.returncode:
        raise Exception("Failed calling openssl with error: {!r}."
                        .format(err))
    return out

# pylint: disable=dangerous-default-value
def run_once(func, state={}, errors={}):
    """A memoization decorator, whose purpose is to cache calls."""
    @six.wraps(func)
    def wrapper(*args, **kwargs):
        if func in errors:
            # Deliberate use of LBYL.
            six.reraise(*errors[func])

        try:
            return state[func]
        except KeyError:
            try:
                state[func] = result = func(*args, **kwargs)
                return result
            except Exception:
                errors[func] = sys.exc_info()
                raise
    return wrapper

def get_resource(resource):
    """Get the given resource from the list of known resources."""
    return pkgutil.get_data('argus.resources', resource)

class cached_property(object):  # pylint: disable=invalid-name
    """A property which caches the result on access."""

    def __init__(self, func, name=None):
        self.func = func
        self.name = name or func.__name__

    def __get__(self, instance, klass=None):
        instance.__dict__[self.name] = result = self.func(instance)
        return result

@run_once
def get_config():
    """Get the argus config object.

    Looks for a file called argus.conf in the working directory.
    If the file is not found it looks for it in /etc/argus/
    """
    if os.path.isfile('argus.conf'):
        config_file = 'argus.conf'
    else:
        config_file = '/etc/argus/argus.conf'
    return config.ConfigurationParser(config_file).conf

def get_logger(name="argus",
               format_string=DEFAULT_FORMAT,
               logging_file=DEFAULT_LOG_FILE):
    """Obtain a new logger object.

    The `name` parameter will be the name of the logger and `format_string`
    will be the format it will use for logging. `logging_file` is a file
    where the messages will be written.
    """
    logger = logging.getLogger(name)
    formatter = logging.Formatter(format_string)

    if not logger.handlers:
        # If the logger wasn't obtained another time,
        # then it shouldn't have any loggers

        if logging_file:
            file_handler = logging.FileHandler(logging_file, delay=True)
            file_handler.setFormatter(formatter)
            logger.addHandler(file_handler)

    logger.setLevel(logging.DEBUG)
    return logger

def rand_name(name=''):
    randbits = str(random.randint(1, 0x7fffffff))
    if name:
        return name + '-' + randbits
    else:
        return randbits

@contextlib.contextmanager
def restore_excepthook():
    """Context manager used to preserve the original except hook.

    *tempest* sets its own except hook, which will log the error
    using the tempest logger. Unfortunately, we are not using
    the tempest logger, so any uncaught error goes into nothingness.
    So just reset the excepthook to the original.
    """
    # pylint: disable=redefined-outer-name,reimported
    import sys
    original = sys.excepthook
    try:
        yield
    finally:
        sys.excepthook = original

def get_namedtuple(name, members, values):
    nt_class = collections.namedtuple(name, members)
    return nt_class(*values)

def get_public_keys():
    return get_resource("public_keys").splitlines()

def get_certificate():
    return get_resource("certificate")

LOG = get_logger()

_BUILDS = ["Beta", "Stable", "test"]
_ARCHES = ["x64", "x86"]
BUILDS = get_namedtuple("BUILDS", _BUILDS, _BUILDS)
ARCHES = get_namedtuple("ARCHES", _ARCHES, _ARCHES)
<commit_msg>Make the implementation of cached_property more robust, by not calculating the value if the instance wasn't created.<commit_after># Copyright 2014 Cloudbase Solutions Srl
# All Rights Reserved.
#
#    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 base64
import collections
import contextlib
import logging
import os
import pkgutil
import random
import socket
import struct
import subprocess
import sys
import time

import six

from argus import config
from argus import exceptions
from argus import remote_client

RETRY_COUNT = 15
RETRY_DELAY = 10

__all__ = (
    'WinRemoteClient',
    'decrypt_password',
    'get_config',
    'get_logger',
    'get_resource',
    'cached_property',
    'run_once',
    'rand_name',
    'get_public_keys',
    'get_certificate',
)

DEFAULT_FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
DEFAULT_LOG_FILE = 'argus.log'

NETWORK_KEYS = [
    "mac",
    "address",
    "address6",
    "gateway",
    "gateway6",
    "netmask",
    "netmask6",
    "dns",
    "dns6",
    "dhcp"
]

class WinRemoteClient(remote_client.WinRemoteClient):

    def run_command(self, cmd):
        """Run the given command and return execution details.

        :rtype: tuple
        :returns: stdout, stderr, exit_code
        """

        LOG.info("Running command %s...", cmd)
        return self.run_remote_cmd(cmd)

    def run_command_verbose(self, cmd):
        """Run the given command and log anything it returns.

        Do this with retrying support.

        :rtype: string
        :returns: stdout
        """
        stdout, stderr, exit_code = self.run_command_with_retry(cmd)
        LOG.info("The command returned the output: %s", stdout)
        LOG.info("The stderr of the command was: %s", stderr)
        LOG.info("The exit code of the command was: %s", exit_code)
        return stdout

    def run_command_with_retry(self, cmd, count=RETRY_COUNT,
                               delay=RETRY_DELAY):
        """Run the given `cmd` until succeeds.

        :param cmd:
            A string, representing a command which needs to
            be executed on the underlying remote client.
        :param count:
            The number of retries which this function has.
            If the value is ``None``, then the function will retry *forever*.
        :param delay:
            The number of seconds to sleep when retrying a command.

        :rtype: tuple
        :returns: stdout, stderr, exit_code
        """

        # Countdown normalization.
        if not count or count < 0:
            count = 0

        while True:
            try:
                return self.run_command(cmd)
            except Exception as exc:  # pylint: disable=broad-except
                LOG.debug("Command failed with %r.", exc)
                # A negative `count` means no count at all.
                if count >= 0:
                    count -= 1
                if count == 0:
                    raise exceptions.ArgusTimeoutError(
                        "Command {!r} failed too many times."
                        .format(cmd))
                LOG.debug("Retrying...")
                time.sleep(delay)

    def run_command_until_condition(self, cmd, cond, retry_count=RETRY_COUNT,
                                    delay=RETRY_DELAY):
        """Run the given `cmd` until a condition `cond` occurs.

        :param cond:
            A callable which receives the standard output returned by
            executing the command. It should return a boolean value,
            which tells to this function to stop execution.
        :raises:
            `ArgusCLIError` if there is output found in the standard error.

        This method uses and behaves like `run_command_with_retry` but
        with an additional condition parameter.
        """

        # countdown normalization
        if not retry_count or retry_count < 0:
            retry_count = 0

        while True:
            try:
                stdout, stderr, _ = self.run_command(cmd)
            except Exception as exc:  # pylint: disable=broad-except
                LOG.debug("Command failed with %r.", exc)
            else:
                if stderr:
                    raise exceptions.ArgusCLIError(
                        "Executing command {!r} failed with {!r}."
                        .format(cmd, stderr))
                elif cond(stdout):
                    return
                else:
                    LOG.debug("Condition not met, retrying...")

            if retry_count > 0:
                retry_count -= 1
                LOG.debug("Retrying...")
                time.sleep(delay)
            else:
                raise exceptions.ArgusTimeoutError(
                    "Command {!r} failed too many times."
                    .format(cmd))

def get_local_ip():
    """Get the current machine's IP."""
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.connect(("google.com", 0))
    return sock.getsockname()[0]

def next_ip(ip, step=1):
    """Return the next IP address of the given one.

    :type step: int
    :param step: offset adjustment value
    """
    # Convert IP address to unsigned long.
    data_type = "!L"
    number = struct.unpack(data_type, socket.inet_aton(ip))[0]
    # Get the next one.
    number += step
    # Convert it back and return the ascii value.
    return socket.inet_ntoa(struct.pack(data_type, number))

def cidr2netmask(cidr):
    """Return the net mask deduced from the CIDR format network address."""
    mask_length = int(cidr.split("/")[1])
    mask_bits = "1" * mask_length + "0" * (32 - mask_length)
    mask_number = int(mask_bits, 2)
    mask_bytes = struct.pack("!L", mask_number)
    return socket.inet_ntoa(mask_bytes)

def decrypt_password(private_key, password):
    """Decode password and unencrypts it with private key.

    Requires openssl binary available in the path.
    """
    unencoded = base64.b64decode(password)
    cmd = ['openssl', 'rsautl', '-decrypt', '-inkey', private_key]
    proc = subprocess.Popen(cmd, stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
    out, err = proc.communicate(unencoded)
    proc.stdin.close()
    if proc.returncode:
        raise Exception("Failed calling openssl with error: {!r}."
                        .format(err))
    return out

# pylint: disable=dangerous-default-value
def run_once(func, state={}, errors={}):
    """A memoization decorator, whose purpose is to cache calls."""
    @six.wraps(func)
    def wrapper(*args, **kwargs):
        if func in errors:
            # Deliberate use of LBYL.
            six.reraise(*errors[func])

        try:
            return state[func]
        except KeyError:
            try:
                state[func] = result = func(*args, **kwargs)
                return result
            except Exception:
                errors[func] = sys.exc_info()
                raise
    return wrapper

def get_resource(resource):
    """Get the given resource from the list of known resources."""
    return pkgutil.get_data('argus.resources', resource)

class cached_property(object):  # pylint: disable=invalid-name
    """A property which caches the result on access."""

    def __init__(self, func, name=None):
        self.func = func
        self.name = name or func.__name__

    def __get__(self, instance, klass=None):
        if instance is None:
            return self
        instance.__dict__[self.name] = result = self.func(instance)
        return result

@run_once
def get_config():
    """Get the argus config object.

    Looks for a file called argus.conf in the working directory.
    If the file is not found it looks for it in /etc/argus/
    """
    if os.path.isfile('argus.conf'):
        config_file = 'argus.conf'
    else:
        config_file = '/etc/argus/argus.conf'
    return config.ConfigurationParser(config_file).conf

def get_logger(name="argus",
               format_string=DEFAULT_FORMAT,
               logging_file=DEFAULT_LOG_FILE):
    """Obtain a new logger object.

    The `name` parameter will be the name of the logger and `format_string`
    will be the format it will use for logging. `logging_file` is a file
    where the messages will be written.
    """
    logger = logging.getLogger(name)
    formatter = logging.Formatter(format_string)

    if not logger.handlers:
        # If the logger wasn't obtained another time,
        # then it shouldn't have any loggers

        if logging_file:
            file_handler = logging.FileHandler(logging_file, delay=True)
            file_handler.setFormatter(formatter)
            logger.addHandler(file_handler)

    logger.setLevel(logging.DEBUG)
    return logger

def rand_name(name=''):
    randbits = str(random.randint(1, 0x7fffffff))
    if name:
        return name + '-' + randbits
    else:
        return randbits

@contextlib.contextmanager
def restore_excepthook():
    """Context manager used to preserve the original except hook.

    *tempest* sets its own except hook, which will log the error
    using the tempest logger. Unfortunately, we are not using
    the tempest logger, so any uncaught error goes into nothingness.
    So just reset the excepthook to the original.
    """
    # pylint: disable=redefined-outer-name,reimported
    import sys
    original = sys.excepthook
    try:
        yield
    finally:
        sys.excepthook = original

def get_namedtuple(name, members, values):
    nt_class = collections.namedtuple(name, members)
    return nt_class(*values)

def get_public_keys():
    return get_resource("public_keys").splitlines()

def get_certificate():
    return get_resource("certificate")

LOG = get_logger()

_BUILDS = ["Beta", "Stable", "test"]
_ARCHES = ["x64", "x86"]
BUILDS = get_namedtuple("BUILDS", _BUILDS, _BUILDS)
ARCHES = get_namedtuple("ARCHES", _ARCHES, _ARCHES)
<|endoftext|>


<commit_before># configure django to use default settings
# note that this can also be done using an environment variable
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured

try:
    settings.__file__
except ImproperlyConfigured:
    # load default settings if they're not set
    from channelworm import settings as defaults
    settings.configure(default_settings=defaults, DEBUG=True)

import ion_channel.models as C
import PyOpenWorm as P
from django.forms.models import model_to_dict

class PatchClampAdapter(object):
    """Map a channelworm model to a pyopenworm model"""

    def __init__(self, cw_obj):
        self.channelworm_object = cw_obj
        cw_dict = model_to_dict(self.channelworm_object)

        experiment_id = cw_dict.pop('experiment')
        patch_clamp_id = cw_dict.pop('id')

        self.pyopenworm_object = P.Experiment()

        for key, value in cw_dict:
            self.pyopenworm_object.conditions.set(key, value)

    def get_pow(self):
        return self.pyopenworm_object

    def get_cw(self):
        return self.channelworm_object
<commit_msg>Remove duplicated adapters.py file<commit_after><|endoftext|>