<commit_before>"""Flow Resource functions."""

# Copyright 2021 Google LLC. This software is provided as-is, without warranty
# or representation for any use or purpose. Your use of it is subject to your
# agreement with Google.

import logging
from typing import Dict
import requests
import google.cloud.dialogflowcx_v3beta1.services as services
import google.cloud.dialogflowcx_v3beta1.types as types
from google.protobuf import field_mask_pb2

from dfcx_sapi.core.sapi_base import SapiBase

# logging config
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)-8s %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)

class Flows(SapiBase):
    """Core Class for CX Flow Resource functions."""

    def __init__(
        self,
        creds_path: str = None,
        creds_dict: Dict = None,
        creds=None,
        scope=False,
        flow_id: str = None,
    ):
        super().__init__(
            creds_path=creds_path,
            creds_dict=creds_dict,
            creds=creds,
            scope=scope,
        )

        if flow_id:
            self.flow_id = flow_id

        self.agent_id = None

    def get_flows_map(self, agent_id, reverse=False):
        """Exports Agent Flow Names and UUIDs into a user friendly dict.

        Args:
            - agent_id, the formatted CX Agent ID to use
            - reverse, (Optional) Boolean flag to swap key:value -> value:key

        Returns:
            - flows_map, Dictionary containing flow UUIDs as keys and
                flow.display_name as values
        """

        if reverse:
            flows_dict = {
                flow.display_name: flow.name
                for flow in self.list_flows(agent_id=agent_id)
            }

        else:
            flows_dict = {
                flow.name: flow.display_name
                for flow in self.list_flows(agent_id=agent_id)
            }

        return flows_dict

    def train_flow(self):
        """trains the specified flow.

        Args:
          flow_id: CX flow ID string in the following format
            projects/<PROJECT ID>/locations/<LOCATION ID>/agents/<AGENT ID>/flows/<FLOW ID>

        Returns:
          response: A Long Running Operation (LRO) ID that can be used to
            check the status of the export using dfcx.get_lro()
        """

        request = types.flow.TrainFlowRequest()
        request.name = self.flow_id
        client = services.flows.FlowsClient(credentials=self.creds)
        response = client.train_flow(request)
        return response

    def list_flows(self, agent_id=None):
        agent_id = agent_id or self.agent_id  # default value
        request = types.flow.ListFlowsRequest()
        request.parent = agent_id

        client_options = self._set_region(agent_id)
        client = services.flows.FlowsClient(
            credentials=self.creds, client_options=client_options
        )
        response = client.list_flows(request)

        flows = []
        for page in response.pages:
            for flow in page.flows:
                flows.append(flow)

        return flows

    def get_flow(self, flow_id):
        client_options = self._set_region(flow_id)
        client = services.flows.FlowsClient(
            credentials=self.creds, client_options=client_options
        )
        response = client.get_flow(name=flow_id)

        return response

    def update_flow(self, flow_id, obj=None, **kwargs):
        if obj:
            flow = obj
            flow.name = flow_id
        else:
            flow = self.get_flow(flow_id)

        # set flow attributes to args
        for key, value in kwargs.items():
            setattr(flow, key, value)
        paths = kwargs.keys()
        mask = field_mask_pb2.FieldMask(paths=paths)

        client_options = self._set_region(flow_id)
        client = services.flows.FlowsClient(
            credentials=self.creds, client_options=client_options
        )
        response = client.update_flow(flow=flow, update_mask=mask)

        return response

    def update_nlu_settings(self, flow_id, **kwargs):
        """updates flow to new NLU setting.
        Args:
            flow_id: flow id to update nlu settings for.
            model_type: (Optional) [0:unspecified, 1:MODEL_TYPE_STANDARD, 2:Custom, 3:Advanced]
            classification_threshold: (Optional) threshold for the flow
            model_training_mode: (Optional) [0:unspecified, 1:automatic, 2:'manual]
        """

        flow = self.get_flow(flow_id)
        current_settings = flow.nlu_settings
        for key, value in kwargs.items():
            setattr(current_settings, key, value)
        self.update_flow(flow_id=flow_id, nlu_settings=current_settings)

    def export_flow(
        self,
        flow_id: str,
        gcs_path: str,
        data_format: str = "BLOB",
        ref_flows: bool = True,
    ) -> Dict[str, str]:
        """Exports DFCX Flow(s) into GCS bucket.

        Args:
          flow_id, the formatted CX Flow ID to export
          gcs_path, the full GCS Bucket and File name path
          data_format, (Optional) One of 'BLOB' or 'JSON'. Defaults to 'BLOB'.
          ref_flows, (Optional) Bool to include referenced flows connected to primary flow

        Returns:
          lro, Dict with value containing a Long Running Operation UUID that can be
              used to retrieve status of LRO from dfcx.get_lro
        """

        location = flow_id.split("/")[3]
        if location != "global":
            base_url = "https://{}-dialogflow.googleapis.com/v3beta1".format(
                location
            )
        else:
            base_url = "https://dialogflow.googleapis.com/v3beta1"
        url = "{0}/{1}:export".format(base_url, flow_id)

        body = {
            "flow_uri": "{}".format(gcs_path),
            "data_format": data_format,
            "include_referenced_flows": ref_flows,
        }

        headers = {
            "Authorization": "Bearer {}".format(self.token),
            "Content-Type": "application/json; charset=utf-8",
        }

        # Make REST call
        response = requests.post(url, json=body, headers=headers)
        response.raise_for_status()

        lro = response.json()

        return lro

    def import_flow(
        self,
        destination_agent_id: str,
        gcs_path: str,
        import_option: str = "FALLBACK",
    ) -> Dict[str, str]:
        """Imports a DFCX Flow from GCS bucket to CX Agent.

        Args:
          agent_id, the DFCX formatted Agent ID
          gcs_path, the full GCS Bucket and File name path
          import_option, one of 'FALLBACK' or 'KEEP'. Defaults to 'FALLBACK'

        Returns:
          lro, Dict with value containing a Long Running Operation UUID that can be
              used to retrieve status of LRO from dfcx.get_lro
        """

        location = destination_agent_id.split("/")[3]
        if location != "global":
            base_url = "https://{}-dialogflow.googleapis.com/v3beta1".format(
                location
            )
        else:
            base_url = "https://dialogflow.googleapis.com/v3beta1"
        url = "{0}/{1}/flows:import".format(base_url, destination_agent_id)

        body = {
            "flow_uri": "{}".format(gcs_path),
            "import_option": "{}".format(import_option),
        }

        headers = {
            "Authorization": "Bearer {}".format(self.token),
            "Content-Type": "application/json; charset=utf-8",
        }

        # Make REST call
        response = requests.post(url, json=body, headers=headers)
        response.raise_for_status()

        lro = response.json()

        return lro

    def delete_flow(self, flow_id: str, force: bool = False) -> None:
        """Deletes a single CX Flow Object resources.

        Args:
          flow_id: flow to delete
          force: False means a flow will not be deleted if a route to the flow exists,
            True means the flow will be deleted and all
        """
        request = types.DeleteFlowRequest()
        request.name = flow_id
        request.force = force

        client_options = self._set_region(flow_id)
        client = services.flows.FlowsClient(
            credentials=self.creds, client_options=client_options
        )

        client.delete_flow(request)
<commit_msg>linter updates<commit_after>"""Flow Resource functions."""

# Copyright 2021 Google LLC. This software is provided as-is, without warranty
# or representation for any use or purpose. Your use of it is subject to your
# agreement with Google.

import logging
from typing import Dict
import requests
import google.cloud.dialogflowcx_v3beta1.services as services
import google.cloud.dialogflowcx_v3beta1.types as types
from google.protobuf import field_mask_pb2

from dfcx_sapi.core.sapi_base import SapiBase

# logging config
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)-8s %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)

class Flows(SapiBase):
    """Core Class for CX Flow Resource functions."""

    def __init__(
        self,
        creds_path: str = None,
        creds_dict: Dict = None,
        creds=None,
        scope=False,
        flow_id: str = None,
    ):
        super().__init__(
            creds_path=creds_path,
            creds_dict=creds_dict,
            creds=creds,
            scope=scope,
        )

        if flow_id:
            self.flow_id = flow_id

        self.agent_id = None

    def get_flows_map(self, agent_id:str = None, reverse=False):
        """Exports Agent Flow Names and UUIDs into a user friendly dict.

        Args:
            - agent_id, the formatted CX Agent ID to use
            - reverse, (Optional) Boolean flag to swap key:value -> value:key

        Returns:
            - flows_dict, Dictionary containing flow UUIDs as keys and
                flow.display_name as values
        """
        if not agent_id:
            agent_id = self.agent_id

        if reverse:
            flows_dict = {
                flow.display_name: flow.name
                for flow in self.list_flows(agent_id=agent_id)
            }

        else:
            flows_dict = {
                flow.name: flow.display_name
                for flow in self.list_flows(agent_id=agent_id)
            }

        return flows_dict

    def train_flow(self, flow_id: str = None):
        """trains the specified flow.

        Args:
          flow_id: CX flow ID string in the following format
            projects/<PROJECT ID>/locations/<LOCATION ID>/agents/<AGENT ID>/flows/<FLOW ID>

        Returns:
          response: A Long Running Operation (LRO) ID that can be used to
            check the status of the export using dfcx.get_lro()
        """
        if not flow_id:
            flow_id = self.flow_id

        request = types.flow.TrainFlowRequest()
        request.name = self.flow_id
        client = services.flows.FlowsClient(credentials=self.creds)
        response = client.train_flow(request)
        return response

    def list_flows(self, agent_id=None):
        """Get a List of all Flows in the current Agent.

        Args:
          agent_id, CX Agent ID string in the proper format
            projects/<PROJECT ID>/locations/<LOCATION ID>/agents/<AGENT ID>

        Returns:
          flows, a List of Flow objects
        """
        if not agent_id:
            agent_id = self.agent_id

        agent_id = agent_id or self.agent_id  # default value
        request = types.flow.ListFlowsRequest()
        request.parent = agent_id

        client_options = self._set_region(agent_id)
        client = services.flows.FlowsClient(
            credentials=self.creds, client_options=client_options
        )
        response = client.list_flows(request)

        flows = []
        for page in response.pages:
            for flow in page.flows:
                flows.append(flow)

        return flows

    def get_flow(self, flow_id: str = None):
        """Get a single CX Flow object.

        Args:
          flow_id, CX Flow ID in the proper format

        Returns:
          response, a single CX Flow object"""
        if not flow_id:
            flow_id = self.flow_id

        client_options = self._set_region(flow_id)
        client = services.flows.FlowsClient(
            credentials=self.creds, client_options=client_options
        )
        response = client.get_flow(name=flow_id)

        return response

    def update_flow(self, flow_id: str = None, obj: types.Flow = None, **kwargs):
        """Update a single specific CX Flow object.

        Args:
          flow_id, CX Flow ID in the proper format
          obj, (Optional) a single CX Flow object of types.Flow

        Returns:
          response, a copy of the updated Flow object
      """

        if obj:
            flow = obj
            flow.name = flow_id
        else:
            flow = self.get_flow(flow_id)

        # set flow attributes to args
        for key, value in kwargs.items():
            setattr(flow, key, value)
        paths = kwargs.keys()
        mask = field_mask_pb2.FieldMask(paths=paths)

        client_options = self._set_region(flow_id)
        client = services.flows.FlowsClient(
            credentials=self.creds, client_options=client_options
        )
        response = client.update_flow(flow=flow, update_mask=mask)

        return response

    def update_nlu_settings(self, flow_id, **kwargs):
        """updates flow to new NLU setting.
        Args:
            flow_id: flow id to update nlu settings for.
            model_type: (Optional) [0:unspecified, 1:MODEL_TYPE_STANDARD, 2:Custom, 3:Advanced]
            classification_threshold: (Optional) threshold for the flow
            model_training_mode: (Optional) [0:unspecified, 1:automatic, 2:'manual]
        """

        flow = self.get_flow(flow_id)
        current_settings = flow.nlu_settings
        for key, value in kwargs.items():
            setattr(current_settings, key, value)
        self.update_flow(flow_id=flow_id, nlu_settings=current_settings)

    def export_flow(
        self,
        flow_id: str,
        gcs_path: str,
        data_format: str = "BLOB",
        ref_flows: bool = True,
    ) -> Dict[str, str]:
        """Exports DFCX Flow(s) into GCS bucket.

        Args:
          flow_id, the formatted CX Flow ID to export
          gcs_path, the full GCS Bucket and File name path
          data_format, (Optional) One of 'BLOB' or 'JSON'. Defaults to 'BLOB'.
          ref_flows, (Optional) Bool to include referenced flows connected to primary flow

        Returns:
          lro, Dict with value containing a Long Running Operation UUID that can be
              used to retrieve status of LRO from dfcx.get_lro
        """

        location = flow_id.split("/")[3]
        if location != "global":
            base_url = "https://{}-dialogflow.googleapis.com/v3beta1".format(
                location
            )
        else:
            base_url = "https://dialogflow.googleapis.com/v3beta1"
        url = "{0}/{1}:export".format(base_url, flow_id)

        body = {
            "flow_uri": "{}".format(gcs_path),
            "data_format": data_format,
            "include_referenced_flows": ref_flows,
        }

        headers = {
            "Authorization": "Bearer {}".format(self.token),
            "Content-Type": "application/json; charset=utf-8",
        }

        # Make REST call
        response = requests.post(url, json=body, headers=headers)
        response.raise_for_status()

        lro = response.json()

        return lro

    def import_flow(
        self,
        destination_agent_id: str,
        gcs_path: str,
        import_option: str = "FALLBACK",
    ) -> Dict[str, str]:
        """Imports a DFCX Flow from GCS bucket to CX Agent.

        Args:
          agent_id, the DFCX formatted Agent ID
          gcs_path, the full GCS Bucket and File name path
          import_option, one of 'FALLBACK' or 'KEEP'. Defaults to 'FALLBACK'

        Returns:
          lro, Dict with value containing a Long Running Operation UUID that can be
              used to retrieve status of LRO from dfcx.get_lro
        """

        location = destination_agent_id.split("/")[3]
        if location != "global":
            base_url = "https://{}-dialogflow.googleapis.com/v3beta1".format(
                location
            )
        else:
            base_url = "https://dialogflow.googleapis.com/v3beta1"
        url = "{0}/{1}/flows:import".format(base_url, destination_agent_id)

        body = {
            "flow_uri": "{}".format(gcs_path),
            "import_option": "{}".format(import_option),
        }

        headers = {
            "Authorization": "Bearer {}".format(self.token),
            "Content-Type": "application/json; charset=utf-8",
        }

        # Make REST call
        response = requests.post(url, json=body, headers=headers)
        response.raise_for_status()

        lro = response.json()

        return lro

    def delete_flow(self, flow_id: str, force: bool = False) -> None:
        """Deletes a single CX Flow Object resources.

        Args:
          flow_id: flow to delete
          force: False means a flow will not be deleted if a route to the flow exists,
            True means the flow will be deleted and all
        """
        request = types.DeleteFlowRequest()
        request.name = flow_id
        request.force = force

        client_options = self._set_region(flow_id)
        client = services.flows.FlowsClient(
            credentials=self.creds, client_options=client_options
        )

        client.delete_flow(request)
<|endoftext|>


<commit_before>from OpenSSL import crypto

from django import forms
from django.core.exceptions import ObjectDoesNotExist
from django.core.exceptions import ValidationError

from core import models
from core.utils import Ca

class RootCrt(forms.Form):
    crt = forms.FileField(label='root .crt file')
    key = forms.FileField(label='root .key file')

    def clean(self):
        cleaned_data = super().clean()
        cert_data = cleaned_data.get('crt').read()
        key_data = cleaned_data.get('key').read()
        cleaned_data.get('crt').seek(0)
        cleaned_data.get('key').seek(0)
        try:
            cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert_data).get_subject()
            ca = Ca()
            if not ca.check_crt_and_key(cert_data.decode(), key_data.decode()):
                raise ValidationError('You upload a different key and certificate')
            if not cert.C or not cert.ST or not cert.L or not cert.O:
                msg = 'Please enter required field in certificate: Country, State, Location, Organization'
                self.add_error('crt', msg)
        except crypto.Error:
            raise ValidationError('Please load valid certificate and key')

        return cleaned_data

class ConfigRootCrt(forms.Form):
    country = forms.CharField(max_length=2, label='Country')
    state = forms.CharField(label='State')
    location = forms.CharField(label='Location')
    organization = forms.CharField(label='Organization')
    organizational_unit_name = forms.CharField(required=False, label='Organizational_unit_name')
    common_name = forms.CharField(required=False, label='Common name')
    email = forms.EmailField(required=False, label='Email')
    validity_period = forms.DateField(label='Certificate expiration date')

class ViewCrtText(forms.Form):
    crt = forms.CharField(widget=forms.Textarea(attrs={'rows': '8'}))
    key = forms.CharField(widget=forms.Textarea(attrs={'rows': '8'}))

class CertificatesCreate(forms.Form):
    cn = forms.CharField(required=False, label='Common name')
    validity_period = forms.DateField(label='Certificate expiration date')

    def clean(self):
        cleaned_data = super().clean()
        data = cleaned_data.get('cn')
        try:
            models.SiteCrt.objects.get(cn=data)
            msg = "Common name {} not unique".format(data)
            self.add_error('cn', msg)
        except ObjectDoesNotExist:
            pass
        return cleaned_data

class CertificatesSearch(forms.Form):
    cn = forms.CharField(required=False, label='Common name')

class CertificatesUploadExisting(forms.Form):
    crt_file = forms.FileField(required=False, label='certificate .crt file')
    key_file = forms.FileField(required=False, label='certificate .key file')
    crt_text = forms.CharField(widget=forms.Textarea(attrs={'rows': '6'}), required=False, label='Certificate')
    key_text = forms.CharField(widget=forms.Textarea(attrs={'rows': '6'}), required=False, label='Key')

    def clean(self):
        cleaned_data = super().clean()
        crt_file = self.cleaned_data.get('crt_file')
        key_file = self.cleaned_data.get('key_file')
        crt_text = self.cleaned_data.get('crt_text')
        key_text = self.cleaned_data.get('key_text')
        if ((crt_file or key_file) and (crt_text or key_text)) or (not (crt_file or key_file or crt_text or key_text)):
            raise ValidationError('Please fill 2 field to choose from(File or Text)')

        if self.errors:
            return

        if crt_file:
            crt = crt_file.read()
            key = key_file.read()
            crt_file.seek(0)
            key_file.seek(0)
        else:
            crt = crt_text
            key = key_text
        crypto.load_certificate(crypto.FILETYPE_PEM, crt)
        ca = Ca()
        if not ca.check_crt_and_key(crt, key):
            raise ValidationError('You upload a different key and certificate')

        return cleaned_data

    def clean_crt_file(self):
        crt_file = self.cleaned_data.get('crt_file')
        if crt_file:
            crt_file_data = crt_file.read()
            crt_file.seek(0)
            try:
                cert = crypto.load_certificate(crypto.FILETYPE_PEM, crt_file_data)
                try:
                    obj_crt_in_db = models.SiteCrt.objects.get(cn=cert.get_subject().CN)
                    if obj_crt_in_db:
                        msg = 'Certificate with Common name {} already exists in db'.format(cert.get_subject().CN)
                        self.add_error('crt_file', msg)
                except ObjectDoesNotExist:
                    pass
            except crypto.Error:
                raise ValidationError('Please load valid certificate and key')
        return crt_file

    def clean_crt_text(self):
        crt_text = self.cleaned_data.get('crt_text')
        if crt_text:
            try:
                cert = crypto.load_certificate(crypto.FILETYPE_PEM, crt_text)
                try:
                    obj_crt_in_db = models.SiteCrt.objects.get(cn=cert.get_subject().CN)
                    if obj_crt_in_db:
                        msg = 'Certificate with Common name {} already exists in db'.format(cert.get_subject().CN)
                        self.add_error('crt_text', msg)
                except ObjectDoesNotExist:
                    pass
            except crypto.Error:
                raise ValidationError('Please load valid certificate and key')
        return crt_text

class RecreationCrt(forms.Form):
    validity_period = forms.DateField(label='Certificate expiration date')
<commit_msg>Проверка на наличие подчеркивания в common_name<commit_after>from OpenSSL import crypto

from django import forms
from django.core.exceptions import ObjectDoesNotExist
from django.core.exceptions import ValidationError

from core import models
from core.utils import Ca

class RootCrt(forms.Form):
    crt = forms.FileField(label='root .crt file')
    key = forms.FileField(label='root .key file')

    def clean(self):
        cleaned_data = super().clean()
        cert_data = cleaned_data.get('crt').read()
        key_data = cleaned_data.get('key').read()
        cleaned_data.get('crt').seek(0)
        cleaned_data.get('key').seek(0)
        try:
            cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert_data).get_subject()
            ca = Ca()
            if not ca.check_crt_and_key(cert_data.decode(), key_data.decode()):
                raise ValidationError('You upload a different key and certificate')
            if not cert.C or not cert.ST or not cert.L or not cert.O:
                msg = 'Please enter required field in certificate: Country, State, Location, Organization'
                self.add_error('crt', msg)
        except crypto.Error:
            raise ValidationError('Please load valid certificate and key')

        return cleaned_data

class ConfigRootCrt(forms.Form):
    country = forms.CharField(max_length=2, label='Country')
    state = forms.CharField(label='State')
    location = forms.CharField(label='Location')
    organization = forms.CharField(label='Organization')
    organizational_unit_name = forms.CharField(required=False, label='Organizational_unit_name')
    common_name = forms.CharField(required=False, label='Common name')
    email = forms.EmailField(required=False, label='Email')
    validity_period = forms.DateField(label='Certificate expiration date')

    def clean_common_name(self):
        common_name = self.cleaned_data.get('common_name')

        if '_' in common_name:
            raise forms.ValidationError('Illegal character "_"')

        return common_name

class ViewCrtText(forms.Form):
    crt = forms.CharField(widget=forms.Textarea(attrs={'rows': '8'}))
    key = forms.CharField(widget=forms.Textarea(attrs={'rows': '8'}))

class CertificatesCreate(forms.Form):
    cn = forms.CharField(required=False, label='Common name')
    validity_period = forms.DateField(label='Certificate expiration date')

    def clean(self):
        cleaned_data = super().clean()
        data = cleaned_data.get('cn')
        try:
            models.SiteCrt.objects.get(cn=data)
            msg = "Common name {} not unique".format(data)
            self.add_error('cn', msg)
        except ObjectDoesNotExist:
            pass
        return cleaned_data

class CertificatesSearch(forms.Form):
    cn = forms.CharField(required=False, label='Common name')

class CertificatesUploadExisting(forms.Form):
    crt_file = forms.FileField(required=False, label='certificate .crt file')
    key_file = forms.FileField(required=False, label='certificate .key file')
    crt_text = forms.CharField(widget=forms.Textarea(attrs={'rows': '6'}), required=False, label='Certificate')
    key_text = forms.CharField(widget=forms.Textarea(attrs={'rows': '6'}), required=False, label='Key')

    def clean(self):
        cleaned_data = super().clean()
        crt_file = self.cleaned_data.get('crt_file')
        key_file = self.cleaned_data.get('key_file')
        crt_text = self.cleaned_data.get('crt_text')
        key_text = self.cleaned_data.get('key_text')
        if ((crt_file or key_file) and (crt_text or key_text)) or (not (crt_file or key_file or crt_text or key_text)):
            raise ValidationError('Please fill 2 field to choose from(File or Text)')

        if self.errors:
            return

        if crt_file:
            crt = crt_file.read()
            key = key_file.read()
            crt_file.seek(0)
            key_file.seek(0)
        else:
            crt = crt_text
            key = key_text
        crypto.load_certificate(crypto.FILETYPE_PEM, crt)
        ca = Ca()
        if not ca.check_crt_and_key(crt, key):
            raise ValidationError('You upload a different key and certificate')

        return cleaned_data

    def clean_crt_file(self):
        crt_file = self.cleaned_data.get('crt_file')
        if crt_file:
            crt_file_data = crt_file.read()
            crt_file.seek(0)
            try:
                cert = crypto.load_certificate(crypto.FILETYPE_PEM, crt_file_data)
                try:
                    obj_crt_in_db = models.SiteCrt.objects.get(cn=cert.get_subject().CN)
                    if obj_crt_in_db:
                        msg = 'Certificate with Common name {} already exists in db'.format(cert.get_subject().CN)
                        self.add_error('crt_file', msg)
                except ObjectDoesNotExist:
                    pass
            except crypto.Error:
                raise ValidationError('Please load valid certificate and key')
        return crt_file

    def clean_crt_text(self):
        crt_text = self.cleaned_data.get('crt_text')
        if crt_text:
            try:
                cert = crypto.load_certificate(crypto.FILETYPE_PEM, crt_text)
                try:
                    obj_crt_in_db = models.SiteCrt.objects.get(cn=cert.get_subject().CN)
                    if obj_crt_in_db:
                        msg = 'Certificate with Common name {} already exists in db'.format(cert.get_subject().CN)
                        self.add_error('crt_text', msg)
                except ObjectDoesNotExist:
                    pass
            except crypto.Error:
                raise ValidationError('Please load valid certificate and key')
        return crt_text

class RecreationCrt(forms.Form):
    validity_period = forms.DateField(label='Certificate expiration date')
<|endoftext|>


<commit_before>
"""
The filter tab for the main toolbar

@author: Chris Scott

"""
import os
import sys
import tempfile
import subprocess

from PyQt4 import QtGui, QtCore
import numpy as np
import vtk

from visclibs import filtering_c
from visclibs import defects_c
from visclibs import clusters_c
import rendering

################################################################################
class Filterer:
    """
    Filter class.

    Contains list of subfilters to be performed in order.

    """
    def __init__(self, parent):

        self.parent = parent
        self.mainWindow = self.parent.mainWindow

        self.log = self.mainWindow.console.write

        self.actorsCollection = vtk.vtkActorCollection()

    def removeActors(self):
        """
        Remove all actors

        """
        self.actorsCollection.InitTraversal()
        actor = self.actorsCollection.GetNextItem()
        while actor is not None:
            try:
                self.mainWindow.VTKRen.RemoveActor(actor)
            except:
                pass

            actor = self.actorsCollection.GetNextItem()

        self.mainWindow.VTKWidget.ReInitialize()

    def addActors(self):
        """
        Add all actors

        """
        self.actorsCollection.InitTraversal()
        actor = self.actorsCollection.GetNextItem()
        while actor is not None:
            try:
                self.mainWindow.VTKRen.AddActor(actor)
            except:
                pass

            actor = self.actorsCollection.GetNextItem()

        self.mainWindow.VTKWidget.ReInitialize()

    def runFilters(self):
        """
        Run the filters.

        """
        self.removeActors()

        self.actorsCollection = vtk.vtkActorCollection()

        # first set up visible atoms arrays
        NAtoms = self.parent.mainWindow.inputState.NAtoms

        if not self.parent.defectFilterSelected:
            visibleAtoms = np.arange(NAtoms, dtype=np.int32)
            self.log("%d visible atoms" % (len(visibleAtoms),), 0, 2)

        # run filters
        currentFilters = self.parent.currentFilters
        currentSettings = self.parent.currentSettings
        for i in xrange(len(currentFilters)):
            filterName = currentFilters[i]
            filterSettings = currentSettings[i]

            self.log("Running filter: %s" % (filterName,), 0, 2)

            if filterName == "Specie":
                self.filterSpecie(visibleAtoms, filterSettings)

            elif filterName == "Crop":
                self.cropFilter(visibleAtoms, filterSettings)

            elif filterName == "Point defects":
                interstitials, vacancies, antisites, onAntisites = self.pointDefectFilter(filterSettings)

            elif filterName == "Clusters":
                clusterList = self.clusterFilter(visibleAtoms, filterSettings)

                if filterSettings.drawConvexHulls:
                    self.clusterFilterDrawHulls(clusterList, filterSettings)

            if self.parent.defectFilterSelected:
                NVis = len(interstitials) + len(vacancies) + len(antisites)
                self.log("%d visible atoms" % (NVis,), 0, 3)

            else:
                self.log("%d visible atoms" % (len(visibleAtoms),), 0, 3)

        # render
        if self.parent.defectFilterSelected:
            rendering.getActorsForFilteredDefects(interstitials, vacancies, antisites, onAntisites, self.mainWindow, self.actorsCollection)

        else:
            rendering.getActorsForFilteredSystem(visibleAtoms, self.mainWindow, self.actorsCollection)

        if self.parent.visible:
            self.addActors()

    def getActorsForFilteredSystem(self, visibleAtoms):
        """
        Render systems after applying filters.

        """
        pass

    def filterSpecie(self, visibleAtoms, settings):
        """
        Filter by specie

        """
        if settings.allSpeciesSelected:
            visSpecArray = np.arange(len(self.mainWindow.inputState.specieList), dtype=np.int32)

        else:
            visSpecArray = np.empty(len(settings.visibleSpecieList), np.int32)
            count = 0
            for i in xrange(len(self.mainWindow.inputState.specieList)):
                if self.mainWindow.inputState.specieList[i] in settings.visibleSpecieList:
                    visSpecArray[count] = i
                    count += 1

        NVisible = filtering_c.specieFilter(visibleAtoms, visSpecArray, self.mainWindow.inputState.specie)

        visibleAtoms.resize(NVisible, refcheck=False)

    def cropFilter(self, visibleAtoms, settings):
        """
        Crop lattice

        """
        lattice = self.mainWindow.inputState

        NVisible = filtering_c.cropFilter(visibleAtoms, lattice.pos, settings.xmin, settings.xmax, settings.ymin,
                                          settings.ymax, settings.zmin, settings.zmax, settings.xEnabled,
                                          settings.yEnabled, settings.zEnabled)

        visibleAtoms.resize(NVisible, refcheck=False)

    def pointDefectFilter(self, settings):
        """
        Point defects filter

        """
        inputLattice = self.mainWindow.inputState
        refLattice = self.mainWindow.refState

        # set up arrays
        if settings.showInterstitials:
            interstitials = np.empty(inputLattice.NAtoms, np.int32)
        else:
            interstitials = np.empty(0, np.int32)
        if settings.showVacancies:
            vacancies = np.empty(refLattice.NAtoms, np.int32)
        else:
            vacancies = np.empty(0, np.int32)
        if settings.showAntisites:
            antisites = np.empty(refLattice.NAtoms, np.int32)
            onAntisites = np.empty(refLattice.NAtoms, np.int32)
        else:
            antisites = np.empty(0, np.int32)
            onAntisites = np.empty(0, np.int32)

        # set up excluded specie arrays
        if settings.allSpeciesSelected:
            exclSpecsInput = np.zeros(0, np.int32)
            exclSpecsRef = np.zeros(0, np.int32)

        else:
            exclSpecs = []
            for i in xrange(len(inputLattice.specieList)):
                spec = inputLattice.specieList[i]
                if spec not in settings.visibleSpecieList:
                    exclSpecs.append(i)
            exclSpecsInput = np.empty(len(exclSpecs), np.int32)
            for i in xrange(len(exclSpecs)):
                exclSpecsInput[i] = exclSpecs[i]

            exclSpecs = []
            for i in xrange(len(refLattice.specieList)):
                spec = refLattice.specieList[i]
                if spec not in settings.visibleSpecieList:
                    exclSpecs.append(i)
            exclSpecsRef = np.empty(len(exclSpecs), np.int32)
            for i in xrange(len(exclSpecs)):
                exclSpecsRef[i] = exclSpecs[i]

#        print "EXCLUDE SPECS INPUT"
#        print inputLattice.specieList
#        print exclSpecsInput
#        print "EXCLUDE SPECS REF"
#        print refLattice.specieList
#        print exclSpecsRef

        NDefectsByType = np.zeros(4, np.int32)

        # call C library
        status = defects_c.findDefects(settings.showVacancies, settings.showInterstitials, settings.showAntisites, NDefectsByType, vacancies,
                                       interstitials, antisites, onAntisites, exclSpecsInput, exclSpecsRef, inputLattice.NAtoms, inputLattice.specieList,
                                       inputLattice.specie, inputLattice.pos, refLattice.NAtoms, refLattice.specieList, refLattice.specie,
                                       refLattice.pos, refLattice.cellDims[0], refLattice.cellDims[1], refLattice.cellDims[2], int(self.mainWindow.PBC[0]),
                                       int(self.mainWindow.PBC[1]), int(self.mainWindow.PBC[2]), settings.vacancyRadius, refLattice.minPos[0],
                                       refLattice.minPos[1], refLattice.minPos[2], refLattice.maxPos[0], refLattice.maxPos[1], refLattice.maxPos[2])

        # summarise
        NDef = NDefectsByType[0]
        NVac = NDefectsByType[1]
        NInt = NDefectsByType[2]
        NAnt = NDefectsByType[3]
        vacancies.resize(NVac)
        interstitials.resize(NInt)
        antisites.resize(NAnt)
        onAntisites.resize(NAnt)

        self.log("Found %d defects" % (NDef,), 0, 3)
        self.log("%d vacancies" % (NVac,), 0, 4)
        self.log("%d interstitials" % (NInt,), 0, 4)
        self.log("%d antisites" % (NAnt,), 0, 4)

        return (interstitials, vacancies, antisites, onAntisites)

    def clusterFilter(self, visibleAtoms, settings, PBC=None, minSize=None):
        """
        Run the cluster filter

        """
        lattice = self.mainWindow.inputState

        atomCluster = np.empty(len(visibleAtoms), np.int32)
        result = np.empty(2, np.int32)

        if PBC is not None and len(PBC) == 3:
            pass

        else:
            PBC = self.mainWindow.PBC

        if minSize is None:
            minSize = settings.minClusterSize

        clusters_c.findClusters(visibleAtoms, lattice.pos, atomCluster, settings.neighbourRadius, lattice.cellDims, PBC,
                                lattice.minPos, lattice.maxPos, minSize, result)

        NVisible = result[0]
        NClusters = result[1]

        visibleAtoms.resize(NVisible, refcheck=False)
        atomCluster.resize(NVisible, refcheck=False)

        # build cluster lists
        clusterList = []
        for i in xrange(NClusters):
            clusterList.append([])

        # add atoms to cluster lists
        clusterIndexMapper = {}
        count = 0
        for i in xrange(NVisible):
            atomIndex = visibleAtoms[i]
            clusterIndex = atomCluster[i]

            if clusterIndex not in clusterIndexMapper:
                clusterIndexMapper[clusterIndex] = count
                count += 1

            clusterListIndex = clusterIndexMapper[clusterIndex]

            clusterList[clusterListIndex].append(atomIndex)

        #TODO: rebuild scalars array of atom cluster (so can colour by cluster maybe?)

        return clusterList

    def clusterFilterDrawHulls(self, clusterList, settings):
        """
        Draw hulls around filters.

        If the clusterList was created using PBCs we need to recalculate each
        cluster without PBCs.

        """
        PBC = self.mainWindow.PBC
        if PBC[0] or PBC[1] or PBC[2]:
            self.clusterFilterDrawHullsWithPBCs(clusterList, settings)

        else:
            self.clusterFilterDrawHullsNoPBCs(clusterList, settings)

    def clusterFilterDrawHullsNoPBCs(self, clusterList, settings):
        """

        """
        lattice = self.mainWindow.inputState

        # draw them as they are
        for cluster in clusterList:
            # first make pos array for this cluster
            clusterPos = np.empty(3 * len(cluster), np.float64)
            for i in xrange(len(cluster)):
                index = cluster[i]

                clusterPos[3*i] = lattice.pos[3*index]
                clusterPos[3*i+1] = lattice.pos[3*index+1]
                clusterPos[3*i+2] = lattice.pos[3*index+2]

            # now get convex hull
            if len(cluster) == 3:
                facets = []
                facets.append([0, 1, 2])

            elif len(cluster) == 2:
                # draw bond
                continue

            elif len(cluster) < 2:
                continue

            else:
                facets = findConvexHull(cluster, clusterPos, qconvex=settings.qconvex)

            # now render
            if facets is not None:
                rendering.getActorsForHullFacets(facets, clusterPos, self.mainWindow, self.actorsCollection)

    def clusterFilterDrawHullsWithPBCs(self, clusterList, settings):
        """

        """
        # recalc each volume with PBCs off
        for cluster in clusterList:
            clusterAtoms = np.empty(len(cluster), np.int32)
            for i in xrange(len(cluster)):
                clusterAtoms[i] = cluster[i]

            subClusterList = self.clusterFilter(clusterAtoms, settings, PBC=np.zeros(3, np.int32), minSize=1)

            self.clusterFilterDrawHullsNoPBCs(subClusterList, settings)

def findConvexHull(cluster, pos, qconvex="qconvex"):
    """
    Find convex hull of given points

    """
    # write to file
    fh, fn = tempfile.mkstemp(dir="/tmp")
    f = open(fn, "w")
    f.write("3\n")
    f.write("%d\n" % (len(cluster),))
    for i in xrange(len(cluster)):
        string = "%f %f %f\n" % (pos[3*i], pos[3*i+1], pos[3*i+2])
        f.write(string)
    f.close()

    command = "%s Qt i < %s" % (qconvex, fn,)
    proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    output, stderr = proc.communicate()
    status = proc.poll()
    if status:
        print "qconvex failed"
        print stderr
        os.unlink(fn)
        sys.exit(35)

    output = output.strip()
    lines = output.split("\n")

    lines.pop(0)

    facets = []
    for line in lines:
        array = line.split()
        facets.append([np.int32(array[0]), np.int32(array[1]), np.int32(array[2])])

    # unlink temp file
    os.unlink(fn)

    return facets
<commit_msg>On second pass when drawing hull using PBCs the neighbour radius is multiplied by 1.5.<commit_after>
"""
The filter tab for the main toolbar

@author: Chris Scott

"""
import os
import sys
import tempfile
import subprocess

from PyQt4 import QtGui, QtCore
import numpy as np
import vtk

from visclibs import filtering_c
from visclibs import defects_c
from visclibs import clusters_c
import rendering

################################################################################
class Filterer:
    """
    Filter class.

    Contains list of subfilters to be performed in order.

    """
    def __init__(self, parent):

        self.parent = parent
        self.mainWindow = self.parent.mainWindow

        self.log = self.mainWindow.console.write

        self.actorsCollection = vtk.vtkActorCollection()

    def removeActors(self):
        """
        Remove all actors

        """
        self.actorsCollection.InitTraversal()
        actor = self.actorsCollection.GetNextItem()
        while actor is not None:
            try:
                self.mainWindow.VTKRen.RemoveActor(actor)
            except:
                pass

            actor = self.actorsCollection.GetNextItem()

        self.mainWindow.VTKWidget.ReInitialize()

    def addActors(self):
        """
        Add all actors

        """
        self.actorsCollection.InitTraversal()
        actor = self.actorsCollection.GetNextItem()
        while actor is not None:
            try:
                self.mainWindow.VTKRen.AddActor(actor)
            except:
                pass

            actor = self.actorsCollection.GetNextItem()

        self.mainWindow.VTKWidget.ReInitialize()

    def runFilters(self):
        """
        Run the filters.

        """
        self.removeActors()

        self.actorsCollection = vtk.vtkActorCollection()

        # first set up visible atoms arrays
        NAtoms = self.parent.mainWindow.inputState.NAtoms

        if not self.parent.defectFilterSelected:
            visibleAtoms = np.arange(NAtoms, dtype=np.int32)
            self.log("%d visible atoms" % (len(visibleAtoms),), 0, 2)

        # run filters
        currentFilters = self.parent.currentFilters
        currentSettings = self.parent.currentSettings
        for i in xrange(len(currentFilters)):
            filterName = currentFilters[i]
            filterSettings = currentSettings[i]

            self.log("Running filter: %s" % (filterName,), 0, 2)

            if filterName == "Specie":
                self.filterSpecie(visibleAtoms, filterSettings)

            elif filterName == "Crop":
                self.cropFilter(visibleAtoms, filterSettings)

            elif filterName == "Point defects":
                interstitials, vacancies, antisites, onAntisites = self.pointDefectFilter(filterSettings)

            elif filterName == "Clusters":
                clusterList = self.clusterFilter(visibleAtoms, filterSettings)

                if filterSettings.drawConvexHulls:
                    self.clusterFilterDrawHulls(clusterList, filterSettings)

            if self.parent.defectFilterSelected:
                NVis = len(interstitials) + len(vacancies) + len(antisites)
                self.log("%d visible atoms" % (NVis,), 0, 3)

            else:
                self.log("%d visible atoms" % (len(visibleAtoms),), 0, 3)

        # render
        if self.parent.defectFilterSelected:
            rendering.getActorsForFilteredDefects(interstitials, vacancies, antisites, onAntisites, self.mainWindow, self.actorsCollection)

        else:
            rendering.getActorsForFilteredSystem(visibleAtoms, self.mainWindow, self.actorsCollection)

        if self.parent.visible:
            self.addActors()

    def getActorsForFilteredSystem(self, visibleAtoms):
        """
        Render systems after applying filters.

        """
        pass

    def filterSpecie(self, visibleAtoms, settings):
        """
        Filter by specie

        """
        if settings.allSpeciesSelected:
            visSpecArray = np.arange(len(self.mainWindow.inputState.specieList), dtype=np.int32)

        else:
            visSpecArray = np.empty(len(settings.visibleSpecieList), np.int32)
            count = 0
            for i in xrange(len(self.mainWindow.inputState.specieList)):
                if self.mainWindow.inputState.specieList[i] in settings.visibleSpecieList:
                    visSpecArray[count] = i
                    count += 1

        NVisible = filtering_c.specieFilter(visibleAtoms, visSpecArray, self.mainWindow.inputState.specie)

        visibleAtoms.resize(NVisible, refcheck=False)

    def cropFilter(self, visibleAtoms, settings):
        """
        Crop lattice

        """
        lattice = self.mainWindow.inputState

        NVisible = filtering_c.cropFilter(visibleAtoms, lattice.pos, settings.xmin, settings.xmax, settings.ymin,
                                          settings.ymax, settings.zmin, settings.zmax, settings.xEnabled,
                                          settings.yEnabled, settings.zEnabled)

        visibleAtoms.resize(NVisible, refcheck=False)

    def pointDefectFilter(self, settings):
        """
        Point defects filter

        """
        inputLattice = self.mainWindow.inputState
        refLattice = self.mainWindow.refState

        # set up arrays
        if settings.showInterstitials:
            interstitials = np.empty(inputLattice.NAtoms, np.int32)
        else:
            interstitials = np.empty(0, np.int32)
        if settings.showVacancies:
            vacancies = np.empty(refLattice.NAtoms, np.int32)
        else:
            vacancies = np.empty(0, np.int32)
        if settings.showAntisites:
            antisites = np.empty(refLattice.NAtoms, np.int32)
            onAntisites = np.empty(refLattice.NAtoms, np.int32)
        else:
            antisites = np.empty(0, np.int32)
            onAntisites = np.empty(0, np.int32)

        # set up excluded specie arrays
        if settings.allSpeciesSelected:
            exclSpecsInput = np.zeros(0, np.int32)
            exclSpecsRef = np.zeros(0, np.int32)

        else:
            exclSpecs = []
            for i in xrange(len(inputLattice.specieList)):
                spec = inputLattice.specieList[i]
                if spec not in settings.visibleSpecieList:
                    exclSpecs.append(i)
            exclSpecsInput = np.empty(len(exclSpecs), np.int32)
            for i in xrange(len(exclSpecs)):
                exclSpecsInput[i] = exclSpecs[i]

            exclSpecs = []
            for i in xrange(len(refLattice.specieList)):
                spec = refLattice.specieList[i]
                if spec not in settings.visibleSpecieList:
                    exclSpecs.append(i)
            exclSpecsRef = np.empty(len(exclSpecs), np.int32)
            for i in xrange(len(exclSpecs)):
                exclSpecsRef[i] = exclSpecs[i]

#        print "EXCLUDE SPECS INPUT"
#        print inputLattice.specieList
#        print exclSpecsInput
#        print "EXCLUDE SPECS REF"
#        print refLattice.specieList
#        print exclSpecsRef

        NDefectsByType = np.zeros(4, np.int32)

        # call C library
        status = defects_c.findDefects(settings.showVacancies, settings.showInterstitials, settings.showAntisites, NDefectsByType, vacancies,
                                       interstitials, antisites, onAntisites, exclSpecsInput, exclSpecsRef, inputLattice.NAtoms, inputLattice.specieList,
                                       inputLattice.specie, inputLattice.pos, refLattice.NAtoms, refLattice.specieList, refLattice.specie,
                                       refLattice.pos, refLattice.cellDims[0], refLattice.cellDims[1], refLattice.cellDims[2], int(self.mainWindow.PBC[0]),
                                       int(self.mainWindow.PBC[1]), int(self.mainWindow.PBC[2]), settings.vacancyRadius, refLattice.minPos[0],
                                       refLattice.minPos[1], refLattice.minPos[2], refLattice.maxPos[0], refLattice.maxPos[1], refLattice.maxPos[2])

        # summarise
        NDef = NDefectsByType[0]
        NVac = NDefectsByType[1]
        NInt = NDefectsByType[2]
        NAnt = NDefectsByType[3]
        vacancies.resize(NVac)
        interstitials.resize(NInt)
        antisites.resize(NAnt)
        onAntisites.resize(NAnt)

        self.log("Found %d defects" % (NDef,), 0, 3)
        self.log("%d vacancies" % (NVac,), 0, 4)
        self.log("%d interstitials" % (NInt,), 0, 4)
        self.log("%d antisites" % (NAnt,), 0, 4)

        return (interstitials, vacancies, antisites, onAntisites)

    def clusterFilter(self, visibleAtoms, settings, PBC=None, minSize=None, nebRad=None):
        """
        Run the cluster filter

        """
        lattice = self.mainWindow.inputState

        atomCluster = np.empty(len(visibleAtoms), np.int32)
        result = np.empty(2, np.int32)

        if PBC is not None and len(PBC) == 3:
            pass
        else:
            PBC = self.mainWindow.PBC

        if minSize is None:
            minSize = settings.minClusterSize

        if nebRad is None:
            nebRad = settings.neighbourRadius

        clusters_c.findClusters(visibleAtoms, lattice.pos, atomCluster, nebRad, lattice.cellDims, PBC,
                                lattice.minPos, lattice.maxPos, minSize, result)

        NVisible = result[0]
        NClusters = result[1]

        visibleAtoms.resize(NVisible, refcheck=False)
        atomCluster.resize(NVisible, refcheck=False)

        # build cluster lists
        clusterList = []
        for i in xrange(NClusters):
            clusterList.append([])

        # add atoms to cluster lists
        clusterIndexMapper = {}
        count = 0
        for i in xrange(NVisible):
            atomIndex = visibleAtoms[i]
            clusterIndex = atomCluster[i]

            if clusterIndex not in clusterIndexMapper:
                clusterIndexMapper[clusterIndex] = count
                count += 1

            clusterListIndex = clusterIndexMapper[clusterIndex]

            clusterList[clusterListIndex].append(atomIndex)

        #TODO: rebuild scalars array of atom cluster (so can colour by cluster maybe?)

        return clusterList

    def clusterFilterDrawHulls(self, clusterList, settings):
        """
        Draw hulls around filters.

        If the clusterList was created using PBCs we need to recalculate each
        cluster without PBCs.

        """
        PBC = self.mainWindow.PBC
        if PBC[0] or PBC[1] or PBC[2]:
            self.clusterFilterDrawHullsWithPBCs(clusterList, settings)

        else:
            self.clusterFilterDrawHullsNoPBCs(clusterList, settings)

    def clusterFilterDrawHullsNoPBCs(self, clusterList, settings):
        """

        """
        lattice = self.mainWindow.inputState

        # draw them as they are
        for cluster in clusterList:
            # first make pos array for this cluster
            clusterPos = np.empty(3 * len(cluster), np.float64)
            for i in xrange(len(cluster)):
                index = cluster[i]

                clusterPos[3*i] = lattice.pos[3*index]
                clusterPos[3*i+1] = lattice.pos[3*index+1]
                clusterPos[3*i+2] = lattice.pos[3*index+2]

            # now get convex hull
            if len(cluster) == 3:
                facets = []
                facets.append([0, 1, 2])

            elif len(cluster) == 2:
                # draw bond
                continue

            elif len(cluster) < 2:
                continue

            else:
                facets = findConvexHull(cluster, clusterPos, qconvex=settings.qconvex)

            # now render
            if facets is not None:
                rendering.getActorsForHullFacets(facets, clusterPos, self.mainWindow, self.actorsCollection)

    def clusterFilterDrawHullsWithPBCs(self, clusterList, settings):
        """

        """
        # recalc each volume with PBCs off
        for cluster in clusterList:
            clusterAtoms = np.empty(len(cluster), np.int32)
            for i in xrange(len(cluster)):
                clusterAtoms[i] = cluster[i]

            subClusterList = self.clusterFilter(clusterAtoms, settings, PBC=np.zeros(3, np.int32), minSize=1, nebRad=1.5*settings.neighbourRadius)

            self.clusterFilterDrawHullsNoPBCs(subClusterList, settings)

def findConvexHull(cluster, pos, qconvex="qconvex"):
    """
    Find convex hull of given points

    """
    # write to file
    fh, fn = tempfile.mkstemp(dir="/tmp")
    f = open(fn, "w")
    f.write("3\n")
    f.write("%d\n" % (len(cluster),))
    for i in xrange(len(cluster)):
        string = "%f %f %f\n" % (pos[3*i], pos[3*i+1], pos[3*i+2])
        f.write(string)
    f.close()

    command = "%s Qt i < %s" % (qconvex, fn,)
    proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    output, stderr = proc.communicate()
    status = proc.poll()
    if status:
        print "qconvex failed"
        print stderr
        os.unlink(fn)
        sys.exit(35)

    output = output.strip()
    lines = output.split("\n")

    lines.pop(0)

    facets = []
    for line in lines:
        array = line.split()
        facets.append([np.int32(array[0]), np.int32(array[1]), np.int32(array[2])])

    # unlink temp file
    os.unlink(fn)

    return facets
<|endoftext|>


<commit_before>
from random import choice, randint

from django.contrib.auth.models import User
from django import forms
from gevent import sleep, spawn

from core.forms import GameForm
from core.settings import BETTING_PERIOD

game_registry = {}

class GameBase(type):
    """
    Whenever Game is subclassed, add a new game instance to the registry.
    """
    def __new__(cls, name, bases, attrs):
        attrs.setdefault("Form", GameForm)
        new = super(GameBase, cls).__new__(cls, name, bases, attrs)
        name = name.lower()
        if name != "game":
            if name != "dummy":
                del game_registry["dummy"]
            game_registry[name] = new(name)
        return new

class Game(object):
    """
    Base class for games. Subclasses should override the bet()
    method to perform validation of game specific betting args,
    and the outcome() method, which receives each player's betting
    args and returns True if the args perform a win.
    """

    __metaclass__ = GameBase

    def __init__(self, name):
        self.form = self.__class__.Form()
        self.name = name
        self.reset()

    def bet(self, namespace, amount, bet_args):
        """
        Called each time a player bets. When there are no players,
        a greenlet is spawned that will trigger the play of a
        turn of the game.

        Player's socketio namespace is passed through so that we
        have a way to broadcast back results once the turn is complete.

        The bet_args argument will be specific for each type of game.

        Subsequent calls to bet() for the same player prior to the turn
        being played, will update their betting arguments, and increase
        their bet.
        """
        if not self.players:
            spawn(self.turn)
        user_id = namespace.user["id"]
        self.players.setdefault(user_id, {"amount": 0})
        self.players[user_id]["namespace"] = namespace
        self.players[user_id]["amount"] += amount
        self.players[user_id]["bet_args"] = bet_args
        return True

    def broadcast(self, *args):
        """
        Piggyback the first connected player's namespace to
        broadcast a message.
        """
        for player in self.players.values():
            if player["namespace"].socket.connected
                player["namespace"].broadcast_event(*args)
                break

    def turn(self):
        """
        Takes an actual turn of the game - called within a separate
        greenlet on the first call to bet(). We iterate through each of
        the players passing their bet_args to outcome() which multiplies
        the amount bet, and build a results dict we can broadcast back
        to all sockets.
        """
        sleep(BETTING_PERIOD)
        results = {}
        for user_id, player in self.players.items():
            result = self.outcome(*player["bet_args"])
            results[user_id] = player["amount"] * result
            if results[user_id] > 0:
                # Put a positive bet amount back into the user's account.
                user = User.objects.get(id=user_id)
                user.account.balance += (results[user_id] * 2)
                user.account.save()
        self.broadcast("game_end", self.name, results)
        self.reset()

    def reset(self):
        self.players = {}

class Dummy(Game):
    """
    Default game with no input - just randomly win lose or draw.
    If any other games are registered, this one is removed.
    """
    def outcome(self):
        # Give back 0 (lose), 1 (even) or 2 (win) times the bet.
        return randint(0, 2)

ROULETTE_CHOICES = range(0, 37)

class Roulette(Game):

    class Form(GameForm):
        number = forms.ChoiceField(choices=[(c, c) for c in ROULETTE_CHOICES])

    def turn(self):
        self.landed_on = str(choice(ROULETTE_CHOICES))
        super(Roulette, self).turn()

    def outcome(self, choice):
        return (choice == self.landed_on) * len(ROULETTE_CHOICES)
<commit_msg>Missing colon<commit_after>
from random import choice, randint

from django.contrib.auth.models import User
from django import forms
from gevent import sleep, spawn

from core.forms import GameForm
from core.settings import BETTING_PERIOD

game_registry = {}

class GameBase(type):
    """
    Whenever Game is subclassed, add a new game instance to the registry.
    """
    def __new__(cls, name, bases, attrs):
        attrs.setdefault("Form", GameForm)
        new = super(GameBase, cls).__new__(cls, name, bases, attrs)
        name = name.lower()
        if name != "game":
            if name != "dummy":
                del game_registry["dummy"]
            game_registry[name] = new(name)
        return new

class Game(object):
    """
    Base class for games. Subclasses should override the bet()
    method to perform validation of game specific betting args,
    and the outcome() method, which receives each player's betting
    args and returns True if the args perform a win.
    """

    __metaclass__ = GameBase

    def __init__(self, name):
        self.form = self.__class__.Form()
        self.name = name
        self.reset()

    def bet(self, namespace, amount, bet_args):
        """
        Called each time a player bets. When there are no players,
        a greenlet is spawned that will trigger the play of a
        turn of the game.

        Player's socketio namespace is passed through so that we
        have a way to broadcast back results once the turn is complete.

        The bet_args argument will be specific for each type of game.

        Subsequent calls to bet() for the same player prior to the turn
        being played, will update their betting arguments, and increase
        their bet.
        """
        if not self.players:
            spawn(self.turn)
        user_id = namespace.user["id"]
        self.players.setdefault(user_id, {"amount": 0})
        self.players[user_id]["namespace"] = namespace
        self.players[user_id]["amount"] += amount
        self.players[user_id]["bet_args"] = bet_args
        return True

    def broadcast(self, *args):
        """
        Piggyback the first connected player's namespace to
        broadcast a message.
        """
        for player in self.players.values():
            if player["namespace"].socket.connected:
                player["namespace"].broadcast_event(*args)
                break

    def turn(self):
        """
        Takes an actual turn of the game - called within a separate
        greenlet on the first call to bet(). We iterate through each of
        the players passing their bet_args to outcome() which multiplies
        the amount bet, and build a results dict we can broadcast back
        to all sockets.
        """
        sleep(BETTING_PERIOD)
        results = {}
        for user_id, player in self.players.items():
            result = self.outcome(*player["bet_args"])
            results[user_id] = player["amount"] * result
            if results[user_id] > 0:
                # Put a positive bet amount back into the user's account.
                user = User.objects.get(id=user_id)
                user.account.balance += (results[user_id] * 2)
                user.account.save()
        self.broadcast("game_end", self.name, results)
        self.reset()

    def reset(self):
        self.players = {}

class Dummy(Game):
    """
    Default game with no input - just randomly win lose or draw.
    If any other games are registered, this one is removed.
    """
    def outcome(self):
        # Give back 0 (lose), 1 (even) or 2 (win) times the bet.
        return randint(0, 2)

ROULETTE_CHOICES = range(0, 37)

class Roulette(Game):

    class Form(GameForm):
        number = forms.ChoiceField(choices=[(c, c) for c in ROULETTE_CHOICES])

    def turn(self):
        self.landed_on = str(choice(ROULETTE_CHOICES))
        super(Roulette, self).turn()

    def outcome(self, choice):
        return (choice == self.landed_on) * len(ROULETTE_CHOICES)
<|endoftext|>


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

import json
import requests
import re
import logging
import tempfile
import shutil
import subprocess
import os
import sys
import urllib
from multiprocessing import Pool

import docker

from collections import OrderedDict
from contextlib import contextmanager

CONFIG = "config.json"
PASSWORDS = "passwords.json"
MAX_COMMENT_SIZE = 5000
PROCS = 2
REQUEST_TIMEOUT = 180

logging.basicConfig(format="%(asctime)-15s %(name)s %(process)d %(message)s", level=logging.DEBUG)

class QueueTask(object):
    host = None
    auth = None
    config = None
    id = None
    course = None
    task = None
    issue = None
    event = None
    files = None

    def __repr__(self):
        return repr(self.__dict__)

@contextmanager
def tmp_dir():
    t = tempfile.mkdtemp(dir="/var/tmp")
    try:
        yield t
    finally:
        shutil.rmtree(t)

def git_clone(repo, dst_dir):
    cmd = ["git", "clone", repo, dst_dir]
    logging.info("RUN: %s", cmd)
    subprocess.check_call(cmd)

def prepare_dir(qtask, dirname):
    git_dir = os.path.join(dirname, "git")
    task_dir = os.path.join(dirname, "task")
    git_clone(qtask.course["repo"], git_dir)

    os.mkdir(task_dir)
    for f in qtask.files:
        url = f["url"]
        filename = url.split('/')[-1]
        dst_path = os.path.join(task_dir, filename)

        logging.info("Download '%s' -> '%s'", url, dst_path)
        urllib.urlretrieve(url, dst_path)

def proccess_task(qtask):
    logging.info("Proccess task %s", qtask.id)
    with tmp_dir() as dirname:
        prepare_dir(qtask, dirname)

        run_cmd = qtask.course["run_cmd"] + [qtask.task["title"], "/task_dir/task"]
        #run_cmd = ["ls", "/task_dir/task"]
        ret = docker.execute(run_cmd, cwd="/task_dir/git", timeout=qtask.course["timeout"], user='root',
                             network='bridge', image=qtask.course["docker_image"],
                             volumes=["{}:/task_dir:ro".format(os.path.abspath(dirname))])

        status, retcode, is_timeout, output = ret

        logging.info("Task %d done, status:%s, retcode:%d, is_timeout:%d",
                     qtask.id, status, retcode, is_timeout)

        logging.info(" == Task %d output start", qtask.id)
        for line in output.split("\n"):
            logging.info(line)
        logging.info(" == Task %d output end", qtask.id)

        if len(output) > MAX_COMMENT_SIZE:
            output = output[:MAX_COMMENT_SIZE]
            output += u"\n...\nTRUNCATED"

        if is_timeout:
            output += u"\nTIMEOUT ({} sec)".format(qtask.course["timeout"])

        comment = u"[id:{}] Check DONE!
\nSubmited on {}
\n
{}
\n".format(qtask.id,
                                                                                qtask.event["timestamp"],
                                                                                output)

        response = requests.post("{}/api/v1/issue/{}/add_comment".format(qtask.host, qtask.issue["id"]),
                                 auth=qtask.auth, data={"comment":comment.encode("utf-8")}, timeout=REQUEST_TIMEOUT)
        response.raise_for_status()
        logging.info(" == Task %d DONE!, URL: %s/issue/%d", qtask.id, qtask.host, qtask.issue["id"])
        return qtask

def load_config(filename=CONFIG):
    with open(filename) as config_fn:
        return json.load(config_fn)

def get_auth(passwords, host):
    host_auth = passwords[host]
    return (host_auth["username"], host_auth["password"])

DONE_MESSAGE_RE = re.compile(r'\[id:(\d+)\] Check DONE!')
def make_queue(config, passwords):
    queue = OrderedDict()
    for course in config:
        course_id = course["course_id"]
        auth = get_auth(passwords, course["host"])
        response = requests.get("{}/api/v1/course/{}/issues?add_events=1".format(course["host"], course_id),
                                auth=auth, timeout=REQUEST_TIMEOUT)
        if response.status_code != 200:
            logging.error("Course %d has non-200 reply. Skipped", course["course_id"])
            continue

        for issue in response.json():
            for event in issue.get("events", []):
                if event["author"]["username"] == auth[0]:
                    m = DONE_MESSAGE_RE.search(event["message"])
                    if m:
                        done_id = int(m.group(1))
                        queue.pop(done_id, None)
                    continue

                files = event.get("files")
                if not files:
                    continue

                qtask = QueueTask()
                qtask.host = course["host"]
                qtask.auth = auth
                qtask.config = config
                qtask.course = course
                qtask.task = issue["task"]
                qtask.issue = issue
                qtask.event = event
                qtask.files = files
                qtask.id = event["id"]

                queue[qtask.id] = qtask

    return queue

def main():
    logging.info("Start parallel version!")
    config = load_config()
    passwords = load_config(PASSWORDS)
    queue = make_queue(config, passwords)
    pool = Pool(processes=PROCS)

    logging.info("Queue:")
    for qtask in queue.itervalues():
        logging.info("%s\t%s\t%s\t%s\t%s\t%s", qtask.host, qtask.course["course_id"], qtask.id, qtask.task["title"],
                     qtask.issue["student"]["username"], "{}/issue/{}".format(qtask.host, qtask.issue["id"]))
    if "--only_queue" in sys.argv:
        sys.exit(0)

    for qtask in pool.imap_unordered(proccess_task, queue.itervalues()):
        logging.info(" == Parralel Task %d DONE!, URL: %s/issue/%d", qtask.id, qtask.host, qtask.issue["id"])

    logging.info("All DONE!")

if __name__ == "__main__":
    main()
<commit_msg>Enlarge MAX_COMMENT_SIZE in easy_ci_robot.py<commit_after>#!/usr/bin/env python

import json
import requests
import re
import logging
import tempfile
import shutil
import subprocess
import os
import sys
import urllib
from multiprocessing import Pool

import docker

from collections import OrderedDict
from contextlib import contextmanager

CONFIG = "config.json"
PASSWORDS = "passwords.json"
MAX_COMMENT_SIZE = 10000
PROCS = 2
REQUEST_TIMEOUT = 180

logging.basicConfig(format="%(asctime)-15s %(name)s %(process)d %(message)s", level=logging.DEBUG)

class QueueTask(object):
    host = None
    auth = None
    config = None
    id = None
    course = None
    task = None
    issue = None
    event = None
    files = None

    def __repr__(self):
        return repr(self.__dict__)

@contextmanager
def tmp_dir():
    t = tempfile.mkdtemp(dir="/var/tmp")
    try:
        yield t
    finally:
        shutil.rmtree(t)

def git_clone(repo, dst_dir):
    cmd = ["git", "clone", repo, dst_dir]
    logging.info("RUN: %s", cmd)
    subprocess.check_call(cmd)

def prepare_dir(qtask, dirname):
    git_dir = os.path.join(dirname, "git")
    task_dir = os.path.join(dirname, "task")
    git_clone(qtask.course["repo"], git_dir)

    os.mkdir(task_dir)
    for f in qtask.files:
        url = f["url"]
        filename = url.split('/')[-1]
        dst_path = os.path.join(task_dir, filename)

        logging.info("Download '%s' -> '%s'", url, dst_path)
        urllib.urlretrieve(url, dst_path)

def proccess_task(qtask):
    logging.info("Proccess task %s", qtask.id)
    with tmp_dir() as dirname:
        prepare_dir(qtask, dirname)

        run_cmd = qtask.course["run_cmd"] + [qtask.task["title"], "/task_dir/task"]
        #run_cmd = ["ls", "/task_dir/task"]
        ret = docker.execute(run_cmd, cwd="/task_dir/git", timeout=qtask.course["timeout"], user='root',
                             network='bridge', image=qtask.course["docker_image"],
                             volumes=["{}:/task_dir:ro".format(os.path.abspath(dirname))])

        status, retcode, is_timeout, output = ret

        logging.info("Task %d done, status:%s, retcode:%d, is_timeout:%d",
                     qtask.id, status, retcode, is_timeout)

        logging.info(" == Task %d output start", qtask.id)
        for line in output.split("\n"):
            logging.info(line)
        logging.info(" == Task %d output end", qtask.id)

        if len(output) > MAX_COMMENT_SIZE:
            output = output[:MAX_COMMENT_SIZE]
            output += u"\n...\nTRUNCATED"

        if is_timeout:
            output += u"\nTIMEOUT ({} sec)".format(qtask.course["timeout"])

        comment = u"[id:{}] Check DONE!
\nSubmited on {}
\n
{}
\n".format(qtask.id,
                                                                                qtask.event["timestamp"],
                                                                                output)

        response = requests.post("{}/api/v1/issue/{}/add_comment".format(qtask.host, qtask.issue["id"]),
                                 auth=qtask.auth, data={"comment":comment.encode("utf-8")}, timeout=REQUEST_TIMEOUT)
        response.raise_for_status()
        logging.info(" == Task %d DONE!, URL: %s/issue/%d", qtask.id, qtask.host, qtask.issue["id"])
        return qtask

def load_config(filename=CONFIG):
    with open(filename) as config_fn:
        return json.load(config_fn)

def get_auth(passwords, host):
    host_auth = passwords[host]
    return (host_auth["username"], host_auth["password"])

DONE_MESSAGE_RE = re.compile(r'\[id:(\d+)\] Check DONE!')
def make_queue(config, passwords):
    queue = OrderedDict()
    for course in config:
        course_id = course["course_id"]
        auth = get_auth(passwords, course["host"])
        response = requests.get("{}/api/v1/course/{}/issues?add_events=1".format(course["host"], course_id),
                                auth=auth, timeout=REQUEST_TIMEOUT)
        if response.status_code != 200:
            logging.error("Course %d has non-200 reply. Skipped", course["course_id"])
            continue

        for issue in response.json():
            for event in issue.get("events", []):
                if event["author"]["username"] == auth[0]:
                    m = DONE_MESSAGE_RE.search(event["message"])
                    if m:
                        done_id = int(m.group(1))
                        queue.pop(done_id, None)
                    continue

                files = event.get("files")
                if not files:
                    continue

                qtask = QueueTask()
                qtask.host = course["host"]
                qtask.auth = auth
                qtask.config = config
                qtask.course = course
                qtask.task = issue["task"]
                qtask.issue = issue
                qtask.event = event
                qtask.files = files
                qtask.id = event["id"]

                queue[qtask.id] = qtask

    return queue

def main():
    logging.info("Start parallel version!")
    config = load_config()
    passwords = load_config(PASSWORDS)
    queue = make_queue(config, passwords)
    pool = Pool(processes=PROCS)

    logging.info("Queue:")
    for qtask in queue.itervalues():
        logging.info("%s\t%s\t%s\t%s\t%s\t%s", qtask.host, qtask.course["course_id"], qtask.id, qtask.task["title"],
                     qtask.issue["student"]["username"], "{}/issue/{}".format(qtask.host, qtask.issue["id"]))
    if "--only_queue" in sys.argv:
        sys.exit(0)

    for qtask in pool.imap_unordered(proccess_task, queue.itervalues()):
        logging.info(" == Parralel Task %d DONE!, URL: %s/issue/%d", qtask.id, qtask.host, qtask.issue["id"])

    logging.info("All DONE!")

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


<commit_before>#!/usr/bin/python

import ConfigParser
import commands
import pygame
import sys
import time

from pushtotalk import PushToTalk

code = {'A': '.-',  'B': '-...',    'C': '-.-.',
    'D': '-..', 'E': '.',   'F': '..-.',
    'G': '--.', 'H': '....',    'I': '..',
    'J': '.---',    'K': '-.-', 'L': '.-..',
    'M': '--',  'N': '-.',  'O': '---',
    'P': '.--.',    'Q': '--.-',    'R': '.-.',
    'S': '...', 'T': '-',   'U': '..-',
    'V': '...-',    'W': '.--', 'X': '-..-',
    'Y': '-.--',    'Z': '--..',

    '0': '-----',   '1': '.----',   '2': '..---',
    '3': '...--',   '4': '....-',   '5': '.....',
    '6': '-....',   '7': '--...',   '8': '---..',
    '9': '----.'
    }

class Morse(object):

    def __init__(self):

        self.configuration()

    def configuration(self):
        self.message = ""
        self.oneunit = 0.5
        self.threeunits = 3 * self.oneunit
        self.sevenunits = 7 * self.oneunit
        self.morsefiles = 'morsefiles/'

        self.conf = ConfigParser.ConfigParser()
        self.path = "configuration/general.config"
        self.conf.read(self.path)
        self.morseagent = self.conf.get("general", "morseagent")

        if self.morseagent == 'pygame':
            pygame.init()

        self.pushtotalk = PushToTalk()

    def verify(self, message):
        keys = code.keys()
        for char in message:
            if char.upper() not in keys and char != ' ':
                sys.exit('Error the character ' + char + ' cannot be translated to Morse Code')

    def generate(self, message):

        self.pushtotalk.openport()

        if self.morseagent == 'pygame':
            self.verify(message)
            for char in message:
                if char == ' ':
                    print ' '*7,
                    time.sleep(self.sevenunits)
                else:
                    print code[char.upper()],
                    print
                    pygame.mixer.music.load(self.morsefiles + char.upper() + '_morse_code.ogg')
                    pygame.mixer.music.play()
                    time.sleep(self.threeunits)
        elif self.morseagent == 'cwpcm':
            message = 'echo ' + message + ' | /home/irlp/bin/cwpcm -sm -l 007 -p 1000 > /dev/dsp'
            status, output = commands.getstatusoutput(message)

        self.pushtotalk.closeport()

# End of File
<commit_msg>Core: Morse CWPCM Extra Fast<commit_after>#!/usr/bin/python

import ConfigParser
import commands
import pygame
import sys
import time

from pushtotalk import PushToTalk

code = {'A': '.-',  'B': '-...',    'C': '-.-.',
    'D': '-..', 'E': '.',   'F': '..-.',
    'G': '--.', 'H': '....',    'I': '..',
    'J': '.---',    'K': '-.-', 'L': '.-..',
    'M': '--',  'N': '-.',  'O': '---',
    'P': '.--.',    'Q': '--.-',    'R': '.-.',
    'S': '...', 'T': '-',   'U': '..-',
    'V': '...-',    'W': '.--', 'X': '-..-',
    'Y': '-.--',    'Z': '--..',

    '0': '-----',   '1': '.----',   '2': '..---',
    '3': '...--',   '4': '....-',   '5': '.....',
    '6': '-....',   '7': '--...',   '8': '---..',
    '9': '----.'
    }

class Morse(object):

    def __init__(self):

        self.configuration()

    def configuration(self):
        self.message = ""
        self.oneunit = 0.5
        self.threeunits = 3 * self.oneunit
        self.sevenunits = 7 * self.oneunit
        self.morsefiles = 'morsefiles/'

        self.conf = ConfigParser.ConfigParser()
        self.path = "configuration/general.config"
        self.conf.read(self.path)
        self.morseagent = self.conf.get("general", "morseagent")

        if self.morseagent == 'pygame':
            pygame.init()

        self.pushtotalk = PushToTalk()

    def verify(self, message):
        keys = code.keys()
        for char in message:
            if char.upper() not in keys and char != ' ':
                sys.exit('Error the character ' + char + ' cannot be translated to Morse Code')

    def generate(self, message):

        self.pushtotalk.openport()

        if self.morseagent == 'pygame':
            self.verify(message)
            for char in message:
                if char == ' ':
                    print ' '*7,
                    time.sleep(self.sevenunits)
                else:
                    print code[char.upper()],
                    print
                    pygame.mixer.music.load(self.morsefiles + char.upper() + '_morse_code.ogg')
                    pygame.mixer.music.play()
                    time.sleep(self.threeunits)
        elif self.morseagent == 'cwpcm':
            message = 'echo ' + message + ' | /home/irlp/bin/cwpcm -sx -l 007 -p 1000 > /dev/dsp'
            status, output = commands.getstatusoutput(message)

        self.pushtotalk.closeport()

# End of File
<|endoftext|>


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

'''
functions
'''
def identity(x): return x

def noop(): pass

def head(arr):
    return arr[0]

def empty(arr):
    return not arr

def tail(arr):
    return arr[1:]

def last(arr):
    l = arr[-1:]
    if l:
        return l[0]
    else:
        return None

def nth(arr, i, out_of_range=None):
    if len(arr) >= i:
        return arr[i]
    return out_of_range

def juxt(*funs):
    ''' juxtaposition '''
    return lambda *args: [fn(*args) for fn in funs]

#
# TODO
# take array as the path in a nested dict and update that item with
# the new value
# def updateIn(d, arraypath, value):
#

def getIn(d, arraypath, default=None):
    '''
    Take array as the path to a dict item and return the item or default if path does not exist.
    '''
    if not d:
        return d
    if not arraypath:
        return d
    else:
        return getIn(d.get(arraypath[0]), arraypath[1:], default) \
            if d.get(arraypath[0]) else default

def reorganizeList(lst, idxs, out_of_range=None):
    # functions for getting a specific index
    n = lambda i: lambda l: nth(l, i, out_of_range)
    # function to apply all index functions to a list
    fn = juxt(*map(n, idxs))
    return fn(lst)

# TODO
#def curry(fn):
#    pass

# TODO
# def partial(fn, args):
#     pass

def inc(n):
    return n+1

def dec(n):
    return n-1

def utf8(sz):
    return sz.encode('utf-8')

def partition(l, n):
    """
    Yield successive n-sized partitions from l.
    >>> partition(range(1,10),2)
    [[1, 2], [3, 4], [5, 6], [7, 8], [9]]
    """
    def _part():
        for i in xrange(0, len(l), n):
            yield l[i:i+n]
    #I prefer it to be a list instead of generator
    return [i for i in _part()]

# from julia
def mapreduce(mapFn, reduceFn, items):
    return reduce(reduceFn, map(mapFn, items))

# alpha
def wrapwith(object):
    '''
    dynamically create a with statement object for closed-over resource
    '''
    def __init__(self, openfn, closefn):
        self.openfn = openfn
        self.closefn = closefn

    def __enter__(self):
        return self.openfn()

    def __exit__(self, type, value, traceback):
        self.closefn()

def juxt_all(predicates, obj):
    '''
    run a juxtaposition of predicates against an object return True
    if all pass, exits immediately when first False is encountered
    '''
    def genfn():
        for p in predicates:
            yield p(obj)
    for x in genfn():
        if not x:
            return False
    return True

def juxt_any(predicates, obj):
    '''
    reverse of juxt_all - returns immediately on first True
    returns False if no predicates passn
    '''
    def genfn():
        for p in predicates:
            yield p(obj)
    for x in genfn():
        if x:
            return True
    return False

# return a snowman
def snowman(): return u'☃'
<commit_msg>Update functions.py<commit_after># -*- coding: utf-8 -*-

'''
functions
'''
def identity(x): return x

def noop(): pass

def head(arr):
    return arr[0]

def empty(arr):
    return not arr

def rest(arr):
    return arr[1:]

def last(arr):
    l = arr[-1:]
    if l:
        return l[0]
    else:
        return None

def nth(arr, i, out_of_range=None):
    if len(arr) >= i:
        return arr[i]
    return out_of_range

def juxt(*funs):
    ''' juxtaposition '''
    return lambda *args: [fn(*args) for fn in funs]

#
# TODO
# take array as the path in a nested dict and update that item with
# the new value
# def updateIn(d, arraypath, value):
#

def getIn(d, arraypath, default=None):
    '''
    Take array as the path to a dict item and return the item or default if path does not exist.
    '''
    if not d:
        return d
    if not arraypath:
        return d
    else:
        return getIn(d.get(arraypath[0]), arraypath[1:], default) \
            if d.get(arraypath[0]) else default

def reorganizeList(lst, idxs, out_of_range=None):
    # functions for getting a specific index
    n = lambda i: lambda l: nth(l, i, out_of_range)
    # function to apply all index functions to a list
    fn = juxt(*map(n, idxs))
    return fn(lst)

# TODO
#def curry(fn):
#    pass

# TODO
# def partial(fn, args):
#     pass

def inc(n):
    return n+1

def dec(n):
    return n-1

def utf8(sz):
    return sz.encode('utf-8')

def partition(l, n):
    """
    Yield successive n-sized partitions from l.
    >>> partition(range(1,10),2)
    [[1, 2], [3, 4], [5, 6], [7, 8], [9]]
    """
    def _part():
        for i in xrange(0, len(l), n):
            yield l[i:i+n]
    #I prefer it to be a list instead of generator
    return [i for i in _part()]

# from julia
def mapreduce(mapFn, reduceFn, items):
    return reduce(reduceFn, map(mapFn, items))

# alpha
def wrapwith(object):
    '''
    dynamically create a with statement object for closed-over resource
    '''
    def __init__(self, openfn, closefn):
        self.openfn = openfn
        self.closefn = closefn

    def __enter__(self):
        return self.openfn()

    def __exit__(self, type, value, traceback):
        self.closefn()

def juxt_all(predicates, obj):
    '''
    run a juxtaposition of predicates against an object return True
    if all pass, exits immediately when first False is encountered
    '''
    def genfn():
        for p in predicates:
            yield p(obj)
    for x in genfn():
        if not x:
            return False
    return True

def juxt_any(predicates, obj):
    '''
    reverse of juxt_all - returns immediately on first True
    returns False if no predicates passn
    '''
    def genfn():
        for p in predicates:
            yield p(obj)
    for x in genfn():
        if x:
            return True
    return False

# return a snowman
def snowman(): return u'☃'
<|endoftext|>