<commit_before>"""
Simple API to docker.
"""

import requests
from paramiko import SSHClient, SSHException, AutoAddPolicy
from git import Repository
from config import config
from subprocess import check_output
from datetime import datetime
from dateutil.parser import parse as parse_date
import socket

class Container:
    """
    Class representing a container, providing the necessary information and
    operations.
    """
    def __init__(self, data):
        """
        :param dict data: dict data: The dataset returned by the Docker API.
        """
        self.__data = data

    def __str__(self):
        return self.name

    @classmethod
    def list(cls):
        return containers()

    @classmethod
    def create(cls, name, image, volumes):
        return create(name, image, volumes)

    @property
    def id(self):
        """
        The containers Id.

        :rtype: str
        """
        return self.__data['Id']

    @property
    def image(self):
        """
        The image's id the container was created from.

        :rtype: str
        """
        return self.__data['Image']

    @property
    def name(self):
        """
        The containers name.

        :rtype: str
        """
        return self.__data['Name']

    @property
    def project(self):
        """
        The containers project. First segment of [Container.name].

        :rtype: str
        """
        return self.name.split('.')[0].strip('/')

    @property
    def instance(self):
        """
        The containers instance. Second segment of [Container.name].

        :rtype: str
        """
        return self.name.split('.')[1]

    @property
    def hash(self):
        """
        The containers git hash. Second segment of [Container.name].

        :rtype: str
        """
        return self.name.split('.')[2]

    @property
    def domain(self):
        """
        The containers internal domain name.

        :rtype: str
        """
        if self.project is self.instance:
            return "%s.dork" % self.project
        else:
            return "%s.%s.dork" % (self.project, self.instance)

    @property
    def running(self):
        """
        Check if the container is running.

        :rtype: bool
        """
        return self.__data['State']['Running']

    @property
    def address(self):
        """
        The containers IP address, or [None] if the container is not running.

        :rtype: str
        """
        if self.running:
            return self.__data['NetworkSettings']['IPAddress']
        else:
            return None

    @property
    def source(self):
        """
        The directory on the host machine, mounted to the containers source
        directory.

        :rtype: str
        """
        directory = None
        for bind in self.__data['HostConfig']['Binds']:
            host = bind.split(':')[0]
            container = bind.split(':')[1]
            if container == config().dork_source_directory:
                directory = host
        return directory

    @property
    def repository(self):
        """
        Retrieve the containers source git repository.

        :rtype: Repository
        """
        return Repository(self.source)

    @property
    def build(self):
        """
        The directory on the host machine, mounted to the containers build
        directory.

        :rtype: str
        """
        directory = None
        for bind in self.__data['HostConfig']['Binds']:
            host = bind.split(':')[0]
            container = bind.split(':')[1]
            if container == config().dork_build_directory:
                directory = host
        return directory

    @property
    def accessible(self):
        """:rtype: bool"""
        if not self.running:
            return False
        else:
            return _container_accessible(self.address)

    @property
    def time_created(self):
        """:rtype: datetime"""
        return parse_date(self.__data['Created'])

    @property
    def time_started(self):
        """:rtype: datetime"""
        if self.running:
            return parse_date(self.__data['State']['StartedAt'])
        else:
            return None

    @property
    def time_stopped(self):
        """:rtype: datetime"""
        if self.running:
            return None
        else:
            return parse_date(self.__data['State']['FinishedAt'])

    def start(self):
        _container_start(self.id)

    def stop(self):
        _container_stop(self.id)

    def remove(self):
        _container_remove(self.id)

    def rename(self, name):
        _container_rename(self.id, name)

    def commit(self, repo):
        _container_commit(self.id, repo)

class Image:
    def __init__(self, data):
        self.__data = data

    def __str__(self):
        return self.name

    @classmethod
    def list(cls):
        return images()

    @classmethod
    def dangling(cls):
        return _dangling_images()

    @property
    def id(self):
        """:rtype: str"""
        return self.__data['Id']

    @property
    def name(self):
        """:rtype: str"""
        return self.__data['RepoTags'][0].split(':')[0]

    @property
    def project(self):
        """:rtype: str"""
        return self.name.split('/')[0]

    @property
    def hash(self):
        """:rtype: str"""
        return self.name.split('/')[1]

    @property
    def time_created(self):
        """:rtype: datetime"""
        return parse_date(self.__data['Created'])

    def delete(self):
        _image_remove(self.id)

class BaseImage:
    def __init__(self, project):
        self.project = project
        self.name = config().base_image
        self.hash = 'new'

# ======================================================================
# PUBLIC METHODS
# ======================================================================
__containers = None
def containers(clear=False):
    global __containers
    if __containers is None or clear:
        __containers = [Container(__get('containers/%s/json' % c['Id']))
                          for c in __get('containers/json', query={'all': 1})]
    return __containers

__images = None
def images(clear=False):
    global __images
    if __images is None or clear:
        __images = []
        for i in __get('images/json'):
            data = __get('images/%s/json' % i['Id'])
            if 'RepoTags' in i:
                data['RepoTags'] = i['RepoTags']
                __images.append(Image(data))
    return __images

def create(name, image, volumes):
    """:type volumes: dict"""
    data = {
        'Image': image,
        'Volumes': {},
        'HostConfig': {
            'Binds': [],
        },
    }
    for host in volumes:
        container = volumes[host]
        data['Volumes'][container] = {}
        data['HostConfig']['Binds'].append("%s:%s" % (host, container))
    __post(
        'containers/create',
        query={'name': name},
        data=data,
        codes=(201,))
    containers(True)

def _dangling_images():
    image_ids = check_output([
        'docker', 'images', '-q', '-f', 'dangling=true'
    ]).splitlines()
    for iid in image_ids:
        yield Image(__get('images/%s/json' % iid))

# ======================================================================
# PROTECTED METHODS
# ======================================================================
def _container_start(cid):
    __post('containers/%s/start' % cid, codes=(204, 304))
    containers(True)

def _container_stop(cid):
    __post('containers/%s/stop' % cid, codes=(204, 304))
    containers(True)

def _container_remove(cid):
    __delete('containers/%s' % cid, codes=(204,))
    containers(True)

def _container_rename(cid, name):
    __post(
        'containers/%s/rename' % cid,
        query={'name': name}, codes=(204,))
    containers(True)

def _container_commit(cid, repo):
    __post(
        'commit',
        query={'container': cid, 'repo': repo},
        codes=(201,))
    images(True)

def _container_accessible(address):
    client = SSHClient()
    client.load_system_host_keys()
    client.set_missing_host_key_policy(AutoAddPolicy())
    try:
        client.connect(address, username=config().dork_user, key_filename='/etc/dork-keys/key')
        return True
    except socket.error:
        return False

def _image_remove(iid):
    __delete('images/%s' % iid, codes=(200,))
    images(True)

# ======================================================================
# PRIVATE METHODS
# ======================================================================
class DockerException(Exception):
    def __init__(self, msg, code):
        super(DockerException, self).__init__(msg)
        self.code = code

def __get(path, query=(), codes=(200,)):
    """
    :param str path:
    :param dict[str,str] query:
    :param list[int] codes:
    :return: json
    """

    result = requests.get(
        "%s/%s" % (config().docker_address, path),
        params=query)

    if result.status_code in codes:
        return result.json()
    else:
        raise DockerException(result.status_code, result.text)

def __post(path, query=(), data=(), codes=(200,)):

    if data:
        result = requests.post(
            "%s/%s" % (config().docker_address, path),
            params=query, json=data)
    else:
        result = requests.post(
            "%s/%s" % (config().docker_address, path),
            params=query)

    if result.status_code not in codes:
        raise DockerException(result.status_code, result.text)

def __delete(path, query=(), codes=(200,)):

    result = requests.delete(
        "%s/%s" % (config().docker_address, path),
        params=query)

    if result.status_code not in codes:
        raise DockerException(result.status_code, result.text)
<commit_msg>Added execute() method to containers.<commit_after>"""
Simple API to docker.
"""

import requests
from paramiko import SSHClient, SSHException, AutoAddPolicy
from git import Repository
from config import config
from subprocess import check_output
from datetime import datetime
from dateutil.parser import parse as parse_date
import socket
import json

class Container:
    """
    Class representing a container, providing the necessary information and
    operations.
    """
    def __init__(self, data):
        """
        :param dict data: dict data: The dataset returned by the Docker API.
        """
        self.__data = data

    def __str__(self):
        return self.name

    @classmethod
    def list(cls):
        return containers()

    @classmethod
    def create(cls, name, image, volumes):
        return create(name, image, volumes)

    @property
    def id(self):
        """
        The containers Id.

        :rtype: str
        """
        return self.__data['Id']

    @property
    def image(self):
        """
        The image's id the container was created from.

        :rtype: str
        """
        return self.__data['Image']

    @property
    def name(self):
        """
        The containers name.

        :rtype: str
        """
        return self.__data['Name']

    @property
    def project(self):
        """
        The containers project. First segment of [Container.name].

        :rtype: str
        """
        return self.name.split('.')[0].strip('/')

    @property
    def instance(self):
        """
        The containers instance. Second segment of [Container.name].

        :rtype: str
        """
        return self.name.split('.')[1]

    @property
    def hash(self):
        """
        The containers git hash. Second segment of [Container.name].

        :rtype: str
        """
        return self.name.split('.')[2]

    @property
    def domain(self):
        """
        The containers internal domain name.

        :rtype: str
        """
        if self.project is self.instance:
            return "%s.dork" % self.project
        else:
            return "%s.%s.dork" % (self.project, self.instance)

    @property
    def running(self):
        """
        Check if the container is running.

        :rtype: bool
        """
        return self.__data['State']['Running']

    @property
    def address(self):
        """
        The containers IP address, or [None] if the container is not running.

        :rtype: str
        """
        if self.running:
            return self.__data['NetworkSettings']['IPAddress']
        else:
            return None

    @property
    def source(self):
        """
        The directory on the host machine, mounted to the containers source
        directory.

        :rtype: str
        """
        directory = None
        for bind in self.__data['HostConfig']['Binds']:
            host = bind.split(':')[0]
            container = bind.split(':')[1]
            if container == config().dork_source_directory:
                directory = host
        return directory

    @property
    def repository(self):
        """
        Retrieve the containers source git repository.

        :rtype: Repository
        """
        return Repository(self.source)

    @property
    def build(self):
        """
        The directory on the host machine, mounted to the containers build
        directory.

        :rtype: str
        """
        directory = None
        for bind in self.__data['HostConfig']['Binds']:
            host = bind.split(':')[0]
            container = bind.split(':')[1]
            if container == config().dork_build_directory:
                directory = host
        return directory

    @property
    def accessible(self):
        """:rtype: bool"""
        if not self.running:
            return False
        else:
            return _container_accessible(self.address)

    @property
    def time_created(self):
        """:rtype: datetime"""
        return parse_date(self.__data['Created'])

    @property
    def time_started(self):
        """:rtype: datetime"""
        if self.running:
            return parse_date(self.__data['State']['StartedAt'])
        else:
            return None

    @property
    def time_stopped(self):
        """:rtype: datetime"""
        if self.running:
            return None
        else:
            return parse_date(self.__data['State']['FinishedAt'])

    def start(self):
        _container_start(self.id)

    def stop(self):
        _container_stop(self.id)

    def remove(self):
        _container_remove(self.id)

    def rename(self, name):
        _container_rename(self.id, name)

    def commit(self, repo):
        _container_commit(self.id, repo)

    def execute(self, command):
        _container_execute(self.id, command)

class Image:
    def __init__(self, data):
        self.__data = data

    def __str__(self):
        return self.name

    @classmethod
    def list(cls):
        return images()

    @classmethod
    def dangling(cls):
        return _dangling_images()

    @property
    def id(self):
        """:rtype: str"""
        return self.__data['Id']

    @property
    def name(self):
        """:rtype: str"""
        return self.__data['RepoTags'][0].split(':')[0]

    @property
    def project(self):
        """:rtype: str"""
        return self.name.split('/')[0]

    @property
    def hash(self):
        """:rtype: str"""
        return self.name.split('/')[1]

    @property
    def time_created(self):
        """:rtype: datetime"""
        return parse_date(self.__data['Created'])

    def delete(self):
        _image_remove(self.id)

class BaseImage:
    def __init__(self, project):
        self.project = project
        self.name = config().base_image
        self.hash = 'new'

# ======================================================================
# PUBLIC METHODS
# ======================================================================
__containers = None
def containers(clear=False):
    global __containers
    if __containers is None or clear:
        __containers = [Container(__get('containers/%s/json' % c['Id']))
                          for c in __get('containers/json', query={'all': 1})]
    return __containers

__images = None
def images(clear=False):
    global __images
    if __images is None or clear:
        __images = []
        for i in __get('images/json'):
            data = __get('images/%s/json' % i['Id'])
            if 'RepoTags' in i:
                data['RepoTags'] = i['RepoTags']
                __images.append(Image(data))
    return __images

def create(name, image, volumes):
    """:type volumes: dict"""
    data = {
        'Image': image,
        'Volumes': {},
        'HostConfig': {
            'Binds': [],
        },
    }
    for host in volumes:
        container = volumes[host]
        data['Volumes'][container] = {}
        data['HostConfig']['Binds'].append("%s:%s" % (host, container))
    __post(
        'containers/create',
        query={'name': name},
        data=data,
        codes=(201,))
    containers(True)

def _dangling_images():
    image_ids = check_output([
        'docker', 'images', '-q', '-f', 'dangling=true'
    ]).splitlines()
    for iid in image_ids:
        yield Image(__get('images/%s/json' % iid))

# ======================================================================
# PROTECTED METHODS
# ======================================================================
def _container_start(cid):
    __post('containers/%s/start' % cid, codes=(204, 304))
    containers(True)

def _container_stop(cid):
    __post('containers/%s/stop' % cid, codes=(204, 304))
    containers(True)

def _container_remove(cid):
    __delete('containers/%s' % cid, codes=(204,))
    containers(True)

def _container_rename(cid, name):
    __post(
        'containers/%s/rename' % cid,
        query={'name': name}, codes=(204,))
    containers(True)

def _container_commit(cid, repo):
    __post(
        'commit',
        query={'container': cid, 'repo': repo},
        codes=(201,))
    images(True)

def _container_accessible(address):
    client = SSHClient()
    client.load_system_host_keys()
    client.set_missing_host_key_policy(AutoAddPolicy())
    try:
        client.connect(address, username=config().dork_user, key_filename='/etc/dork-keys/key')
        return True
    except socket.error:
        return False

def _container_execute(id, command):
    execute = json.loads(__post('containers/%s/exec' % id, data= {
        "AttachStdin": False,
        "AttachStdout": True,
        "AttachStderr": True,
        "Tty": False,
        "Cmd": command,
    }, codes=(201,)))
    return __post('exec/%s/start' % execute['Id'], data = {
        "Detach": False,
        "Tty": False,
    }, codes=(200,))

def _image_remove(iid):
    __delete('images/%s' % iid, codes=(200,))
    images(True)

# ======================================================================
# PRIVATE METHODS
# ======================================================================
class DockerException(Exception):
    def __init__(self, msg, code):
        super(DockerException, self).__init__(msg)
        self.code = code

def __get(path, query=(), codes=(200,)):
    """
    :param str path:
    :param dict[str,str] query:
    :param list[int] codes:
    :return: json
    """

    result = requests.get(
        "%s/%s" % (config().docker_address, path),
        params=query)

    if result.status_code in codes:
        return result.json()
    else:
        raise DockerException(result.status_code, result.text)

def __post(path, query=(), data=(), codes=(200,)):

    if data:
        result = requests.post(
            "%s/%s" % (config().docker_address, path),
            params=query, json=data)
    else:
        result = requests.post(
            "%s/%s" % (config().docker_address, path),
            params=query)

    if result.status_code not in codes:
        raise DockerException(result.status_code, result.text)
    return result.text

def __delete(path, query=(), codes=(200,)):

    result = requests.delete(
        "%s/%s" % (config().docker_address, path),
        params=query)

    if result.status_code not in codes:
        raise DockerException(result.status_code, result.text)
<|endoftext|>


<commit_before>"""
A base contact form for allowing users to send email messages through
a web interface, and a subclass demonstrating useful functionality.

"""

import sha

from django import newforms as forms
from django.conf import settings
from django.core.mail import send_mail
from django.template import loader, RequestContext
from django.contrib.sites.models import Site

# I put this on all required fields, because it's easier to pick up
# on them with CSS or JavaScript if they have a class of "required"
# in the HTML. Your mileage may vary.
attrs_dict = { 'class': 'required' }

class ContactForm(forms.Form):
    """
    Base contact form class from which all contact form classes should
    inherit.

    If you don't need any custom functionality, you can simply use
    this form to provide basic contact functionality; it will collect
    name, email address and message.

    The ``contact_form`` view included in this application knows how
    to work with this form and can handle many types of subclasses as
    well (see below for a discussion of the important points), so in
    many cases it will be all that you need. If you'd like to use this
    form or a subclass of it from one of your own views, just do the
    following:

        1. When you instantiate the form, pass the current
           ``HttpRequest`` object to the constructor as the keyword
           argument ``request``; this is used internally by the base
           implementation, and also made available so that subclasses
           can add functionality which relies on inspecting the
           request.

        2. To send the message, call the form's ``save`` method, which
           accepts the keyword argument ``fail_silently`` and defaults
           it to ``False``. This argument is passed directly to
           ``send_mail``, and allows you to suppress or raise
           exceptions as needed for debugging. The ``save`` method has
           no return value.

    Other than that, treat it like any other form; validity checks and
    validated data are handled normally, through the ``is_valid``
    method and the ``cleaned_data`` dictionary.

    Base implementation
    -------------------

    Under the hood, this form uses a somewhat abstracted interface in
    order to make it easier to subclass and add functionality. There
    are several important attributes subclasses may want to look at
    overriding, all of which will work (in the base implementation) as
    either plain attributes or as callable methods:

        * ``from_email`` -- used to get the address to use in the
          ``From:`` header of the message. The base implementation
          returns the value of the ``DEFAULT_FROM_EMAIL`` setting.

        * ``message`` -- used to get the message body as a string. The
          base implementation renders a template using the form's
          ``cleaned_data`` dictionary as context.

        * ``recipient_list`` -- used to generate the list of
          recipients for the message. The base implementation returns
          the email addresses specified in the ``MANAGERS`` setting.

        * ``subject`` -- used to generate the subject line for the
          message. The base implementation returns the string 'Message
          sent through the web site', with the name of the current
          ``Site`` prepended.

        * ``template_name`` -- used by the base ``message`` method to
          determine which template to use for rendering the
          message. Default is ``contact_form/contact_form.txt``.

    Internally, the base implementation ``_get_message_dict`` method
    collects ``from_email``, ``message``, ``recipient_list`` and
    ``subject`` into a dictionary, which the ``save`` method then
    passes directly to ``send_mail`` as keyword arguments.

    Particularly important is the ``message`` attribute, with its base
    implementation as a method which renders a template; because it
    passes ``cleaned_data`` as the template context, any additional
    fields added by a subclass will automatically be available in the
    template. This means that many useful subclasses can get by with
    just adding a few fields and possibly overriding
    ``template_name``.

    Much useful functionality can be achieved in subclasses without
    having to override much of the above; adding additional validation
    methods works the same as any other form, and typically only a few
    items -- ``recipient_list`` and ``subject_line``, for example,
    need to be overridden to achieve customized behavior.

    Other notes for subclassing
    ---------------------------

    Subclasses which want to inspect the current ``HttpRequest`` to
    add functionality can access it via the attribute ``request``; the
    base ``message`` takes advantage of this to use ``RequestContext``
    when rendering its template. See the ``AkismetContactForm``
    subclass in this file for an example of using the request to
    perform additional validation.

    Subclasses which override ``__init__`` need to accept ``*args``
    and ``**kwargs``, and pass them via ``super`` in order to ensure
    proper behavior.

    Subclasses should be careful if overriding ``_get_message_dict``,
    since that method **must** return a dictionary suitable for
    passing directly to ``send_mail`` (unless ``save`` is overridden
    as well).

    Overriding ``save`` is relatively safe, though remember that code
    which uses your form will expect ``save`` to accept the
    ``fail_silently`` keyword argument. In the base implementation,
    that argument defaults to ``False``, on the assumption that it's
    far better to notice errors than to silently not send mail from
    the contact form (see also the Zen of Python: "Errors should never
    pass silently, unless explicitly silenced").

    """
    def __init__(self, data=None, request=None, *args, **kwargs):
        if request is None:
            raise TypeError("Keyword argument 'request' must be supplied")
        super(ContactForm, self).__init__(data, *args, **kwargs)
        self.request = request

    name = forms.CharField(max_length=100,
                           widget=forms.TextInput(attrs=attrs_dict),
                           label=u'Your name')
    email = forms.EmailField(widget=forms.TextInput(attrs=dict(attrs_dict,
                                                               maxlength=200)),
                             label=u'Your email address')
    body = forms.CharField(widget=forms.Textarea(attrs=attrs_dict),
                              label=u'Your message')

    from_email = settings.DEFAULT_FROM_EMAIL

    recipient_list = [mail_tuple[1] for mail_tuple in settings.MANAGERS]

    subject = "[%s] Message sent through the web site" % Site.objects.get_current().name

    template_name = 'contact_form/contact_form.txt'

    def message(self):
        """
        Renders the body of the message to a string.

        """
        if callable(self.template_name):
            template_name = self.template_name()
        else:
            template_name = self.template_name
        t = loader.get_template(template_name)
        return t.render(RequestContext(self.request, self.cleaned_data))

    def _get_message_dict(self):
        if not self.is_valid():
            raise ValueError("Message cannot be sent from invalid contact form")
        message_dict = {}
        for message_part in ('from_email', 'message', 'recipient_list', 'subject'):
            attr = getattr(self, message_part)
            message_dict[message_part] = callable(attr) and attr() or attr
        return message_dict

    def save(self, fail_silently=False):
        """
        Builds and sends the email message.

        """
        send_mail(fail_silently=fail_silently, **self._get_message_dict())

class AkismetContactForm(ContactForm):
    """
    Contact form which doesn't add any extra fields, but does add an
    Akismet spam check to the validation routine.

    Requires the setting ``AKISMET_API_KEY``, which should be a valid
    Akismet API key.

    """
    def clean_body(self):
        if 'body' in self.cleaned_data and hasattr(settings, 'AKISMET_API_KEY') and settings.AKISMET_API_KEY:
            from akismet import Akismet
            akismet_api = Akismet(key=settings.AKISMET_API_KEY,
                                  blog_url='http://%s/' % Site.objects.get_current().domain)
            if akismet_api.verify_key():
                akismet_data = { 'comment_type': 'comment',
                                 'referer': self.request.META.get('HTTP_REFERER', ''),
                                 'user_ip': self.request.META.get('REMOTE_ADDR', ''),
                                 'user_agent': self.request.META.get('HTTP_USER_AGENT', '') }
                if akismet_api.comment_check(self.cleaned_data['body'], data=akismet_data, build_data=True):
                    raise forms.ValidationError(u"Akismet thinks this message is spam")
        return self.cleaned_data['body']
<commit_msg>Quick Unicode fix<commit_after>"""
A base contact form for allowing users to send email messages through
a web interface, and a subclass demonstrating useful functionality.

"""

from django import newforms as forms
from django.conf import settings
from django.core.mail import send_mail
from django.template import loader, RequestContext
from django.contrib.sites.models import Site

# I put this on all required fields, because it's easier to pick up
# on them with CSS or JavaScript if they have a class of "required"
# in the HTML. Your mileage may vary.
attrs_dict = { 'class': 'required' }

class ContactForm(forms.Form):
    """
    Base contact form class from which all contact form classes should
    inherit.

    If you don't need any custom functionality, you can simply use
    this form to provide basic contact functionality; it will collect
    name, email address and message.

    The ``contact_form`` view included in this application knows how
    to work with this form and can handle many types of subclasses as
    well (see below for a discussion of the important points), so in
    many cases it will be all that you need. If you'd like to use this
    form or a subclass of it from one of your own views, just do the
    following:

        1. When you instantiate the form, pass the current
           ``HttpRequest`` object to the constructor as the keyword
           argument ``request``; this is used internally by the base
           implementation, and also made available so that subclasses
           can add functionality which relies on inspecting the
           request.

        2. To send the message, call the form's ``save`` method, which
           accepts the keyword argument ``fail_silently`` and defaults
           it to ``False``. This argument is passed directly to
           ``send_mail``, and allows you to suppress or raise
           exceptions as needed for debugging. The ``save`` method has
           no return value.

    Other than that, treat it like any other form; validity checks and
    validated data are handled normally, through the ``is_valid``
    method and the ``cleaned_data`` dictionary.

    Base implementation
    -------------------

    Under the hood, this form uses a somewhat abstracted interface in
    order to make it easier to subclass and add functionality. There
    are several important attributes subclasses may want to look at
    overriding, all of which will work (in the base implementation) as
    either plain attributes or as callable methods:

        * ``from_email`` -- used to get the address to use in the
          ``From:`` header of the message. The base implementation
          returns the value of the ``DEFAULT_FROM_EMAIL`` setting.

        * ``message`` -- used to get the message body as a string. The
          base implementation renders a template using the form's
          ``cleaned_data`` dictionary as context.

        * ``recipient_list`` -- used to generate the list of
          recipients for the message. The base implementation returns
          the email addresses specified in the ``MANAGERS`` setting.

        * ``subject`` -- used to generate the subject line for the
          message. The base implementation returns the string 'Message
          sent through the web site', with the name of the current
          ``Site`` prepended.

        * ``template_name`` -- used by the base ``message`` method to
          determine which template to use for rendering the
          message. Default is ``contact_form/contact_form.txt``.

    Internally, the base implementation ``_get_message_dict`` method
    collects ``from_email``, ``message``, ``recipient_list`` and
    ``subject`` into a dictionary, which the ``save`` method then
    passes directly to ``send_mail`` as keyword arguments.

    Particularly important is the ``message`` attribute, with its base
    implementation as a method which renders a template; because it
    passes ``cleaned_data`` as the template context, any additional
    fields added by a subclass will automatically be available in the
    template. This means that many useful subclasses can get by with
    just adding a few fields and possibly overriding
    ``template_name``.

    Much useful functionality can be achieved in subclasses without
    having to override much of the above; adding additional validation
    methods works the same as any other form, and typically only a few
    items -- ``recipient_list`` and ``subject_line``, for example,
    need to be overridden to achieve customized behavior.

    Other notes for subclassing
    ---------------------------

    Subclasses which want to inspect the current ``HttpRequest`` to
    add functionality can access it via the attribute ``request``; the
    base ``message`` takes advantage of this to use ``RequestContext``
    when rendering its template. See the ``AkismetContactForm``
    subclass in this file for an example of using the request to
    perform additional validation.

    Subclasses which override ``__init__`` need to accept ``*args``
    and ``**kwargs``, and pass them via ``super`` in order to ensure
    proper behavior.

    Subclasses should be careful if overriding ``_get_message_dict``,
    since that method **must** return a dictionary suitable for
    passing directly to ``send_mail`` (unless ``save`` is overridden
    as well).

    Overriding ``save`` is relatively safe, though remember that code
    which uses your form will expect ``save`` to accept the
    ``fail_silently`` keyword argument. In the base implementation,
    that argument defaults to ``False``, on the assumption that it's
    far better to notice errors than to silently not send mail from
    the contact form (see also the Zen of Python: "Errors should never
    pass silently, unless explicitly silenced").

    """
    def __init__(self, data=None, request=None, *args, **kwargs):
        if request is None:
            raise TypeError("Keyword argument 'request' must be supplied")
        super(ContactForm, self).__init__(data, *args, **kwargs)
        self.request = request

    name = forms.CharField(max_length=100,
                           widget=forms.TextInput(attrs=attrs_dict),
                           label=u'Your name')
    email = forms.EmailField(widget=forms.TextInput(attrs=dict(attrs_dict,
                                                               maxlength=200)),
                             label=u'Your email address')
    body = forms.CharField(widget=forms.Textarea(attrs=attrs_dict),
                              label=u'Your message')

    from_email = settings.DEFAULT_FROM_EMAIL

    recipient_list = [mail_tuple[1] for mail_tuple in settings.MANAGERS]

    subject_template_name = "contact_form/contact_form_subject.txt"

    template_name = 'contact_form/contact_form.txt'

    _context = None

    def message(self):
        """
        Renders the body of the message to a string.

        """
        if callable(self.template_name):
            template_name = self.template_name()
        else:
            template_name = self.template_name
        return loader.render_to_string(template_name,
                                       self.get_context())

    def subject(self):
        """
        Renders the subject of the message to a string.

        """
        subject = loader.render_to_string(self.subject_template_name,
                                          self.get_context())
        return ''.join(subject.splitlines())

    def get_context(self):
        if not self.is_valid():
            raise ValueError("Cannot generate Context from invalid contact form")
        if self._context is None:
            self._context = RequestContext(self.request,
                                           dict(self.cleaned_data,
                                                site=Site.objects.get_current()))
        return self._context

    def get_message_dict(self):
        if not self.is_valid():
            raise ValueError("Message cannot be sent from invalid contact form")
        message_dict = {}
        for message_part in ('from_email', 'message', 'recipient_list', 'subject'):
            attr = getattr(self, message_part)
            message_dict[message_part] = callable(attr) and attr() or attr
        return message_dict

    def save(self, fail_silently=False):
        """
        Builds and sends the email message.

        """
        send_mail(fail_silently=fail_silently, **self.get_message_dict())

class AkismetContactForm(ContactForm):
    """
    Contact form which doesn't add any extra fields, but does add an
    Akismet spam check to the validation routine.

    Requires the setting ``AKISMET_API_KEY``, which should be a valid
    Akismet API key.

    """
    def clean_body(self):
        if 'body' in self.cleaned_data and getattr(settings, 'AKISMET_API_KEY', ''):
            from akismet import Akismet
            from django.utils.encoding import smart_str
            akismet_api = Akismet(key=settings.AKISMET_API_KEY,
                                  blog_url='http://%s/' % Site.objects.get_current().domain)
            if akismet_api.verify_key():
                akismet_data = { 'comment_type': 'comment',
                                 'referer': self.request.META.get('HTTP_REFERER', ''),
                                 'user_ip': self.request.META.get('REMOTE_ADDR', ''),
                                 'user_agent': self.request.META.get('HTTP_USER_AGENT', '') }
                if akismet_api.comment_check(smart_str(self.cleaned_data['body']), data=akismet_data, build_data=True):
                    raise forms.ValidationError(u"Akismet thinks this message is spam")
        return self.cleaned_data['body']
<|endoftext|>


<commit_before>"""
View which can render and send email from a contact form.

"""

from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.auth.views import redirect_to_login

from contact_form.forms import ContactForm

def contact_form(request, form_class=ContactForm,
                 template_name='contact_form/contact_form.html',
                 success_url='/contact/sent/', login_required=False,
                 fail_silently=False):
    """
    Renders a contact form, validates its input and sends an email
    from it.

    To specify the form class to use, pass the ``form_class`` keyword
    argument; if no ``form_class`` is specified, the base
    ``ContactForm`` class will be used.

    To specify the template to use for rendering the form (*not* the
    template used to render the email message sent from the form,
    which is handled by the form class), pass the ``template_name``
    keyword argument; if not supplied, this will default to
    ``contact_form/contact_form.html``.

    To specify a URL to redirect to after a successfully-sent message,
    pass the ``success_url`` keyword argument; if not supplied, this
    will default to ``/contact/sent/``.

    To allow only registered users to use the form, pass a ``True``
    value for the ``login_required`` keyword argument.

    To suppress exceptions raised during sending of the email, pass a
    ``True`` value for the ``fail_silently`` keyword argument. This is
    **not** recommended.

    Template::

        Passed in the ``template_name`` argument.

    Context::

        form
            The form instance.

    """
    if login_required and not request.user.is_authenticated():
        return redirect_to_login(request.path)

    if request.method == 'POST':
        form = form_class(data=request.POST, request=request)
        if form.is_valid():
            form.save(fail_silently=fail_silently)
            return HttpResponseRedirect(success_url)
    else:
        form = form_class(request=request)
    return render_to_response(template_name,
                              { 'form': form },
                              context_instance=RequestContext(request))
<commit_msg>Make files available to contact form<commit_after>"""
View which can render and send email from a contact form.

"""

from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.auth.views import redirect_to_login

from contact_form.forms import ContactForm

def contact_form(request, form_class=ContactForm,
                 template_name='contact_form/contact_form.html',
                 success_url='/contact/sent/', login_required=False,
                 fail_silently=False):
    """
    Renders a contact form, validates its input and sends an email
    from it.

    To specify the form class to use, pass the ``form_class`` keyword
    argument; if no ``form_class`` is specified, the base
    ``ContactForm`` class will be used.

    To specify the template to use for rendering the form (*not* the
    template used to render the email message sent from the form,
    which is handled by the form class), pass the ``template_name``
    keyword argument; if not supplied, this will default to
    ``contact_form/contact_form.html``.

    To specify a URL to redirect to after a successfully-sent message,
    pass the ``success_url`` keyword argument; if not supplied, this
    will default to ``/contact/sent/``.

    To allow only registered users to use the form, pass a ``True``
    value for the ``login_required`` keyword argument.

    To suppress exceptions raised during sending of the email, pass a
    ``True`` value for the ``fail_silently`` keyword argument. This is
    **not** recommended.

    Template::

        Passed in the ``template_name`` argument.

    Context::

        form
            The form instance.

    """
    if login_required and not request.user.is_authenticated():
        return redirect_to_login(request.path)

    if request.method == 'POST':
        form = form_class(data=request.POST, files=request.FILES, request=request)
        if form.is_valid():
            form.save(fail_silently=fail_silently)
            return HttpResponseRedirect(success_url)
    else:
        form = form_class(request=request)
    return render_to_response(template_name,
                              { 'form': form },
                              context_instance=RequestContext(request))
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
@authors: R. Sanchez-Martin / C. Zambaldi / D. Mercier
"""

from base import Proc

class Indenter(Proc):
    '''Abaqus file writer for Indenter geometries.
    '''
    #def __init__(self):
    #    pass

    def procIndenterModel(self,
                          modelname='indenter',
                          h_indent=0.20,
                          D_sample=None, geo='conical',
                          sample_rep=24, # 24, 48
                          Dexp=None,
                          twoDimensional=False):
        coneAngle = 120.
        h_indent = 0.25
        tipRadius = 1.6

        # create dictionary of parameters
        self.IndentParameters = {
            'coneAngle': coneAngle,
            'coneHalfAngle': coneAngle / 2.,
            #'friction':friction,
            'h_indent': h_indent, # indentation depth
            #'sample_rep':sample_rep,
            'tipRadius': tipRadius,
            #'D_sample':D_sample, # not yet implemented, governed by h_indent
            #'ind_time':ind_time, # in seconds, since dotgamma_0 is in perSecond
            #'dwell_time':dwell_time, # time at maximum load
            'Dexp': Dexp, # experimental remaining indent diameter
            'indAxis': 'z', # however, indDirection is -z
            '2D': twoDimensional} #2D model flag
        if twoDimensional: self.IndentParameters['indAxis'] = 'y'
        print(repr(self.IndentParameters))
        self.proc = []
        self.start(title='INDENTER-MODEL (%s)' % modelname)
        self.procNewModel()
        self.procIndenter()
        self.proc.append('''
''')
        if geo == 'conical':
            self.procIndenterConical(coneHalfAngle=self.IndentParameters['coneHalfAngle'])
        savename = modelname
        #savename=modelname+'_fric%.1f'%self.IndentParameters['friction']
        if geo == 'conical':
            savename += '_R%.2f' % self.IndentParameters['tipRadius']
            savename += '_cA%.1f' % self.IndentParameters['coneAngle']
        savename += '_h%.3f' % self.IndentParameters['h_indent']
        self.procSaveModel(modelname=savename + '.mfd')
        #self.procMicronbar(posXYZ=N.array([0., 0., 0.]),height=h_indent)
        if Dexp is not None:
            self.procExpIndent(D=Dexp, Z=h_indent)
            #self.proc.append('*save_as_model %s yes'%(savename+'.mfd'))
        self.procfilename = savename + '.proc'
        #self.print_commands(self.proc,filename=)
        #self.define_post_vars()

    def procIndenter(self):# geo={berko # cc # conical}):
        self.proc.append('''
#+++++++++++++++++++++++++++++++++++++++++++++
# INDENTER-MODELING
#+++++++++++++++++++++++++++++++++++++++++++++
''')

    def procIndenterConical(self,
                            coneHalfAngle=45,
                            tipRadius=0.1,
                            geo=None):
        if geo != None:
            if geo == 'berkovich':
                coneHalfAngle = 90 - 19.7
            if geo == 'cubecorner':
                coneHalfAngle = 90 - 47.72
        self.proc.append('''
#+++++++++++++++++++++++++++++++++++++++++++++
# PARAMETERS FOR THE CONICAL INDENTER
#+++++++++++++++++++++++++++++++++++++++++++++
coneAngle = %f''' % (coneHalfAngle) + ''' # full angle of the conical tip at the apex in degrees
h_indent = %f''' % (self.IndentParameters['h_indent']) + ''' # indentation depth
tipRadius = %f''' % (self.IndentParameters['tipRadius']) +  ''' # radius of spherical tip'''
# 3000 mikroN for Berkovich geometry in TiAl
#*define indenter_ang 90-70.3  # 19.7, Standard Berkovich A=24.5*h**2
#*define indenter_ang 90-70.3   # 19.7, equ. to Modified Berkovich A=24.5033*h**2
#*define indenter_ang 90-42.28  # 47.72, equ. to Cube Corner A=2.598*h**2
'''
#+++++++++++++++++++++++++++++++++++++++++++++
# CONICAL INDENTER-MODELING
#+++++++++++++++++++++++++++++++++++++++++++++
# 3D analytical rigid indenter

Sketch_indenter = model_name.ConstrainedSketch(name='__profile__',
    sheetSize=sheet_Size)
g, v, d, c = Sketch_indenter.geometry, Sketch_indenter.vertices, Sketch_indenter.dimensions, Sketch_indenter.constraints

s = Sketch_indenter

Sketch_indenter.setPrimaryObject(option=STANDALONE)
Sketch_indenter.ConstructionLine(point1=(0.0, -100.0), point2=(0.0, 100.0))
Sketch_indenter.FixedConstraint(entity=g[2])

coneAngle = coneAngle*math.pi/180

# Spherical part
r = tipRadius
y_trans = r*(1-sin(coneAngle))
x_trans = r*cos(coneAngle)
Sketch_indenter.ArcByCenterEnds(center=(0.0, r), point1=(x_trans , y_trans), point2=(0.0, 0.0),
    direction=CLOCKWISE)

# Conical part
h_con_part = 1.3*h_indent
x_2 = x_trans + (h_con_part*sin(coneAngle)/cos(coneAngle))
y_2 = y_trans + h_con_part
Sketch_indenter.Line(point1=(x_trans , y_trans), point2=(x_2, y_2))

# Definition of the three-dimensional part
Indenter = model_name.Part(name='indenter', dimensionality=THREE_D,
    type=ANALYTIC_RIGID_SURFACE)
Indenter = model_name.parts['indenter']

# Symmetry of revolution

Indenter.AnalyticRigidSurfRevolve(sketch=Sketch_indenter)
Sketch_indenter.unsetPrimaryObject()
Indenter = model_name.parts['indenter']
session.viewports['Viewport: 1'].setValues(displayedObject=Indenter)
del model_name.sketches['__profile__']

# Creating instance and positioning the indenter

Indenter = model_name.parts['indenter']
session.viewports['Viewport: 1'].setValues(displayedObject=Indenter)
InstanceRoot = model_name.rootAssembly
session.viewports['Viewport: 1'].setValues(displayedObject=InstanceRoot)
InstanceRoot = model_name.rootAssembly
p = model_name.parts['indenter']
InstanceRoot.Instance(name='indenter-1', part=Indenter, dependent=ON)
InstanceRoot = model_name.rootAssembly
InstanceRoot.rotate(instanceList=('indenter-1', ), axisPoint=(10.0, 0.0, 0.0),
    axisDirection=(-20.0, 0.0, 0.0), angle=-90.0)

InstanceRoot.translate(instanceList=('indenter-1', ), vector=(0.0, 0.0, sep_ind_samp))

### Surface of the conical indenter

InstanceRoot = model_name.rootAssembly
faces_indenter = InstanceRoot.instances['indenter-1'].faces
d = tipRadius/tan(coneAngle)
r = tipRadius
x_coor = r*cos(coneAngle)
y_coor = 0
z_coor = r*(1-sin(coneAngle))+sep_ind_samp
side1Faces1 = faces_indenter.findAt(((0, 0, sep_ind_samp), ), ((x_coor, y_coor, z_coor), ))
InstanceRoot.Surface(side1Faces=side1Faces1, name='Surf Indenter')
'''
)
    def procIndenterFlatPunch(self, tipRadius=0.1):
        self.proc.append('''
#+++++++++++++++++++++++++++++++++++++++++++++
# PARAMETERS FOR FLAT PUNCH INDENTER
#+++++++++++++++++++++++++++++++++++++++++++++

h_indent = %f''' % (self.IndentParameters['h_indent']) + ''' # indentation depth
tipRadius = %f''' % (self.IndentParameters['tipRadius']) +  ''' # radius of spherical tip'''

'''

#+++++++++++++++++++++++++++++++++++++++++++++
# MODELING OF FLAT PUNCH INDENTER
#+++++++++++++++++++++++++++++++++++++++++++++

s = model_name.ConstrainedSketch(
    name='__profile__', sheetSize=sheet_Size)
g, v, d, c = s.geometry, s.vertices, s.dimensions, s.constraints
s.setPrimaryObject(option=STANDALONE)
s.ConstructionLine(point1=(0.0, -sheet_Size*0.5), point2=(0.0, sheet_Size*0.5))
s.Line(point1=(0.0, 0.0), point2=(tipRadius, 0.0))
s.Line(point1=(tipRadius, 0.0), point2=(tipRadius, h_indent*2.0))
s.Line(point1=(tipRadius, h_indent*2.0), point2=(0.0, h_indent*2.0))
s.FilletByRadius(radius=0.1*tipRadius, curve1=g.findAt((tipRadius*0.5, 0.0)), nearPoint1=(
    0.9*tipRadius, 0.0), curve2=g.findAt((tipRadius, h_indent)),
    nearPoint2=(tipRadius,0.1*tipRadius))
p = model_name.Part(name='indenter', dimensionality=THREE_D,
    type=ANALYTIC_RIGID_SURFACE)
p = model_name.parts['indenter']
p.AnalyticRigidSurfRevolve(sketch=s)
s.unsetPrimaryObject()
p = model_name.parts['indenter']
session.viewports['Viewport: 1'].setValues(displayedObject=p)
del model_name.sketches['__profile__']

# Creating instance and positioning the indenter

Indenter = model_name.parts['indenter']
session.viewports['Viewport: 1'].setValues(displayedObject=Indenter)
InstanceRoot = model_name.rootAssembly
session.viewports['Viewport: 1'].setValues(displayedObject=InstanceRoot)
InstanceRoot = model_name.rootAssembly
p = model_name.parts['indenter']
InstanceRoot.Instance(name='indenter-1', part=Indenter, dependent=ON)
InstanceRoot = model_name.rootAssembly
InstanceRoot.rotate(instanceList=('indenter-1', ), axisPoint=(10.0, 0.0, 0.0),
    axisDirection=(-20.0, 0.0, 0.0), angle=-90.0)

InstanceRoot.translate(instanceList=('indenter-1', ), vector=(0.0, 0.0, sep_ind_samp))

### Surface of the flat punch

InstanceRoot = model_name.rootAssembly
faces_indenter = InstanceRoot.instances['indenter-1'].faces
r = tipRadius
x_coor = r*0.5
y_coor = 0
z_coor = sep_ind_samp
side1Faces1 = faces_indenter.findAt(((0, 0, sep_ind_samp), ), ((x_coor, y_coor, z_coor), ))
InstanceRoot.Surface(side1Faces=side1Faces1, name='Surf Indenter')
''')

    def procIndenterCustomizedTopo(self, free_mesh_inp):
        self.proc.append('''
#+++++++++++++++++++++++++++++++++++++++++++++
# MODELING OF FREE TOPOGRAPHY OF INDENTER
#+++++++++++++++++++++++++++++++++++++++++++++
''')
    def procIndenterDeformable(self):
        self.proc.append('''
''')<commit_msg>cleaned code in indenter.py for Abaqus<commit_after># -*- coding: utf-8 -*-
"""
@authors: R. Sanchez-Martin / C. Zambaldi / D. Mercier
"""

from base import Proc

class Indenter(Proc):
    '''Abaqus file writer for Indenter geometries.
    '''
    #def __init__(self):
    #    pass

    def procIndenterModel(self,
                          modelname='indenter',
                          h_indent=0.20,
                          D_sample=None, geo='conical',
                          sample_rep=24, # 24, 48
                          Dexp=None,
                          twoDimensional=False):
        coneAngle = 120.
        h_indent = 0.25
        tipRadius = 1.6

        # create dictionary of parameters
        self.IndentParameters = {
            'coneAngle': coneAngle,
            'coneHalfAngle': coneAngle / 2.,
            #'friction':friction,
            'h_indent': h_indent, # indentation depth
            #'sample_rep':sample_rep,
            'tipRadius': tipRadius,
            #'D_sample':D_sample, # not yet implemented, governed by h_indent
            #'ind_time':ind_time, # in seconds, since dotgamma_0 is in perSecond
            #'dwell_time':dwell_time, # time at maximum load
            'Dexp': Dexp, # experimental remaining indent diameter
            'indAxis': 'z', # however, indDirection is -z
            '2D': twoDimensional} #2D model flag
        if twoDimensional: self.IndentParameters['indAxis'] = 'y'
        print(repr(self.IndentParameters))
        self.proc = []
        self.start(title='INDENTER-MODEL (%s)' % modelname)
        self.procNewModel()
        self.procIndenter()
        self.proc.append('''
''')
        if geo == 'conical':
            self.procIndenterConical(coneHalfAngle=self.IndentParameters['coneHalfAngle'])
        savename = modelname
        #savename=modelname+'_fric%.1f'%self.IndentParameters['friction']
        if geo == 'conical':
            savename += '_R%.2f' % self.IndentParameters['tipRadius']
            savename += '_cA%.1f' % self.IndentParameters['coneAngle']
        savename += '_h%.3f' % self.IndentParameters['h_indent']
        self.procSaveModel(modelname=savename + '.mfd')
        #self.procMicronbar(posXYZ=N.array([0., 0., 0.]),height=h_indent)
        if Dexp is not None:
            self.procExpIndent(D=Dexp, Z=h_indent)
            #self.proc.append('*save_as_model %s yes'%(savename+'.mfd'))
        self.procfilename = savename + '.proc'
        #self.print_commands(self.proc,filename=)
        #self.define_post_vars()

    def procIndenter(self):# geo={berko # cc # conical}):
        self.proc.append('''
#+++++++++++++++++++++++++++++++++++++++++++++
# INDENTER-MODELING
#+++++++++++++++++++++++++++++++++++++++++++++
''')

    def procIndenterConical(self,
                            coneHalfAngle=45,
                            tipRadius=0.1,
                            geo=None):
        if geo != None:
            if geo == 'berkovich':
                coneHalfAngle = 90 - 19.7
            if geo == 'cubecorner':
                coneHalfAngle = 90 - 47.72
        self.proc.append('''
#+++++++++++++++++++++++++++++++++++++++++++++
# PARAMETERS FOR THE CONICAL INDENTER
#+++++++++++++++++++++++++++++++++++++++++++++
coneAngle = %f''' % (coneHalfAngle) + ''' # full angle of the conical tip at the apex in degrees
h_indent = %f''' % (self.IndentParameters['h_indent']) + ''' # indentation depth
tipRadius = %f''' % (self.IndentParameters['tipRadius']) +  ''' # radius of spherical tip'''
# 3000 mikroN for Berkovich geometry in TiAl
#*define indenter_ang 90-70.3  # 19.7, Standard Berkovich A=24.5*h**2
#*define indenter_ang 90-70.3   # 19.7, equ. to Modified Berkovich A=24.5033*h**2
#*define indenter_ang 90-42.28  # 47.72, equ. to Cube Corner A=2.598*h**2
'''
#+++++++++++++++++++++++++++++++++++++++++++++
# CONICAL INDENTER-MODELING
#+++++++++++++++++++++++++++++++++++++++++++++
# 3D analytical rigid indenter
Sketch_indenter = model_name.ConstrainedSketch(name='__profile__', sheetSize=sheet_Size)
g, v, d, c = Sketch_indenter.geometry, Sketch_indenter.vertices, Sketch_indenter.dimensions, Sketch_indenter.constraints

s = Sketch_indenter

Sketch_indenter.setPrimaryObject(option=STANDALONE)
Sketch_indenter.ConstructionLine(point1=(0.0, -100.0), point2=(0.0, 100.0))
Sketch_indenter.FixedConstraint(entity=g[2])

coneAngle = coneAngle*math.pi/180

# Spherical part
r = tipRadius
y_trans = r*(1-sin(coneAngle))
x_trans = r*cos(coneAngle)
Sketch_indenter.ArcByCenterEnds(center=(0.0, r), point1=(x_trans , y_trans), point2=(0.0, 0.0),
    direction=CLOCKWISE)

# Conical part
h_con_part = 1.3*h_indent
x_2 = x_trans + (h_con_part*sin(coneAngle)/cos(coneAngle))
y_2 = y_trans + h_con_part
Sketch_indenter.Line(point1=(x_trans , y_trans), point2=(x_2, y_2))

# Definition of the three-dimensional part
Indenter = model_name.Part(name='indenter', dimensionality=THREE_D, type=ANALYTIC_RIGID_SURFACE)
Indenter = model_name.parts['indenter']

# Symmetry of revolution
Indenter.AnalyticRigidSurfRevolve(sketch=Sketch_indenter)
Sketch_indenter.unsetPrimaryObject()
Indenter = model_name.parts['indenter']
session.viewports['Viewport: 1'].setValues(displayedObject=Indenter)
del model_name.sketches['__profile__']

# Creating instance and positioning the indenter
Indenter = model_name.parts['indenter']
session.viewports['Viewport: 1'].setValues(displayedObject=Indenter)
InstanceRoot = model_name.rootAssembly
session.viewports['Viewport: 1'].setValues(displayedObject=InstanceRoot)
InstanceRoot = model_name.rootAssembly
p = model_name.parts['indenter']
InstanceRoot.Instance(name='indenter-1', part=Indenter, dependent=ON)
InstanceRoot = model_name.rootAssembly
InstanceRoot.rotate(instanceList=('indenter-1', ), axisPoint=(10.0, 0.0, 0.0),
    axisDirection=(-20.0, 0.0, 0.0), angle=-90.0)

InstanceRoot.translate(instanceList=('indenter-1', ), vector=(0.0, 0.0, sep_ind_samp))

# Surface of the conical indenter
InstanceRoot = model_name.rootAssembly
faces_indenter = InstanceRoot.instances['indenter-1'].faces
d = tipRadius/tan(coneAngle)
r = tipRadius
x_coor = r*cos(coneAngle)
y_coor = 0
z_coor = r*(1-sin(coneAngle))+sep_ind_samp
side1Faces1 = faces_indenter.findAt(((0, 0, sep_ind_samp), ), ((x_coor, y_coor, z_coor), ))
InstanceRoot.Surface(side1Faces=side1Faces1, name='Surf Indenter')
''')

    def procIndenterFlatPunch(self, tipRadius=0.1):
        self.proc.append('''
#+++++++++++++++++++++++++++++++++++++++++++++
# PARAMETERS FOR FLAT PUNCH INDENTER
#+++++++++++++++++++++++++++++++++++++++++++++

h_indent = %f''' % (self.IndentParameters['h_indent']) + ''' # indentation depth
tipRadius = %f''' % (self.IndentParameters['tipRadius']) +  ''' # radius of spherical tip

#+++++++++++++++++++++++++++++++++++++++++++++
# MODELING OF FLAT PUNCH INDENTER
#+++++++++++++++++++++++++++++++++++++++++++++

s = model_name.ConstrainedSketch(name='__profile__', sheetSize=sheet_Size)
g, v, d, c = s.geometry, s.vertices, s.dimensions, s.constraints
s.setPrimaryObject(option=STANDALONE)
s.ConstructionLine(point1=(0.0, -sheet_Size*0.5), point2=(0.0, sheet_Size*0.5))
s.Line(point1=(0.0, 0.0), point2=(tipRadius, 0.0))
s.Line(point1=(tipRadius, 0.0), point2=(tipRadius, h_indent*2.0))
s.Line(point1=(tipRadius, h_indent*2.0), point2=(0.0, h_indent*2.0))
s.FilletByRadius(radius=0.1*tipRadius, curve1=g.findAt((tipRadius*0.5, 0.0)), nearPoint1=(
    0.9*tipRadius, 0.0), curve2=g.findAt((tipRadius, h_indent)),
    nearPoint2=(tipRadius,0.1*tipRadius))
p = model_name.Part(name='indenter', dimensionality=THREE_D, type=ANALYTIC_RIGID_SURFACE)
p = model_name.parts['indenter']
p.AnalyticRigidSurfRevolve(sketch=s)
s.unsetPrimaryObject()
p = model_name.parts['indenter']
session.viewports['Viewport: 1'].setValues(displayedObject=p)
del model_name.sketches['__profile__']

# Creating instance and positioning the indenter
Indenter = model_name.parts['indenter']
session.viewports['Viewport: 1'].setValues(displayedObject=Indenter)
InstanceRoot = model_name.rootAssembly
session.viewports['Viewport: 1'].setValues(displayedObject=InstanceRoot)
InstanceRoot = model_name.rootAssembly
p = model_name.parts['indenter']
InstanceRoot.Instance(name='indenter-1', part=Indenter, dependent=ON)
InstanceRoot = model_name.rootAssembly
InstanceRoot.rotate(instanceList=('indenter-1', ), axisPoint=(10.0, 0.0, 0.0),
    axisDirection=(-20.0, 0.0, 0.0), angle=-90.0)

InstanceRoot.translate(instanceList=('indenter-1', ), vector=(0.0, 0.0, sep_ind_samp))

# Surface of the flat punch
InstanceRoot = model_name.rootAssembly
faces_indenter = InstanceRoot.instances['indenter-1'].faces
r = tipRadius
x_coor = r*0.5
y_coor = 0
z_coor = sep_ind_samp
side1Faces1 = faces_indenter.findAt(((0, 0, sep_ind_samp), ), ((x_coor, y_coor, z_coor), ))
InstanceRoot.Surface(side1Faces=side1Faces1, name='Surf Indenter')
''')

    def procIndenterCustomizedTopo(self, free_mesh_inp):
        self.proc.append('''
#+++++++++++++++++++++++++++++++++++++++++++++
# MODELING OF FREE TOPOGRAPHY OF INDENTER
#+++++++++++++++++++++++++++++++++++++++++++++
''')
    def procIndenterDeformable(self):
        self.proc.append('''
''')<|endoftext|>


<commit_before># Author: Braedy Kuzma

from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
import uuid
from dash.models import Post
from .serializers import PostSerializer

# Initially taken from
# http://www.django-rest-framework.org/tutorial/1-serialization/
class JSONResponse(HttpResponse):
    """
    An HttpResponse that renders its content into JSON.
    """
    def __init__(self, data, **kwargs):
        content = JSONRenderer().render(data)
        kwargs['content_type'] = 'application/json'
        super(JSONResponse, self).__init__(content, **kwargs)

@csrf_exempt
def post(request, pid=None):
    """
    REST view of Post.

    pid = Post id (uuid4)
    """
    try:
        uuid.UUID(pid)
    except ValueError:
        return HttpResponse(status=500) # Bad uuid = malformed client request

    try:
        post = Post.objects.get(id=pid)
    except Post.DoesNotExist:
        return HttpResponse(status=404)

    if request.method == 'GET':
        serializer = PostSerializer(post)
        return JSONResponse(serializer.data)
    elif request.method == 'DELETE':
        post.delete()
        return HttpResponse(status=204)
<commit_msg>Add multiple objects returned error.<commit_after># Author: Braedy Kuzma

from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
import uuid
from dash.models import Post
from .serializers import PostSerializer

# Initially taken from
# http://www.django-rest-framework.org/tutorial/1-serialization/
class JSONResponse(HttpResponse):
    """
    An HttpResponse that renders its content into JSON.
    """
    def __init__(self, data, **kwargs):
        content = JSONRenderer().render(data)
        kwargs['content_type'] = 'application/json'
        super(JSONResponse, self).__init__(content, **kwargs)

@csrf_exempt
def post(request, pid=None):
    """
    REST view of Post.

    pid = Post id (uuid4)
    """
    try:
        uuid.UUID(pid)
    except ValueError:
        return HttpResponse(status=500) # Bad uuid = malformed client request

    try:
        post = Post.objects.get(id=pid)
    except Post.DoesNotExist:
        return HttpResponse(status=404)
    except Post.MultipleObjectsReturned:
        return HttpResponse(status=500) # Some how the UUID matched multiple
                                        # posts

    if request.method == 'GET':
        serializer = PostSerializer(post)
        return JSONResponse(serializer.data)
    elif request.method == 'DELETE':
        post.delete()
        return HttpResponse(status=204)
<|endoftext|>


<commit_before>from corehq.apps.app_manager import id_strings
from corehq.apps.app_manager.models import ReportModule, ReportGraphConfig
from corehq.apps.app_manager import models
from corehq.apps.app_manager.suite_xml.xml_models import Locale, Text, Command, Entry, \
    SessionDatum, Detail, Header, Field, Template, Series, ConfigurationGroup, \
    ConfigurationItem, GraphTemplate, Graph, Xpath
from corehq.util.quickcache import quickcache

@quickcache(['report_module.unique_id'])
def _load_reports(report_module):
    if not report_module._loaded:
        # load reports in bulk to avoid hitting the database for each one
        for i, report in enumerate(report_module.reports):
            report_module.report_configs[i]._report = report
    report_module._loaded = True

class ReportModuleSuiteHelper(object):
    def __init__(self, report_module):
        assert isinstance(report_module, ReportModule)
        self.report_module = report_module
        self._loaded = None

    def get_details(self):
        _load_reports(self.report_module)
        for config in self.report_module.report_configs:
            yield (_get_select_detail_id(config), _get_select_details(config), True)
            yield (_get_summary_detail_id(config), _get_summary_details(config), True)

    def get_custom_entries(self):
        _load_reports(self.report_module)
        for config in self.report_module.report_configs:
            yield _get_config_entry(config)

def _get_config_entry(config):
    return Entry(
        command=Command(
            id='reports.{}'.format(config.uuid),
            text=Text(
                locale=Locale(id=id_strings.report_name(config.uuid)),
            ),
        ),
        datums=[
            SessionDatum(
                detail_confirm=_get_summary_detail_id(config),
                detail_select=_get_select_detail_id(config),
                id='report_id_{}'.format(config.uuid),
                nodeset="instance('reports')/reports/report[@id='{}']".format(config.uuid),
                value='./@id',
            ),
        ]
    )

def _get_select_detail_id(config):
    return 'reports.{}.select'.format(config.uuid)

def _get_summary_detail_id(config):
    return 'reports.{}.summary'.format(config.uuid)

def _get_select_details(config):
    return models.Detail(custom_xml=Detail(
        id='reports.{}.select'.format(config.uuid),
        title=Text(
            locale=Locale(id=id_strings.report_menu()),
        ),
        fields=[
            Field(
                header=Header(
                    text=Text(
                        locale=Locale(id=id_strings.report_name_header()),
                    )
                ),
                template=Template(
                    text=Text(
                        locale=Locale(id=id_strings.report_name(config.uuid))
                    )
                ),
            )
        ]
    ).serialize())

def _get_summary_details(config):
    def _get_graph_fields():
        from corehq.apps.userreports.reports.specs import MultibarChartSpec
        # todo: make this less hard-coded
        for chart_config in config.report.charts:
            if isinstance(chart_config, MultibarChartSpec):
                graph_config = config.graph_configs.get(chart_config.chart_id, ReportGraphConfig())

                def _column_to_series(column):
                    return Series(
                        nodeset="instance('reports')/reports/report[@id='{}']/rows/row".format(config.uuid),
                        x_function="column[@id='{}']".format(chart_config.x_axis_column),
                        y_function="column[@id='{}']".format(column),
                        configuration=ConfigurationGroup(configs=[
                            ConfigurationItem(id=key, xpath_function=value)
                            for key, value in graph_config.series_configs.get(column, {}).items()
                        ])
                    )
                yield Field(
                    header=Header(text=Text()),
                    template=GraphTemplate(
                        form='graph',
                        graph=Graph(
                            type=graph_config.graph_type,
                            series=[_column_to_series(c.column_id) for c in chart_config.y_axis_columns],
                            configuration=ConfigurationGroup(configs=[
                                ConfigurationItem(id=key, xpath_function=value)
                                for key, value in graph_config.config.items()
                            ]),
                        ),
                    )
                )

    return models.Detail(custom_xml=Detail(
        id='reports.{}.summary'.format(config.uuid),
        title=Text(
            locale=Locale(id=id_strings.report_menu()),
        ),
        details=[
            Detail(
                title=Text(
                    locale=Locale(id=id_strings.report_menu()),
                ),
                fields=[
                    Field(
                        header=Header(
                            text=Text(
                                locale=Locale(id=id_strings.report_name_header())
                            )
                        ),
                        template=Template(
                            text=Text(
                                locale=Locale(id=id_strings.report_name(config.uuid))
                            )
                        ),
                    ),
                    Field(
                        header=Header(
                            text=Text(
                                locale=Locale(id=id_strings.report_description_header()),
                            )
                        ),
                        template=Template(
                            text=Text(
                                xpath=Xpath(function=config.description)
                            )
                        ),
                    ),
                ] + [
                    Field(
                        header=Header(
                            text=Text(
                                locale=Locale(id=id_strings.report_last_sync())
                            )
                        ),
                        template=Template(
                            text=Text(
                                xpath=Xpath(
                                    function="format-date(date(instance('reports')/reports/@last_sync), '%Y-%m-%d %H:%M')"
                                )
                            )
                        )
                    ),
                ] + list(_get_graph_fields()),
            ),
            _get_data_detail(config),
        ],
    ).serialize())

def _get_data_detail(config):
    def _column_to_field(column):
        return Field(
            header=Header(
                text=Text(
                    locale=Locale(
                        id=id_strings.report_column_header(config.uuid, column.column_id)
                    ),
                )
            ),
            template=Template(
                text=Text(
                    xpath=Xpath(function="column[@id='{}']".format(column.column_id)))
            ),
        )

    return Detail(
        id='reports.{}.data'.format(config.uuid),
        nodeset='rows/row',
        title=Text(
            locale=Locale(id=id_strings.report_data_table()),
        ),
        fields=[_column_to_field(c) for c in config.report.report_columns]
    )
<commit_msg>make app_manager.ReportFiltersSuiteTest.test_data_detail pass<commit_after>from corehq.apps.app_manager import id_strings
from corehq.apps.app_manager.models import ReportModule, ReportGraphConfig, \
    MobileSelectFilter
from corehq.apps.app_manager import models
from corehq.apps.app_manager.suite_xml.xml_models import Locale, Text, Command, Entry, \
    SessionDatum, Detail, Header, Field, Template, Series, ConfigurationGroup, \
    ConfigurationItem, GraphTemplate, Graph, Xpath
from corehq.util.quickcache import quickcache

@quickcache(['report_module.unique_id'])
def _load_reports(report_module):
    if not report_module._loaded:
        # load reports in bulk to avoid hitting the database for each one
        for i, report in enumerate(report_module.reports):
            report_module.report_configs[i]._report = report
    report_module._loaded = True

class ReportModuleSuiteHelper(object):
    def __init__(self, report_module):
        assert isinstance(report_module, ReportModule)
        self.report_module = report_module
        self._loaded = None

    def get_details(self):
        _load_reports(self.report_module)
        for config in self.report_module.report_configs:
            yield (_get_select_detail_id(config), _get_select_details(config), True)
            yield (_get_summary_detail_id(config), _get_summary_details(config), True)

    def get_custom_entries(self):
        _load_reports(self.report_module)
        for config in self.report_module.report_configs:
            yield _get_config_entry(config)

def _get_config_entry(config):
    return Entry(
        command=Command(
            id='reports.{}'.format(config.uuid),
            text=Text(
                locale=Locale(id=id_strings.report_name(config.uuid)),
            ),
        ),
        datums=[
            SessionDatum(
                detail_confirm=_get_summary_detail_id(config),
                detail_select=_get_select_detail_id(config),
                id='report_id_{}'.format(config.uuid),
                nodeset="instance('reports')/reports/report[@id='{}']".format(config.uuid),
                value='./@id',
            ),
        ]
    )

def _get_select_detail_id(config):
    return 'reports.{}.select'.format(config.uuid)

def _get_summary_detail_id(config):
    return 'reports.{}.summary'.format(config.uuid)

def _get_select_details(config):
    return models.Detail(custom_xml=Detail(
        id='reports.{}.select'.format(config.uuid),
        title=Text(
            locale=Locale(id=id_strings.report_menu()),
        ),
        fields=[
            Field(
                header=Header(
                    text=Text(
                        locale=Locale(id=id_strings.report_name_header()),
                    )
                ),
                template=Template(
                    text=Text(
                        locale=Locale(id=id_strings.report_name(config.uuid))
                    )
                ),
            )
        ]
    ).serialize())

def _get_summary_details(config):
    def _get_graph_fields():
        from corehq.apps.userreports.reports.specs import MultibarChartSpec
        # todo: make this less hard-coded
        for chart_config in config.report.charts:
            if isinstance(chart_config, MultibarChartSpec):
                graph_config = config.graph_configs.get(chart_config.chart_id, ReportGraphConfig())

                def _column_to_series(column):
                    return Series(
                        nodeset="instance('reports')/reports/report[@id='{}']/rows/row".format(config.uuid),
                        x_function="column[@id='{}']".format(chart_config.x_axis_column),
                        y_function="column[@id='{}']".format(column),
                        configuration=ConfigurationGroup(configs=[
                            ConfigurationItem(id=key, xpath_function=value)
                            for key, value in graph_config.series_configs.get(column, {}).items()
                        ])
                    )
                yield Field(
                    header=Header(text=Text()),
                    template=GraphTemplate(
                        form='graph',
                        graph=Graph(
                            type=graph_config.graph_type,
                            series=[_column_to_series(c.column_id) for c in chart_config.y_axis_columns],
                            configuration=ConfigurationGroup(configs=[
                                ConfigurationItem(id=key, xpath_function=value)
                                for key, value in graph_config.config.items()
                            ]),
                        ),
                    )
                )

    return models.Detail(custom_xml=Detail(
        id='reports.{}.summary'.format(config.uuid),
        title=Text(
            locale=Locale(id=id_strings.report_menu()),
        ),
        details=[
            Detail(
                title=Text(
                    locale=Locale(id=id_strings.report_menu()),
                ),
                fields=[
                    Field(
                        header=Header(
                            text=Text(
                                locale=Locale(id=id_strings.report_name_header())
                            )
                        ),
                        template=Template(
                            text=Text(
                                locale=Locale(id=id_strings.report_name(config.uuid))
                            )
                        ),
                    ),
                    Field(
                        header=Header(
                            text=Text(
                                locale=Locale(id=id_strings.report_description_header()),
                            )
                        ),
                        template=Template(
                            text=Text(
                                xpath=Xpath(function=config.description)
                            )
                        ),
                    ),
                ] + [
                    Field(
                        header=Header(
                            text=Text(
                                locale=Locale(id=id_strings.report_last_sync())
                            )
                        ),
                        template=Template(
                            text=Text(
                                xpath=Xpath(
                                    function="format-date(date(instance('reports')/reports/@last_sync), '%Y-%m-%d %H:%M')"
                                )
                            )
                        )
                    ),
                ] + list(_get_graph_fields()),
            ),
            _get_data_detail(config),
        ],
    ).serialize())

def _get_data_detail(config):
    def _column_to_field(column):
        return Field(
            header=Header(
                text=Text(
                    locale=Locale(
                        id=id_strings.report_column_header(config.uuid, column.column_id)
                    ),
                )
            ),
            template=Template(
                text=Text(
                    xpath=Xpath(function="column[@id='{}']".format(column.column_id)))
            ),
        )

    return Detail(
        id='reports.{}.data'.format(config.uuid),
        nodeset='rows/row{}'.format(_data_filter_xpath(config)),
        title=Text(
            locale=Locale(id=id_strings.report_data_table()),
        ),
        fields=[_column_to_field(c) for c in config.report.report_columns]
    )

def _data_filter_xpath(config):
    mobile_select_filters = [(slug, f) for slug, f in config.filters.items()
                             if isinstance(f, MobileSelectFilter)]
    return ''.join([
        "[column[@id='{column_id}']=instance('commcaresession')/session/data/{datum_id}]".format(
            column_id=config.report.get_ui_filter(slug).field,
            datum_id=_mobile_select_filter_datum_id(config, slug))
        for slug, f in mobile_select_filters])

def _mobile_select_filter_datum_id(config, filter_slug):
    return 'report_filter_{report_id}_{column_id}'.format(
        report_id=config.uuid, column_id=filter_slug)
<|endoftext|>


<commit_before>from __future__ import absolute_import
from __future__ import unicode_literals

import uuid

from couchdbkit import ResourceNotFound
from django.test import SimpleTestCase, TestCase
from mock import patch

from corehq.apps.app_manager.models import Module
from corehq.apps.app_manager.tests.app_factory import AppFactory
from corehq.apps.app_manager.tests.util import TestXmlMixin

class ReleaseFormsSetupMixin(object):
    def set_up_app(self):
        self.factory = AppFactory(build_version='2.30.0')
        training_module = self.factory.app.add_module(Module.new_training_module('training module', None))
        self.releases_form = self.factory.app.new_form(training_module.id, "Untitled Form", None)
        self.releases_form.is_release_notes_form=True
        self.releases_form.xmlns = "http://openrosa.org/formdesigner/{}".format(uuid.uuid4().hex)
        basic_module, self.basic_form = self.factory.new_basic_module("basic_module", "doctor", with_form=True)
        self.basic_form.xmlns = "http://openrosa.org/formdesigner/{}".format(uuid.uuid4().hex)

class ReleaseFormsEnabledTest(SimpleTestCase, ReleaseFormsSetupMixin, TestXmlMixin):

    def setUp(self):
        self.set_up_app()
        self.releases_form.enable_release_notes = True
        super(ReleaseFormsEnabledTest, self).setUp()

    def test_resource(self):
        # release form should be as xform-update-info
        suite = self.factory.app.create_suite()
        xpath = "./xform-update-info"
        expected = """
            <partial>
              <xform-update-info>
                <resource id="{id}" descriptor="Form: (Module training module) - Untitled Form">
                  <location authority="local">./modules-0/forms-0.xml</location>
                  <location authority="remote">./modules-0/forms-0.xml</location>
                </resource>
              </xform-update-info>
            </partial>
        """.format(id=self.releases_form.unique_id)
        self.assertXmlPartialEqual(expected, suite, xpath)
        # normal form should be still under xform
        xpath = "./xform"
        expected = """
            <partial>
              <xform>
                <resource id="basic_module_form_0" descriptor="Form: (Module basic_module module) - basic_module form 0">
                  <location authority="local">./modules-1/forms-0.xml</location>
                  <location authority="remote">./modules-1/forms-0.xml</location>
                </resource>
              </xform>
            </partial>
        """
        # not included in resource
        self.assertXmlPartialEqual(expected, suite, xpath)

    def test_entry(self):
        suite = self.factory.app.create_suite()
        expected = """
            <partial>
              <entry>
                <form>{release_xmlns}</form>
                <command id="m0-f0">
                  <text>
                    <locale id="forms.m0f0"/>
                  </text>
                </command>
              </entry>
              <entry>
                <form>{basic_xmlns}</form>
                <command id="m1-f0">
                  <text>
                    <locale id="forms.m1f0"/>
                  </text>
                </command>
              </entry>
            </partial>
        """.format(
            release_xmlns=self.releases_form.xmlns,
            basic_xmlns=self.basic_form.xmlns)
        # check entry exists
        self.assertXmlPartialEqual(expected, suite, "./entry")

    def test_command(self):
        # check command in suite/menu exists
        suite = self.factory.app.create_suite()
        expected = """
        <partial>
            <menu id="m0" root="training-root" >
              <text>
                <locale id="modules.m0"/>
              </text>
              <command id="m0-f0"/>
            </menu>
            <menu id="m1">
              <text>
                <locale id="modules.m1"/>
              </text>
              <command id="m1-f0"/>
            </menu>
            <menu id="training-root">
              <text>
                <locale id="training.root.title"/>
              </text>
            </menu>
        </partial>
        """
        self.assertXmlPartialEqual(expected, suite, "./menu")

class ReleaseFormsDisabledTest(SimpleTestCase, ReleaseFormsSetupMixin, TestXmlMixin):

    def setUp(self):
        self.set_up_app()
        # Todo: if there is the training module has only one releases_form and it is disabled
        #   should menus related to that module be included? and should we treat as if that module
        #   exists or not, what happens to m0, m1 etc?
        self.releases_form.enable_release_notes = False
        super(ReleaseFormsDisabledTest, self).setUp()

    def test_resource(self):
        # release form should be as xform-update-info
        suite = self.factory.app.create_suite()
        xpath = "./xform-update-info"
        self.assertXmlDoesNotHaveXpath(suite, xpath)
        expected = """
            <partial>
              <xform>
                <resource id="basic_module_form_0" descriptor="Form: (Module basic_module module) - basic_module form 0">
                  <location authority="local">./modules-1/forms-0.xml</location>
                  <location authority="remote">./modules-1/forms-0.xml</location>
                </resource>
              </xform>
            </partial>
        """
        self.assertXmlPartialEqual(expected, suite, './xform')

    def test_entry(self):
        suite = self.factory.app.create_suite()
        expected = """
            <partial>
              <entry>
                <form>{basic_xmlns}</form>
                <command id="m1-f0">
                  <text>
                    <locale id="forms.m1f0"/>
                  </text>
                </command>
              </entry>
            </partial>
        """.format(
            basic_xmlns=self.basic_form.xmlns)
        # check entry exists
        self.assertXmlPartialEqual(expected, suite, "./entry")

    def test_command(self):
        # check command in suite/menu exists
        suite = self.factory.app.create_suite()
        # todo: get the correct spec in case there is only one disabled release form
        expected = """
        <partial>
            <menu id="m1">
              <text>
                <locale id="modules.m1"/>
              </text>
              <command id="m1-f0"/>
            </menu>
            <menu id="training-root">
              <text>
                <locale id="training.root.title"/>
              </text>
            </menu>
        </partial>
        """
        self.assertXmlPartialEqual(expected, suite, "./menu")

class ReleaseNotesResourceFileTest(TestCase, ReleaseFormsSetupMixin, TestXmlMixin):
    file_path = ('data',)

    def setUp(self):
        self.set_up_app()
        self.releases_form.source = self.get_xml('very_simple_form')
        self.basic_form.source = self.get_xml('very_simple_form')
        self.factory.app.save()

        super(ReleaseNotesResourceFileTest, self).setUp()

    @patch('corehq.apps.app_manager.models.FormBase.is_a_disabled_release_form', return_value=False)
    def test_enabled(self, mock):
        # check form in resource files
        self.factory.app.create_build_files(save=True)
        copy = self.factory.app.make_build()
        copy.save()
        self.assertTrue(copy.lazy_fetch_attachment('files/modules-0/forms-0.xml'))

    @patch('corehq.apps.app_manager.models.FormBase.is_a_disabled_release_form', return_value=True)
    def test_disabled(self, mock):
        self.factory.app.create_build_files(save=True)
        copy = self.factory.app.make_build()
        copy.save()
        with self.assertRaises(ResourceNotFound):
            self.assertTrue(copy.lazy_fetch_attachment('files/modules-0/forms-0.xml'))
<commit_msg>validate_form in tests<commit_after>from __future__ import absolute_import
from __future__ import unicode_literals

import uuid

from couchdbkit import ResourceNotFound
from django.test import SimpleTestCase, TestCase
from mock import patch

from corehq.apps.app_manager.models import Module
from corehq.apps.app_manager.tests.app_factory import AppFactory
from corehq.apps.app_manager.tests.util import TestXmlMixin

class ReleaseFormsSetupMixin(object):
    def set_up_app(self):
        self.factory = AppFactory(build_version='2.30.0')
        training_module = self.factory.app.add_module(Module.new_training_module('training module', None))
        self.releases_form = self.factory.app.new_form(training_module.id, "Untitled Form", None)
        self.releases_form.is_release_notes_form=True
        self.releases_form.xmlns = "http://openrosa.org/formdesigner/{}".format(uuid.uuid4().hex)
        basic_module, self.basic_form = self.factory.new_basic_module("basic_module", "doctor", with_form=True)
        self.basic_form.xmlns = "http://openrosa.org/formdesigner/{}".format(uuid.uuid4().hex)

class ReleaseFormsEnabledTest(SimpleTestCase, ReleaseFormsSetupMixin, TestXmlMixin):

    def setUp(self):
        self.set_up_app()
        self.releases_form.enable_release_notes = True
        super(ReleaseFormsEnabledTest, self).setUp()

    def test_resource(self):
        # release form should be as xform-update-info
        suite = self.factory.app.create_suite()
        xpath = "./xform-update-info"
        expected = """
            <partial>
              <xform-update-info>
                <resource id="{id}" descriptor="Form: (Module training module) - Untitled Form">
                  <location authority="local">./modules-0/forms-0.xml</location>
                  <location authority="remote">./modules-0/forms-0.xml</location>
                </resource>
              </xform-update-info>
            </partial>
        """.format(id=self.releases_form.unique_id)
        self.assertXmlPartialEqual(expected, suite, xpath)
        # normal form should be still under xform
        xpath = "./xform"
        expected = """
            <partial>
              <xform>
                <resource id="basic_module_form_0" descriptor="Form: (Module basic_module module) - basic_module form 0">
                  <location authority="local">./modules-1/forms-0.xml</location>
                  <location authority="remote">./modules-1/forms-0.xml</location>
                </resource>
              </xform>
            </partial>
        """
        # not included in resource
        self.assertXmlPartialEqual(expected, suite, xpath)

    def test_entry(self):
        suite = self.factory.app.create_suite()
        expected = """
            <partial>
              <entry>
                <form>{release_xmlns}</form>
                <command id="m0-f0">
                  <text>
                    <locale id="forms.m0f0"/>
                  </text>
                </command>
              </entry>
              <entry>
                <form>{basic_xmlns}</form>
                <command id="m1-f0">
                  <text>
                    <locale id="forms.m1f0"/>
                  </text>
                </command>
              </entry>
            </partial>
        """.format(
            release_xmlns=self.releases_form.xmlns,
            basic_xmlns=self.basic_form.xmlns)
        # check entry exists
        self.assertXmlPartialEqual(expected, suite, "./entry")

    def test_command(self):
        # check command in suite/menu exists
        suite = self.factory.app.create_suite()
        expected = """
        <partial>
            <menu id="m0" root="training-root" >
              <text>
                <locale id="modules.m0"/>
              </text>
              <command id="m0-f0"/>
            </menu>
            <menu id="m1">
              <text>
                <locale id="modules.m1"/>
              </text>
              <command id="m1-f0"/>
            </menu>
            <menu id="training-root">
              <text>
                <locale id="training.root.title"/>
              </text>
            </menu>
        </partial>
        """
        self.assertXmlPartialEqual(expected, suite, "./menu")

class ReleaseFormsDisabledTest(SimpleTestCase, ReleaseFormsSetupMixin, TestXmlMixin):

    def setUp(self):
        self.set_up_app()
        # Todo: if there is the training module has only one releases_form and it is disabled
        #   should menus related to that module be included? and should we treat as if that module
        #   exists or not, what happens to m0, m1 etc?
        self.releases_form.enable_release_notes = False
        super(ReleaseFormsDisabledTest, self).setUp()

    def test_resource(self):
        # release form should be as xform-update-info
        suite = self.factory.app.create_suite()
        xpath = "./xform-update-info"
        self.assertXmlDoesNotHaveXpath(suite, xpath)
        expected = """
            <partial>
              <xform>
                <resource id="basic_module_form_0" descriptor="Form: (Module basic_module module) - basic_module form 0">
                  <location authority="local">./modules-1/forms-0.xml</location>
                  <location authority="remote">./modules-1/forms-0.xml</location>
                </resource>
              </xform>
            </partial>
        """
        self.assertXmlPartialEqual(expected, suite, './xform')

    def test_entry(self):
        suite = self.factory.app.create_suite()
        expected = """
            <partial>
              <entry>
                <form>{basic_xmlns}</form>
                <command id="m1-f0">
                  <text>
                    <locale id="forms.m1f0"/>
                  </text>
                </command>
              </entry>
            </partial>
        """.format(
            basic_xmlns=self.basic_form.xmlns)
        # check entry exists
        self.assertXmlPartialEqual(expected, suite, "./entry")

    def test_command(self):
        # check command in suite/menu exists
        suite = self.factory.app.create_suite()
        # todo: get the correct spec in case there is only one disabled release form
        expected = """
        <partial>
            <menu id="m1">
              <text>
                <locale id="modules.m1"/>
              </text>
              <command id="m1-f0"/>
            </menu>
            <menu id="training-root">
              <text>
                <locale id="training.root.title"/>
              </text>
            </menu>
        </partial>
        """
        self.assertXmlPartialEqual(expected, suite, "./menu")

class ReleaseNotesResourceFileTest(TestCase, ReleaseFormsSetupMixin, TestXmlMixin):
    file_path = ('data',)

    def setUp(self):
        self.set_up_app()
        self.releases_form.source = self.get_xml('very_simple_form')
        self.basic_form.source = self.get_xml('very_simple_form')
        self.factory.app.save()

        super(ReleaseNotesResourceFileTest, self).setUp()

    @patch('corehq.apps.app_manager.models.validate_xform', return_value=None)
    @patch('corehq.apps.app_manager.models.FormBase.is_a_disabled_release_form', return_value=False)
    def test_enabled(self, mock1, mock2):
        # check form in resource files
        self.factory.app.create_build_files(save=True)
        copy = self.factory.app.make_build()
        copy.save()
        self.assertTrue(copy.lazy_fetch_attachment('files/modules-0/forms-0.xml'))

    @patch('corehq.apps.app_manager.models.validate_xform', return_value=None)
    @patch('corehq.apps.app_manager.models.FormBase.is_a_disabled_release_form', return_value=True)
    def test_disabled(self, mock1, mock2):
        self.factory.app.create_build_files(save=True)
        copy = self.factory.app.make_build()
        copy.save()
        with self.assertRaises(ResourceNotFound):
            self.assertTrue(copy.lazy_fetch_attachment('files/modules-0/forms-0.xml'))
<|endoftext|>