<commit_before># coding: utf-8

from __future__ import unicode_literals
import logging

from mkdocs.structure.pages import Page
from mkdocs.utils import string_types, nest_paths

log = logging.getLogger(__name__)

class Navigation(object):
    def __init__(self, items, pages):
        self.items = items  # Nested List with full navigation of Sections, Pages, and Links.
        self.pages = pages  # Flat List of subset of Pages in nav, in order.

        self.homepage = None
        for page in pages:
            if page.is_homepage:
                self.homepage = page
                break

    def __repr__(self):
        return '\n'.join([item._indent_print() for item in self])

    def __iter__(self):
        return iter(self.items)

    def __len__(self):
        return len(self.items)

class Section(object):
    def __init__(self, title, children):
        self.title = title
        self.children = children

        self.parent = None
        self.active = False

        self.is_section = True
        self.is_page = False
        self.is_link = False

    def __repr__(self):
        return "Section(title='{0}')".format(self.title)

    def _get_active(self):
        """ Return active status of section. """
        return self.__active

    def _set_active(self, value):
        """ Set active status of section and ancestors. """
        self.__active = bool(value)
        if self.parent is not None:
            self.parent.active = bool(value)

    active = property(_get_active, _set_active)

    @property
    def ancestors(self):
        if self.parent is None:
            return []
        return [self.parent] + self.parent.ancestors

    def _indent_print(self, depth=0):
        ret = ['{}{}'.format('    ' * depth, repr(self))]
        for item in self.children:
            ret.append(item._indent_print(depth + 1))
        return '\n'.join(ret)

class Link(object):
    def __init__(self, title, url):
        self.title = title
        self.url = url
        self.parent = None

        # These should never change but are included for consistency with sections and pages.
        self.children = None
        self.active = False
        self.is_section = False
        self.is_page = False
        self.is_link = True

    def __repr__(self):
        title = "'{}'".format(self.title) if (self.title is not None) else '[blank]'
        return "Link(title={}, url='{}')".format(title, self.url)

    @property
    def ancestors(self):
        if self.parent is None:
            return []
        return [self.parent] + self.parent.ancestors

    def _indent_print(self, depth=0):
        return '{}{}'.format('    ' * depth, repr(self))

def get_navigation(files, config):
    """ Build site navigation from config and files."""
    nav_config = config['nav'] or nest_paths(f.src_path for f in files.documentation_pages())
    items = _data_to_navigation(nav_config, files, config)
    if not isinstance(items, list):
        items = [items]

    # Get only the pages from the navigation, ignoring any sections and links.
    pages = _get_by_type(items, Page)

    # Include next, previous and parent links.
    _add_previous_and_next_links(pages)
    _add_parent_links(items)

    missing_from_config = [file for file in files.documentation_pages() if file.page is None]
    if missing_from_config:
        log.info(
            'The following pages exist in the docs directory, but are not '
            'included in the "nav" configuration:\n  - {}'.format(
                '\n  - '.join([file.src_path for file in missing_from_config]))
        )
        # Any documentation files not found in the nav should still have an associated page.
        # However, these page objects are only accessable from File instances as `file.page`.
        for file in missing_from_config:
            Page(None, file, config)

    links = _get_by_type(items, Link)
    if links:
        # Assume all links are external.
        # TODO: warn or error on internal links?
        log.info(
            'The following paths are included in the "nav" configuration, '
            'but do not exist in the docs directory:\n  - {}'.format(
                '\n  - '.join([link.url for link in links]))
        )
    return Navigation(items, pages)

def _data_to_navigation(data, files, config):
    if isinstance(data, dict):
        return [
            _data_to_navigation((key, value), files, config)
            if isinstance(value, string_types) else
            Section(title=key, children=_data_to_navigation(value, files, config))
            for key, value in data.items()
        ]
    elif isinstance(data, list):
        return [
            _data_to_navigation(item, files, config)[0]
            if isinstance(item, dict) and len(item) == 1 else
            _data_to_navigation(item, files, config)
            for item in data
        ]
    title, path = data if isinstance(data, tuple) else (None, data)
    file = files.get_file_from_path(path)
    if file:
        return Page(title, file, config)
    return Link(title, path)

def _get_by_type(nav, T):
    ret = []
    for item in nav:
        if isinstance(item, T):
            ret.append(item)
        elif item.children:
            ret.extend(_get_by_type(item.children, T))
    return ret

def _add_parent_links(nav):
    for item in nav:
        if item.is_section:
            for child in item.children:
                child.parent = item
            _add_parent_links(item.children)

def _add_previous_and_next_links(pages):
    bookended = [None] + pages + [None]
    zipped = zip(bookended[:-2], bookended[1:-1], bookended[2:])
    for page0, page1, page2 in zipped:
        page1.previous_page, page1.next_page = page0, page2
<commit_msg>Use DEBUG log level for external links in nav.<commit_after># coding: utf-8

from __future__ import unicode_literals
import logging

from mkdocs.structure.pages import Page
from mkdocs.utils import string_types, nest_paths

log = logging.getLogger(__name__)

class Navigation(object):
    def __init__(self, items, pages):
        self.items = items  # Nested List with full navigation of Sections, Pages, and Links.
        self.pages = pages  # Flat List of subset of Pages in nav, in order.

        self.homepage = None
        for page in pages:
            if page.is_homepage:
                self.homepage = page
                break

    def __repr__(self):
        return '\n'.join([item._indent_print() for item in self])

    def __iter__(self):
        return iter(self.items)

    def __len__(self):
        return len(self.items)

class Section(object):
    def __init__(self, title, children):
        self.title = title
        self.children = children

        self.parent = None
        self.active = False

        self.is_section = True
        self.is_page = False
        self.is_link = False

    def __repr__(self):
        return "Section(title='{0}')".format(self.title)

    def _get_active(self):
        """ Return active status of section. """
        return self.__active

    def _set_active(self, value):
        """ Set active status of section and ancestors. """
        self.__active = bool(value)
        if self.parent is not None:
            self.parent.active = bool(value)

    active = property(_get_active, _set_active)

    @property
    def ancestors(self):
        if self.parent is None:
            return []
        return [self.parent] + self.parent.ancestors

    def _indent_print(self, depth=0):
        ret = ['{}{}'.format('    ' * depth, repr(self))]
        for item in self.children:
            ret.append(item._indent_print(depth + 1))
        return '\n'.join(ret)

class Link(object):
    def __init__(self, title, url):
        self.title = title
        self.url = url
        self.parent = None

        # These should never change but are included for consistency with sections and pages.
        self.children = None
        self.active = False
        self.is_section = False
        self.is_page = False
        self.is_link = True

    def __repr__(self):
        title = "'{}'".format(self.title) if (self.title is not None) else '[blank]'
        return "Link(title={}, url='{}')".format(title, self.url)

    @property
    def ancestors(self):
        if self.parent is None:
            return []
        return [self.parent] + self.parent.ancestors

    def _indent_print(self, depth=0):
        return '{}{}'.format('    ' * depth, repr(self))

def get_navigation(files, config):
    """ Build site navigation from config and files."""
    nav_config = config['nav'] or nest_paths(f.src_path for f in files.documentation_pages())
    items = _data_to_navigation(nav_config, files, config)
    if not isinstance(items, list):
        items = [items]

    # Get only the pages from the navigation, ignoring any sections and links.
    pages = _get_by_type(items, Page)

    # Include next, previous and parent links.
    _add_previous_and_next_links(pages)
    _add_parent_links(items)

    missing_from_config = [file for file in files.documentation_pages() if file.page is None]
    if missing_from_config:
        log.info(
            'The following pages exist in the docs directory, but are not '
            'included in the "nav" configuration:\n  - {}'.format(
                '\n  - '.join([file.src_path for file in missing_from_config]))
        )
        # Any documentation files not found in the nav should still have an associated page.
        # However, these page objects are only accessable from File instances as `file.page`.
        for file in missing_from_config:
            Page(None, file, config)

    links = _get_by_type(items, Link)
    if links:
        # Assume all links are external.
        log.debug(
            'The following paths are included in the "nav" configuration, '
            'but do not exist in the docs directory:\n  - {}'.format(
                '\n  - '.join([link.url for link in links]))
        )
    return Navigation(items, pages)

def _data_to_navigation(data, files, config):
    if isinstance(data, dict):
        return [
            _data_to_navigation((key, value), files, config)
            if isinstance(value, string_types) else
            Section(title=key, children=_data_to_navigation(value, files, config))
            for key, value in data.items()
        ]
    elif isinstance(data, list):
        return [
            _data_to_navigation(item, files, config)[0]
            if isinstance(item, dict) and len(item) == 1 else
            _data_to_navigation(item, files, config)
            for item in data
        ]
    title, path = data if isinstance(data, tuple) else (None, data)
    file = files.get_file_from_path(path)
    if file:
        return Page(title, file, config)
    return Link(title, path)

def _get_by_type(nav, T):
    ret = []
    for item in nav:
        if isinstance(item, T):
            ret.append(item)
        elif item.children:
            ret.extend(_get_by_type(item.children, T))
    return ret

def _add_parent_links(nav):
    for item in nav:
        if item.is_section:
            for child in item.children:
                child.parent = item
            _add_parent_links(item.children)

def _add_previous_and_next_links(pages):
    bookended = [None] + pages + [None]
    zipped = zip(bookended[:-2], bookended[1:-1], bookended[2:])
    for page0, page1, page2 in zipped:
        page1.previous_page, page1.next_page = page0, page2
<|endoftext|>


<commit_before><commit_msg>nph plot<commit_after><|endoftext|>


<commit_before>"""
Models for Djax.
"""
from django.db import models
from django.contrib.contenttypes.models import ContentType
import logging
from datetime import datetime
from djax.gateway import content_client, library_client, library_project
from djax.registry import content_registry, build_registry
import re

log = logging.getLogger('djax')

class AxilentContentRecordManager(models.Manager):
    """
    Manager class for AxilentContentRecord.
    """
    def get_record(self,model):
        """
        Gets the record for the specified model.
        """
        content_type = ContentType.objects.get_for_model(model)
        return self.get(local_content_type=content_type,local_id=model.pk)

    def field_map(self,model,axilent_content={}):
        """
        Gets the field map for the model.
        """
        field_map = {}
        excludes = []

        # collect mappings
        if hasattr(model,'Axilent'):
            if hasattr(model.Axilent,'field_map'):
                field_map = model.Axilent.field_map

            if hasattr(model.Axilent,'exclude'):
                excludes = model.Axilent.exclude

        # Default the field map to the axilent fields
        if not field_map:
            for key in axilent_content.data.keys():
                if not key in excludes:
                    field_map[key] = key

        return field_map

    def create_model(self,axilent_content_type,axilent_content_key):
        """
        Creates a new model and accompaning content record for the axilent content.
        """
        content_data = content_client.get_content(axilent_content_type,axilent_content_key)
        model_class = content_registry[axilent_content_type]

        field_map = {}
        try:
            field_map = model_class.Axilent.field_map
        except AttributeError:
            for key in content_data.data.keys():
                field_map[key] = key

        fields = {}
        for axilent_field,model_field in field_map.items():
            try:
                fields[model_field] = content_data.data[axilent_field]
            except KeyError:
                pass

        local_model = model_class.objects.create(**fields) # create the local model with the content data
        local_content_type = ContentType.objects.get_for_model(local_model)
        record = self.create(local_content_type=local_content_type,
                             local_id=local_model.pk,
                             axilent_content_type=axilent_content_type,
                             axilent_content_key=axilent_content_key,
                             updated=datetime.now())

        return (local_model,record)

    def model_to_content_link(self,value):
        """
        Converts a local model (held as a foreign key reference) to an Axilent
        content link in <content-type>:<content-key> format.
        """
        if isinstance(value,models.Model):
            try:
                record = self.get_record(value)
                return '%s:%s' % (record.axilent_content_type,record.axilent_content_key)
            except AxilentContentRecord.DoesNotExist:
                return ''
        else:
            return value

    def content_link_to_model(self,value):
        """
        Converts a content link format string '<content-type>:<content-key>' to a local
        model to be used as a foreign key.
        """
        if re.match(r'^[\w\s]+:[A-Fa-f0-9]+$',value):
            ctype, ckey = value.split(':')
            record = self.get(axilent_content_type=ctype,axilent_content_key=ckey)
            return record.get_local_model()
        else:
            return value

    def data_for_library(self,model):
        """
        Gets a data dictionary prepared for the library.
        """
        lib_data = {}
        field_map = self.field_map(model)
        for axilent_field, model_field in field_map.items():
            try:
                lib_data[axilent_field] = self.model_to_content_link(getattr(model,model_field))
            except AttributeError:
                log.exception('Local model has no field %s (matched to Axilent field %s).' % (model_field,axilent_field))

        return lib_data

    def push_to_library(self,model):
        """
        Pushes the model to the Axilent library (assuming the library integration is active).

        Returns a 2-tuple of booleans indicating 1.  If the library was updated and 2. If the
        content item was created on Axilent for the first time.

        """
        if library_client:
            lib_data = self.data_for_library(model)
            try:
                record = self.get_record(model)
                # this content item already exists on Axilent - update
                response = library_client.update_content(record.axilent_content_type,
                                                         library_project,
                                                         record.axilent_content_key,
                                                         **lib_data)
                return (True,False)
            except AxilentContentRecord.DoesNotExist:
                # this is new
                local_content_type = ContentType.objects.get_for_model(model)
                axilent_content_type = model.Axilent.content_type
                response = library_client.create_content(axilent_content_type,
                                                         library_project,
                                                         **lib_data)
                returned_content_type, returned_key = response.split(':')

                # create new record
                self.create(local_content_type=local_content_type,
                            local_id=model.pk,
                            axilent_content_type=axilent_content_type,
                            axilent_content_key=returned_key)

                return (True,True)
        else:
            return (False,False)

class AxilentContentRecord(models.Model):
    """
    Mapping for a specific Axilent content item to a model.
    """
    local_content_type = models.ForeignKey(ContentType,related_name='axilent_content_records')
    local_id = models.IntegerField()
    axilent_content_type = models.CharField(max_length=100)
    axilent_content_key = models.CharField(max_length=100)
    updated = models.DateTimeField(null=True)

    objects = AxilentContentRecordManager()

    def update_available(self):
        """
        Determines if a new content update is available from Axilent.
        """
        if content_client.latest_update(self.axilent_content_type,self.axilent_content_key):
            return True
        else:
            return False

    def get_update(self):
        """
        Gets the updated content from Axilent.
        """
        return content_client.latest_update(self.axilent_content_type,self.axilent_content_key)

    def sync_content(self,axilent_content):
        """
        Syncs the local content to the incoming axilent content (a dictionary).
        """
        local_model = self.get_local_model()
        field_map = local_model.Axilent.field_map

        log.debug('syncing local model with Axilent content %s, using field map %s.' % (unicode(axilent_content),unicode(field_map)))

        # Iterate through the field map and set the local model values from the incoming Axilent content
        for axilent_field, model_field in field_map.items():
            try:
                value = getattr(axilent_content,axilent_field)
                setattr(local_model,model_field,self.objects.content_link_to_model(value))
                log.debug('settings local model attribute %s with value %s.' % (model_field,value))
            except AttributeError:
                log.exception('Local model has no field %s (matched to Axilent field %s).' % (model_field,axilent_field))

        local_model.save()
        self.updated = datetime.now()
        self.save()

        return local_model

    def get_local_model(self):
        """
        Gets the local model for this record.
        """
        return self.local_content_type.model_class().objects.get(pk=self.local_id)

    def archive(self):
        """
        Archives the content on Axilent.
        """
        return library_client.archive_content(library_project,self.axilent_content_type,self.axilent_content_key)

    class Meta:
        unique_together = (('local_content_type','local_id'),('axilent_content_type','axilent_content_key'))

class ContentSyncLock(models.Model):
    """
    Lock for a content sync.  Indicates a sync is under way.
    """
    token = models.CharField(max_length=100)

# =================
# = Registry Hook =
# =================
build_registry()<commit_msg>Fixing content update bug.<commit_after>"""
Models for Djax.
"""
from django.db import models
from django.contrib.contenttypes.models import ContentType
import logging
from datetime import datetime
from djax.gateway import content_client, library_client, library_project
from djax.registry import content_registry, build_registry
import re

log = logging.getLogger('djax')

class AxilentContentRecordManager(models.Manager):
    """
    Manager class for AxilentContentRecord.
    """
    def get_record(self,model):
        """
        Gets the record for the specified model.
        """
        content_type = ContentType.objects.get_for_model(model)
        return self.get(local_content_type=content_type,local_id=model.pk)

    def field_map(self,model,axilent_content={}):
        """
        Gets the field map for the model.
        """
        field_map = {}
        excludes = []

        # collect mappings
        if hasattr(model,'Axilent'):
            if hasattr(model.Axilent,'field_map'):
                field_map = model.Axilent.field_map

            if hasattr(model.Axilent,'exclude'):
                excludes = model.Axilent.exclude

        # Default the field map to the axilent fields
        if not field_map:
            for key in axilent_content.data.keys():
                if not key in excludes:
                    field_map[key] = key

        return field_map

    def create_model(self,axilent_content_type,axilent_content_key):
        """
        Creates a new model and accompaning content record for the axilent content.
        """
        content_data = content_client.get_content(axilent_content_type,axilent_content_key)
        model_class = content_registry[axilent_content_type]

        field_map = {}
        try:
            field_map = model_class.Axilent.field_map
        except AttributeError:
            for key in content_data.data.keys():
                field_map[key] = key

        fields = {}
        for axilent_field,model_field in field_map.items():
            try:
                fields[model_field] = content_data.data[axilent_field]
            except KeyError:
                pass

        local_model = model_class.objects.create(**fields) # create the local model with the content data
        local_content_type = ContentType.objects.get_for_model(local_model)
        record = self.create(local_content_type=local_content_type,
                             local_id=local_model.pk,
                             axilent_content_type=axilent_content_type,
                             axilent_content_key=axilent_content_key,
                             updated=datetime.now())

        return (local_model,record)

    def model_to_content_link(self,value):
        """
        Converts a local model (held as a foreign key reference) to an Axilent
        content link in <content-type>:<content-key> format.
        """
        if isinstance(value,models.Model):
            try:
                record = self.get_record(value)
                return '%s:%s' % (record.axilent_content_type,record.axilent_content_key)
            except AxilentContentRecord.DoesNotExist:
                return ''
        else:
            return value

    def content_link_to_model(self,value):
        """
        Converts a content link format string '<content-type>:<content-key>' to a local
        model to be used as a foreign key.
        """
        if re.match(r'^[\w\s]+:[A-Fa-f0-9]+$',value):
            ctype, ckey = value.split(':')
            record = self.get(axilent_content_type=ctype,axilent_content_key=ckey)
            return record.get_local_model()
        else:
            return value

    def data_for_library(self,model):
        """
        Gets a data dictionary prepared for the library.
        """
        lib_data = {}
        field_map = self.field_map(model)
        for axilent_field, model_field in field_map.items():
            try:
                lib_data[axilent_field] = self.model_to_content_link(getattr(model,model_field))
            except AttributeError:
                log.exception('Local model has no field %s (matched to Axilent field %s).' % (model_field,axilent_field))

        return lib_data

    def push_to_library(self,model):
        """
        Pushes the model to the Axilent library (assuming the library integration is active).

        Returns a 2-tuple of booleans indicating 1.  If the library was updated and 2. If the
        content item was created on Axilent for the first time.

        """
        if library_client:
            lib_data = self.data_for_library(model)
            try:
                record = self.get_record(model)
                # this content item already exists on Axilent - update
                response = library_client.update_content(record.axilent_content_type,
                                                         library_project,
                                                         record.axilent_content_key,
                                                         **lib_data)
                return (True,False)
            except AxilentContentRecord.DoesNotExist:
                # this is new
                local_content_type = ContentType.objects.get_for_model(model)
                axilent_content_type = model.Axilent.content_type
                response = library_client.create_content(axilent_content_type,
                                                         library_project,
                                                         **lib_data)
                returned_content_type, returned_key = response.split(':')

                # create new record
                self.create(local_content_type=local_content_type,
                            local_id=model.pk,
                            axilent_content_type=axilent_content_type,
                            axilent_content_key=returned_key)

                return (True,True)
        else:
            return (False,False)

class AxilentContentRecord(models.Model):
    """
    Mapping for a specific Axilent content item to a model.
    """
    local_content_type = models.ForeignKey(ContentType,related_name='axilent_content_records')
    local_id = models.IntegerField()
    axilent_content_type = models.CharField(max_length=100)
    axilent_content_key = models.CharField(max_length=100)
    updated = models.DateTimeField(null=True)

    objects = AxilentContentRecordManager()

    def update_available(self):
        """
        Determines if a new content update is available from Axilent.
        """
        if content_client.latest_update(self.axilent_content_type,self.axilent_content_key):
            return True
        else:
            return False

    def get_update(self):
        """
        Gets the updated content from Axilent.
        """
        latest = content_client.latest_update(self.axilent_content_type,self.axilent_content_key)
        if self.updated and self.updated >= latest:
            return None
        else:
            return content_client.get_content(self.axilent_content_type,self.axilent_content_key)

    def sync_content(self,axilent_content):
        """
        Syncs the local content to the incoming axilent content (a dictionary).
        """
        local_model = self.get_local_model()
        field_map = local_model.Axilent.field_map

        log.debug('syncing local model with Axilent content %s, using field map %s.' % (unicode(axilent_content),unicode(field_map)))

        # Iterate through the field map and set the local model values from the incoming Axilent content
        for axilent_field, model_field in field_map.items():
            try:
                value = getattr(axilent_content,axilent_field)
                setattr(local_model,model_field,self.objects.content_link_to_model(value))
                log.debug('settings local model attribute %s with value %s.' % (model_field,value))
            except AttributeError:
                log.exception('Local model has no field %s (matched to Axilent field %s).' % (model_field,axilent_field))

        local_model.save()
        self.updated = datetime.now()
        self.save()

        return local_model

    def get_local_model(self):
        """
        Gets the local model for this record.
        """
        return self.local_content_type.model_class().objects.get(pk=self.local_id)

    def archive(self):
        """
        Archives the content on Axilent.
        """
        return library_client.archive_content(library_project,self.axilent_content_type,self.axilent_content_key)

    class Meta:
        unique_together = (('local_content_type','local_id'),('axilent_content_type','axilent_content_key'))

class ContentSyncLock(models.Model):
    """
    Lock for a content sync.  Indicates a sync is under way.
    """
    token = models.CharField(max_length=100)

# =================
# = Registry Hook =
# =================
build_registry()<|endoftext|>


<commit_before>from django.core.urlresolvers import reverse
from django.db.models import Q
from django.http import HttpResponseRedirect, HttpResponseForbidden
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.template.defaultfilters import slugify
from django.views.generic.list_detail import object_list, object_detail
from django.views.generic.create_update import create_object, update_object
from djobs.forms import JobForm, ContactForm, LocationForm, EmployerForm
from djobs.models import Job, JobCategory, Employer, EmployerLogo, Location
import datetime

def category_jobs(request, slug, **kwargs):
    template_name = kwargs.get("template_name", "djobs/category_jobs.html")

    category = get_object_or_404(JobCategory, slug=slug)
    jobs = Job.active.filter(category=category)

    return object_list(request,
        queryset=jobs,
        allow_empty=True,
        template_name=template_name,
        extra_context={'category': category}
    )

def employer_detail(request, id, **kwargs):
    template_name = kwargs.get("template_name", "djobs/employer_detail.html")

    employer = get_object_or_404(Employer, pk=id)
    jobs = Job.active.filter(employer=employer)

    return object_list(request,
        queryset=jobs,
        allow_empty=True,
        template_name=template_name,
        extra_context={'employer': employer}
    )

def job_detail(request, id, **kwargs):
    template_name = kwargs.get("template_name", "djobs/job_detail.html")

    jobs = Job.active.all()

    return object_detail(request,
        queryset=jobs,
        object_id=id,
        template_name=template_name)

def manage(request, **kwargs):
    template_name = kwargs.get("template_name", "djobs/manage.html")

    jobs = Job.active.filter(employer__administrator=request.user)
    employers = Employer.objects.filter(administrator=request.user)

    return render_to_response(template_name, {
            'jobs': jobs,
            'employers': employers,
        }, context_instance=RequestContext(request)
    )

def create_job(request, **kwargs):
    """
    job creation
    """
    template_name = kwargs.get("template_name", "djobs/job_form.html")

    if request.method == 'POST':
        location_form = LocationForm(request.POST)

        if location_form.is_valid():
            location = location_form.save()

        contact_form = ContactForm(request.POST)

        if contact_form.is_valid():
            contact = contact_form.save()

        job_form = JobForm(request.POST)
        job_form.fields['employer'].queryset = job_form.fields['employer'].queryset.filter(administrator=request.user)

        if job_form.is_valid():
            title = job_form.cleaned_data['title']
            description = job_form.cleaned_data['description']
            category = job_form.cleaned_data['category']
            employment_type = job_form.cleaned_data['employment_type']
            employment_level = job_form.cleaned_data['employment_level']
            employer = job_form.cleaned_data['employer']

            new_job = Job.objects.create(title=title,
                description=description,
                category=category,
                employment_type=employment_type,
                employment_level=employment_level,
                employer=employer,
                location=location,
                contact=contact
            )

            return HttpResponseRedirect(reverse('djobs_job_detail',
                args=[new_job.id]
            ))
    else:
        job_form = JobForm()
        job_form.fields['employer'].queryset = job_form.fields['employer'].queryset.filter(administrator=request.user)

        location_form = LocationForm()
        contact_form = ContactForm()

    return render_to_response(template_name, {
            'job_form': job_form,
            'location_form': location_form,
            'contact_form': contact_form,
            'add': True,
        }, context_instance=RequestContext(request)
    )

def edit_job(request, job_id, **kwargs):
    """
    job editing
    """
    template_name = kwargs.get("template_name", "djobs/job_form.html")
    job = get_object_or_404(Job, pk=job_id)

    if request.user != job.employer.administrator:
        return HttpResponseForbidden()

    if request.method == 'POST':
        location_form = LocationForm(request.POST)

        if location_form.is_valid():
            job.location = location_form.save()

        contact_form = ContactForm(request.POST)

        if contact_form.is_valid():
            job.contact = contact_form.save()

        job_form = JobForm(request.POST)
        job_form.fields['employer'].queryset = job_form.fields['employer'].queryset.filter(administrator=request.user)

        if job_form.is_valid():
            job.title = job_form.cleaned_data['title']
            job.description = job_form.cleaned_data['description']
            job.category = job_form.cleaned_data['category']
            job.employment_type = job_form.cleaned_data['employment_type']
            job.employment_level = job_form.cleaned_data['employment_level']
            job.employer = job_form.cleaned_data['employer']

            job.save()

            return HttpResponseRedirect(reverse('djobs_job_detail',
                args=[job.id]
            ))
    else:
        job_form = JobForm({'title': job.title, 'description': job.description,
            'category': job.category.id,
            'employment_type': job.employment_type,
            'employment_level': job.employment_level,
            'employer': job.employer.id,
        })
        job_form.fields['employer'].queryset = job_form.fields['employer'].queryset.filter(administrator=request.user)

        location_form = LocationForm({'address': job.location.address,
            'city': job.location.city,
            'state': job.location.state,
            'zip': job.location.zip,
        })
        contact_form = ContactForm({'name': job.contact.name,
            'email': job.contact.email,
            'phone': job.contact.phone,
            'fax': job.contact.fax,
            'url': job.contact.url,
        })

    return render_to_response(template_name, {
            'job_form': job_form,
            'location_form': location_form,
            'contact_form': contact_form,
            'add': False,
        }, context_instance=RequestContext(request)
    )

def create_employer(request, **kwargs):
    """
    employer creation
    """
    template_name = kwargs.get("template_name", "djobs/employer_form.html")

    if request.method == 'POST':
        employer_form = EmployerForm(request.POST, request.FILES)

        if employer_form.is_valid():
            employer_name = employer_form.cleaned_data['name']
            profile = employer_form.cleaned_data['profile']
            logo = employer_form.cleaned_data['logo']

            new_employer_logo = EmployerLogo.objects.create(
                name="%s's logo" % employer_name,
                original_image=logo,
                caption="%s's logo" % employer_name,
            )

            new_employer = Employer.objects.create(
                name=employer_name,
                slug=slugify(employer_name),
                logo=new_employer_logo,
                profile=profile,
                administrator=request.user
            )

            return HttpResponseRedirect(reverse('djobs_employer_detail',
                args=[new_employer.id]
            ))
    else:
        employer_form = EmployerForm()

    return render_to_response(template_name, {
        'employer_form': employer_form,
        'add': True,
        }, context_instance=RequestContext(request)
    )

def edit_employer(request, employer_id, **kwargs):
    """
    employer editing/updating
    """
    template_name = kwargs.get("template_name", "djobs/employer_form.html")
    employer = get_object_or_404(Employer, pk=employer_id)

    if request.user != employer.administrator:
        return HttpResponseForbidden()

    if request.method == 'POST':
        employer_form = EmployerForm(request.POST)

        if employer_form.is_valid():
            employer.name = employer_form.cleaned_data['name']
            employer.profile = employer_form.cleaned_data['profile']

            if employer_form.cleaned_data['logo']:
                employer.logo = employer_form.cleaned_data['logo']
            elif employer.logo:
                employer.logo = employer.logo

            employer.save()

            return HttpResponseRedirect(reverse('djobs_employer_detail',
                args=[employer.id]
            ))
    else:
        employer_form = EmployerForm({'name': employer.name,
            'profile': employer.profile,
            'logo': employer.logo,
        })

    return render_to_response(template_name, {
            'employer_form': employer_form,
            'add': False,
        }, context_instance=RequestContext(request)
    )

def search(request, **kwargs):
    """
    keyword search on jobs and employers
    """
    template_name = kwargs.get("template_name", "djobs/search_results.html")

    search_query = request.GET.get("search", "")

    job_results = Job.objects.filter(
        Q(description__icontains=search_query) | Q(title__icontains=search_query)
    )

    employer_results = Employer.objects.filter(
        Q(name__icontains=search_query) | Q(profile__icontains=search_query)
    )

    return render_to_response(template_name, {
            'job_results': job_results,
            'employer_results': employer_results,
        }, context_instance=RequestContext(request)
    )<commit_msg>added search query context to search results<commit_after>from django.core.urlresolvers import reverse
from django.db.models import Q
from django.http import HttpResponseRedirect, HttpResponseForbidden
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.template.defaultfilters import slugify
from django.views.generic.list_detail import object_list, object_detail
from django.views.generic.create_update import create_object, update_object
from djobs.forms import JobForm, ContactForm, LocationForm, EmployerForm
from djobs.models import Job, JobCategory, Employer, EmployerLogo, Location
import datetime

def category_jobs(request, slug, **kwargs):
    template_name = kwargs.get("template_name", "djobs/category_jobs.html")

    category = get_object_or_404(JobCategory, slug=slug)
    jobs = Job.active.filter(category=category)

    return object_list(request,
        queryset=jobs,
        allow_empty=True,
        template_name=template_name,
        extra_context={'category': category}
    )

def employer_detail(request, id, **kwargs):
    template_name = kwargs.get("template_name", "djobs/employer_detail.html")

    employer = get_object_or_404(Employer, pk=id)
    jobs = Job.active.filter(employer=employer)

    return object_list(request,
        queryset=jobs,
        allow_empty=True,
        template_name=template_name,
        extra_context={'employer': employer}
    )

def job_detail(request, id, **kwargs):
    template_name = kwargs.get("template_name", "djobs/job_detail.html")

    jobs = Job.active.all()

    return object_detail(request,
        queryset=jobs,
        object_id=id,
        template_name=template_name)

def manage(request, **kwargs):
    template_name = kwargs.get("template_name", "djobs/manage.html")

    jobs = Job.active.filter(employer__administrator=request.user)
    employers = Employer.objects.filter(administrator=request.user)

    return render_to_response(template_name, {
            'jobs': jobs,
            'employers': employers,
        }, context_instance=RequestContext(request)
    )

def create_job(request, **kwargs):
    """
    job creation
    """
    template_name = kwargs.get("template_name", "djobs/job_form.html")

    if request.method == 'POST':
        location_form = LocationForm(request.POST)

        if location_form.is_valid():
            location = location_form.save()

        contact_form = ContactForm(request.POST)

        if contact_form.is_valid():
            contact = contact_form.save()

        job_form = JobForm(request.POST)
        job_form.fields['employer'].queryset = job_form.fields['employer'].queryset.filter(administrator=request.user)

        if job_form.is_valid():
            title = job_form.cleaned_data['title']
            description = job_form.cleaned_data['description']
            category = job_form.cleaned_data['category']
            employment_type = job_form.cleaned_data['employment_type']
            employment_level = job_form.cleaned_data['employment_level']
            employer = job_form.cleaned_data['employer']

            new_job = Job.objects.create(title=title,
                description=description,
                category=category,
                employment_type=employment_type,
                employment_level=employment_level,
                employer=employer,
                location=location,
                contact=contact
            )

            return HttpResponseRedirect(reverse('djobs_job_detail',
                args=[new_job.id]
            ))
    else:
        job_form = JobForm()
        job_form.fields['employer'].queryset = job_form.fields['employer'].queryset.filter(administrator=request.user)

        location_form = LocationForm()
        contact_form = ContactForm()

    return render_to_response(template_name, {
            'job_form': job_form,
            'location_form': location_form,
            'contact_form': contact_form,
            'add': True,
        }, context_instance=RequestContext(request)
    )

def edit_job(request, job_id, **kwargs):
    """
    job editing
    """
    template_name = kwargs.get("template_name", "djobs/job_form.html")
    job = get_object_or_404(Job, pk=job_id)

    if request.user != job.employer.administrator:
        return HttpResponseForbidden()

    if request.method == 'POST':
        location_form = LocationForm(request.POST)

        if location_form.is_valid():
            job.location = location_form.save()

        contact_form = ContactForm(request.POST)

        if contact_form.is_valid():
            job.contact = contact_form.save()

        job_form = JobForm(request.POST)
        job_form.fields['employer'].queryset = job_form.fields['employer'].queryset.filter(administrator=request.user)

        if job_form.is_valid():
            job.title = job_form.cleaned_data['title']
            job.description = job_form.cleaned_data['description']
            job.category = job_form.cleaned_data['category']
            job.employment_type = job_form.cleaned_data['employment_type']
            job.employment_level = job_form.cleaned_data['employment_level']
            job.employer = job_form.cleaned_data['employer']

            job.save()

            return HttpResponseRedirect(reverse('djobs_job_detail',
                args=[job.id]
            ))
    else:
        job_form = JobForm({'title': job.title, 'description': job.description,
            'category': job.category.id,
            'employment_type': job.employment_type,
            'employment_level': job.employment_level,
            'employer': job.employer.id,
        })
        job_form.fields['employer'].queryset = job_form.fields['employer'].queryset.filter(administrator=request.user)

        location_form = LocationForm({'address': job.location.address,
            'city': job.location.city,
            'state': job.location.state,
            'zip': job.location.zip,
        })
        contact_form = ContactForm({'name': job.contact.name,
            'email': job.contact.email,
            'phone': job.contact.phone,
            'fax': job.contact.fax,
            'url': job.contact.url,
        })

    return render_to_response(template_name, {
            'job_form': job_form,
            'location_form': location_form,
            'contact_form': contact_form,
            'add': False,
        }, context_instance=RequestContext(request)
    )

def create_employer(request, **kwargs):
    """
    employer creation
    """
    template_name = kwargs.get("template_name", "djobs/employer_form.html")

    if request.method == 'POST':
        employer_form = EmployerForm(request.POST, request.FILES)

        if employer_form.is_valid():
            employer_name = employer_form.cleaned_data['name']
            profile = employer_form.cleaned_data['profile']
            logo = employer_form.cleaned_data['logo']

            new_employer_logo = EmployerLogo.objects.create(
                name="%s's logo" % employer_name,
                original_image=logo,
                caption="%s's logo" % employer_name,
            )

            new_employer = Employer.objects.create(
                name=employer_name,
                slug=slugify(employer_name),
                logo=new_employer_logo,
                profile=profile,
                administrator=request.user
            )

            return HttpResponseRedirect(reverse('djobs_employer_detail',
                args=[new_employer.id]
            ))
    else:
        employer_form = EmployerForm()

    return render_to_response(template_name, {
        'employer_form': employer_form,
        'add': True,
        }, context_instance=RequestContext(request)
    )

def edit_employer(request, employer_id, **kwargs):
    """
    employer editing/updating
    """
    template_name = kwargs.get("template_name", "djobs/employer_form.html")
    employer = get_object_or_404(Employer, pk=employer_id)

    if request.user != employer.administrator:
        return HttpResponseForbidden()

    if request.method == 'POST':
        employer_form = EmployerForm(request.POST)

        if employer_form.is_valid():
            employer.name = employer_form.cleaned_data['name']
            employer.profile = employer_form.cleaned_data['profile']

            if employer_form.cleaned_data['logo']:
                employer.logo = employer_form.cleaned_data['logo']
            elif employer.logo:
                employer.logo = employer.logo

            employer.save()

            return HttpResponseRedirect(reverse('djobs_employer_detail',
                args=[employer.id]
            ))
    else:
        employer_form = EmployerForm({'name': employer.name,
            'profile': employer.profile,
            'logo': employer.logo,
        })

    return render_to_response(template_name, {
            'employer_form': employer_form,
            'add': False,
        }, context_instance=RequestContext(request)
    )

def search(request, **kwargs):
    """
    keyword search on jobs and employers
    """
    template_name = kwargs.get("template_name", "djobs/search_results.html")

    search_query = request.GET.get("search", "")

    job_results = Job.objects.filter(
        Q(description__icontains=search_query) | Q(title__icontains=search_query)
    )

    employer_results = Employer.objects.filter(
        Q(name__icontains=search_query) | Q(profile__icontains=search_query)
    )

    return render_to_response(template_name, {
            'search_query': search_query,
            'job_results': job_results,
            'employer_results': employer_results,
        }, context_instance=RequestContext(request)
    )<|endoftext|>


<commit_before>import logging
import textwrap

import numpy as np

from .las_items import HeaderItem, CurveItem, SectionItems, OrderedDict
from . import defaults
from . import exceptions

logger = logging.getLogger(__name__)

def write(
    las,
    file_object,
    version=None,
    wrap=None,
    STRT=None,
    STOP=None,
    STEP=None,
    fmt="%.5f",
    len_numeric_field=None,
    data_width=79,
    header_width=60,
):
    """Write a LAS files.

    Arguments:
        las (:class:`lasio.las.LASFile`)
        file_object (file-like object open for writing): output
        version (float or None): version of written file, either 1.2 or 2.
            If this is None, ``las.version.VERS.value`` will be used.
        wrap (bool or None): whether to wrap the output data section.
            If this is None, ``las.version.WRAP.value`` will be used.
        STRT (float or None): value to use as STRT (note the data will not
            be clipped). If this is None, the data value in the first column,
            first row will be used.
        STOP (float or None): value to use as STOP (note the data will not
            be clipped). If this is None, the data value in the first column,
            last row will be used.
        STEP (float or None): value to use as STEP (note the data will not
            be resampled and/or interpolated). If this is None, the STEP will
            be estimated from the first two rows of the first column.
        fmt (str): Python string formatting operator for numeric data to be
            used.
        len_numeric_field (int): width of each numeric field column (must be
            greater than than all the formatted numeric values in the file).
        data_width (79): width of data field in characters

    Creating an output file is not the only side-effect of this function. It
    will also modify the STRT, STOP and STEP HeaderItems so that they correctly
    reflect the ~Data section's units and the actual first, last, and interval
    values.

    You should avoid calling this function directly - instead use the
    :meth:`lasio.las.LASFile.write` method.

    """
    if wrap is None:
        wrap = las.version["WRAP"] == "YES"
    elif wrap is True:
        las.version["WRAP"] = HeaderItem(
            "WRAP", "", "YES", "Multiple lines per depth step"
        )
    elif wrap is False:
        las.version["WRAP"] = HeaderItem("WRAP", "", "NO", "One line per depth step")
    lines = []

    assert version in (1.2, 2, None)
    if version is None:
        version = las.version["VERS"].value
    if version == 1.2:
        las.version["VERS"] = HeaderItem(
            "VERS", "", 1.2, "CWLS LOG ASCII STANDARD - VERSION 1.2"
        )
    elif version == 2:
        las.version["VERS"] = HeaderItem(
            "VERS", "", 2.0, "CWLS log ASCII Standard -VERSION 2.0"
        )

    if STRT is None:
        STRT = las.index[0]
    if STOP is None:
        STOP = las.index[-1]
    if STEP is None:
        if STOP != STRT: #prevents an error being thrown in the case of only a single sample being written
            STEP = las.index[1] - las.index[0]  # Faster than np.gradient

    las.well["STRT"].value = STRT
    las.well["STOP"].value = STOP
    las.well["STEP"].value = STEP

    # Check units
    if las.curves[0].unit:
        unit = las.curves[0].unit
    else:
        unit = las.well["STRT"].unit
    las.well["STRT"].unit = unit
    las.well["STOP"].unit = unit
    las.well["STEP"].unit = unit
    las.curves[0].unit = unit

    # Write each section.
    # get_formatter_function ( ** get_section_widths )

    # ~Version
    logger.debug("LASFile.write Version section")
    lines.append("~Version ".ljust(header_width, "-"))
    order_func = get_section_order_function("Version", version)
    section_widths = get_section_widths("Version", las.version, version, order_func)
    for header_item in las.version.values():
        mnemonic = header_item.original_mnemonic
        # logger.debug('LASFile.write ' + str(header_item))
        order = order_func(mnemonic)
        # logger.debug('LASFile.write order = %s' % (order, ))
        logger.debug(
            "LASFile.write %s order=%s section_widths=%s"
            % (header_item, order, section_widths)
        )
        formatter_func = get_formatter_function(order, **section_widths)
        line = formatter_func(header_item)
        lines.append(line)

    # ~Well
    logger.debug("LASFile.write Well section")
    lines.append("~Well ".ljust(header_width, "-"))
    order_func = get_section_order_function("Well", version)
    section_widths = get_section_widths("Well", las.well, version, order_func)
    # logger.debug('LASFile.write well section_widths=%s' % section_widths)
    for header_item in las.well.values():
        mnemonic = header_item.original_mnemonic
        order = order_func(mnemonic)
        logger.debug(
            "LASFile.write %s order=%s section_widths=%s"
            % (header_item, order, section_widths)
        )
        formatter_func = get_formatter_function(order, **section_widths)
        line = formatter_func(header_item)
        lines.append(line)

    # ~Curves
    logger.debug("LASFile.write Curves section")
    lines.append("~Curve Information ".ljust(header_width, "-"))
    order_func = get_section_order_function("Curves", version)
    section_widths = get_section_widths("Curves", las.curves, version, order_func)
    for header_item in las.curves:
        mnemonic = header_item.original_mnemonic
        order = order_func(mnemonic)
        formatter_func = get_formatter_function(order, **section_widths)
        line = formatter_func(header_item)
        lines.append(line)

    # ~Params
    logger.debug("LASFile.write Params section")
    lines.append("~Params ".ljust(header_width, "-"))
    order_func = get_section_order_function("Parameter", version)
    section_widths = get_section_widths("Parameter", las.params, version, order_func)
    for header_item in las.params.values():
        mnemonic = header_item.original_mnemonic
        order = order_func(mnemonic)
        formatter_func = get_formatter_function(order, **section_widths)
        line = formatter_func(header_item)
        lines.append(line)

    # ~Other
    logger.debug("LASFile.write Other section")
    lines.append("~Other ".ljust(header_width, "-"))
    lines += las.other.splitlines()

    logger.debug("LASFile.write ASCII section")
    lines.append("~ASCII ".ljust(header_width, "-"))

    file_object.write("\n".join(lines))
    file_object.write("\n")
    line_counter = len(lines)

    # data_arr = np.column_stack([c.data for c in las.curves])
    data_arr = las.data
    nrows, ncols = data_arr.shape
    logger.debug("Data section shape: {}".format((nrows, ncols)))

    logger.debug("len_numeric_field = {}".format(len_numeric_field))
    if len_numeric_field is None:
        logger.debug("Calculating len_numeric_field. fmt = {}".format(fmt))
        len_numeric_field = 10
        test_fmt = fmt % np.pi
        while len(test_fmt) > (len_numeric_field - 1):
            logger.debug("test_fmt = {}".format(test_fmt))
            len_numeric_field += 1

    def format_data_section_line(n, fmt, l=len_numeric_field, spacer=" "):
        try:
            if np.isnan(n):
                return spacer + str(las.well["NULL"].value).rjust(l)
            else:
                return spacer + (fmt % n).rjust(l)
        except TypeError:
            return spacer + str(n).rjust(l)

    twrapper = textwrap.TextWrapper(width=data_width)

    for i in range(nrows):
        logger.debug("Writing data array row {} of {}".format(i + 1, nrows))
        depth_slice = ""
        for j in range(ncols):
            depth_slice += format_data_section_line(data_arr[i, j], fmt)

        if wrap:
            lines = twrapper.wrap(depth_slice)
            logger.debug(
                "LASFile.write Wrapped %d lines out of %s" % (len(lines), depth_slice)
            )
        else:
            lines = [depth_slice]

        for line in lines:
            if las.version["VERS"].value == 1.2 and len(line) > 255:
                logger.warning(
                    "[v1.2] line #{} has {} chars (>256)".format(
                        line_counter + 1, len(line)
                    )
                )
            file_object.write(line + "\n")
            line_counter += 1

def get_formatter_function(order, left_width=None, middle_width=None):
    """Create function to format a LAS header item for output.

    Arguments:
        order: format of item, either 'descr:value' or 'value:descr'

    Keyword Arguments:
        left_width (int): number of characters to the left hand side of the
            first period
        middle_width (int): total number of characters minus 1 between the
            first period from the left and the first colon from the left.

    Returns:
        A function which takes a header item
        (e.g. :class:`lasio.las_items.HeaderItem`) as its single argument and
        which in turn returns a string which is the correctly formatted LAS
        header line.

    """
    if left_width is None:
        left_width = 10
    if middle_width is None:
        middle_width = 40
    mnemonic_func = lambda mnemonic: mnemonic.ljust(left_width)
    middle_func = lambda unit, right_hand_item: (
        unit
        + " " * (middle_width - len(str(unit)) - len(right_hand_item))
        + right_hand_item
    )
    if order == "descr:value":
        return lambda item: "%s.%s : %s" % (
            mnemonic_func(item.original_mnemonic),
            middle_func(str(item.unit), str(item.descr)),
            item.value,
        )
    elif order == "value:descr":
        return lambda item: "%s.%s : %s" % (
            mnemonic_func(item.original_mnemonic),
            middle_func(str(item.unit), str(item.value)),
            item.descr,
        )

def get_section_order_function(
    section, version, order_definitions=defaults.ORDER_DEFINITIONS
):
    """Get a function that returns the order per the mnemonic and section.

    Arguments:
        section (str): either 'well', 'params', 'curves', 'version'
        version (float): either 1.2 and 2.0

    Keyword Arguments:
        order_definitions (dict): see source of defaults.py for more information

    Returns:
        A function which takes a mnemonic (str) as its only argument, and
        in turn returns the order 'value:descr' or 'descr:value'.

    """
    section_orders = order_definitions[version][section]
    default_order = section_orders[0]
    orders = {}
    for order, mnemonics in section_orders[1:]:
        for mnemonic in mnemonics:
            orders[mnemonic] = order
    return lambda mnemonic: orders.get(mnemonic, default_order)

def get_section_widths(section_name, items, version, order_func):
    """Find minimum section widths fitting the content in *items*.

    Arguments:
        section_name (str): either 'version', 'well', 'curves', or 'params'
        items (SectionItems): section items
        version (float): either 1.2 or 2.0
        order_func (func): see :func:`lasio.writer.get_section_order_function`

    """
    section_widths = {"left_width": None, "middle_width": None}
    if len(items) > 0:
        section_widths["left_width"] = max([len(i.original_mnemonic) for i in items])
        middle_widths = []
        for i in items:
            order = order_func(i.mnemonic)
            rhs_element = order.split(":")[0]
            logger.debug(
                "get_section_widths %s\n\torder=%s rhs_element=%s"
                % (i, order, rhs_element)
            )
            middle_widths.append(len(str(i.unit)) + 1 + len(str(i[rhs_element])))
        section_widths["middle_width"] = max(middle_widths)
    return section_widths
<commit_msg>#304: Add column_fmt kwarg to lasio.writer.write()<commit_after>import logging
import textwrap

import numpy as np

from .las_items import HeaderItem, CurveItem, SectionItems, OrderedDict
from . import defaults
from . import exceptions

logger = logging.getLogger(__name__)

def write(
    las,
    file_object,
    version=None,
    wrap=None,
    STRT=None,
    STOP=None,
    STEP=None,
    fmt="%.5f",
    column_fmt=None,
    len_numeric_field=None,
    data_width=79,
    header_width=60,
):
    """Write a LAS files.

    Arguments:
        las (:class:`lasio.las.LASFile`)
        file_object (file-like object open for writing): output
        version (float or None): version of written file, either 1.2 or 2.
            If this is None, ``las.version.VERS.value`` will be used.
        wrap (bool or None): whether to wrap the output data section.
            If this is None, ``las.version.WRAP.value`` will be used.
        STRT (float or None): value to use as STRT (note the data will not
            be clipped). If this is None, the data value in the first column,
            first row will be used.
        STOP (float or None): value to use as STOP (note the data will not
            be clipped). If this is None, the data value in the first column,
            last row will be used.
        STEP (float or None): value to use as STEP (note the data will not
            be resampled and/or interpolated). If this is None, the STEP will
            be estimated from the first two rows of the first column.
        fmt (str): Python string formatting operator for numeric data to be
            used.
        column_fmt (dict or None): use this to set a different format string
            for specific columns from the data ndarray. E.g. to use ``'%.4f'``
            for the depth column and ``'%.2f'`` for all the other columns,
            you would use ``fmt='%.2f', column_fmt={0: '%.3f'}``.
        len_numeric_field (int): width of each numeric field column (must be
            greater than than all the formatted numeric values in the file).
        data_width (79): width of data field in characters

    Creating an output file is not the only side-effect of this function. It
    will also modify the STRT, STOP and STEP HeaderItems so that they correctly
    reflect the ~Data section's units and the actual first, last, and interval
    values.

    You should avoid calling this function directly - instead use the
    :meth:`lasio.las.LASFile.write` method.

    """
    if column_fmt is None:
        column_fmt = {}
    if wrap is None:
        wrap = las.version["WRAP"] == "YES"
    elif wrap is True:
        las.version["WRAP"] = HeaderItem(
            "WRAP", "", "YES", "Multiple lines per depth step"
        )
    elif wrap is False:
        las.version["WRAP"] = HeaderItem("WRAP", "", "NO", "One line per depth step")
    lines = []

    assert version in (1.2, 2, None)
    if version is None:
        version = las.version["VERS"].value
    if version == 1.2:
        las.version["VERS"] = HeaderItem(
            "VERS", "", 1.2, "CWLS LOG ASCII STANDARD - VERSION 1.2"
        )
    elif version == 2:
        las.version["VERS"] = HeaderItem(
            "VERS", "", 2.0, "CWLS log ASCII Standard -VERSION 2.0"
        )

    if STRT is None:
        STRT = las.index[0]
    if STOP is None:
        STOP = las.index[-1]
    if STEP is None:
        if (
            STOP != STRT
        ):  # prevents an error being thrown in the case of only a single sample being written
            STEP = las.index[1] - las.index[0]  # Faster than np.gradient

    las.well["STRT"].value = STRT
    las.well["STOP"].value = STOP
    las.well["STEP"].value = STEP

    # Check units
    if las.curves[0].unit:
        unit = las.curves[0].unit
    else:
        unit = las.well["STRT"].unit
    las.well["STRT"].unit = unit
    las.well["STOP"].unit = unit
    las.well["STEP"].unit = unit
    las.curves[0].unit = unit

    # Write each section.
    # get_formatter_function ( ** get_section_widths )

    # ~Version
    logger.debug("LASFile.write Version section")
    lines.append("~Version ".ljust(header_width, "-"))
    order_func = get_section_order_function("Version", version)
    section_widths = get_section_widths("Version", las.version, version, order_func)
    for header_item in las.version.values():
        mnemonic = header_item.original_mnemonic
        # logger.debug('LASFile.write ' + str(header_item))
        order = order_func(mnemonic)
        # logger.debug('LASFile.write order = %s' % (order, ))
        logger.debug(
            "LASFile.write %s order=%s section_widths=%s"
            % (header_item, order, section_widths)
        )
        formatter_func = get_formatter_function(order, **section_widths)
        line = formatter_func(header_item)
        lines.append(line)

    # ~Well
    logger.debug("LASFile.write Well section")
    lines.append("~Well ".ljust(header_width, "-"))
    order_func = get_section_order_function("Well", version)
    section_widths = get_section_widths("Well", las.well, version, order_func)
    # logger.debug('LASFile.write well section_widths=%s' % section_widths)
    for header_item in las.well.values():
        mnemonic = header_item.original_mnemonic
        order = order_func(mnemonic)
        logger.debug(
            "LASFile.write %s order=%s section_widths=%s"
            % (header_item, order, section_widths)
        )
        formatter_func = get_formatter_function(order, **section_widths)
        line = formatter_func(header_item)
        lines.append(line)

    # ~Curves
    logger.debug("LASFile.write Curves section")
    lines.append("~Curve Information ".ljust(header_width, "-"))
    order_func = get_section_order_function("Curves", version)
    section_widths = get_section_widths("Curves", las.curves, version, order_func)
    for header_item in las.curves:
        mnemonic = header_item.original_mnemonic
        order = order_func(mnemonic)
        formatter_func = get_formatter_function(order, **section_widths)
        line = formatter_func(header_item)
        lines.append(line)

    # ~Params
    logger.debug("LASFile.write Params section")
    lines.append("~Params ".ljust(header_width, "-"))
    order_func = get_section_order_function("Parameter", version)
    section_widths = get_section_widths("Parameter", las.params, version, order_func)
    for header_item in las.params.values():
        mnemonic = header_item.original_mnemonic
        order = order_func(mnemonic)
        formatter_func = get_formatter_function(order, **section_widths)
        line = formatter_func(header_item)
        lines.append(line)

    # ~Other
    logger.debug("LASFile.write Other section")
    lines.append("~Other ".ljust(header_width, "-"))
    lines += las.other.splitlines()

    logger.debug("LASFile.write ASCII section")
    lines.append("~ASCII ".ljust(header_width, "-"))

    file_object.write("\n".join(lines))
    file_object.write("\n")
    line_counter = len(lines)

    # data_arr = np.column_stack([c.data for c in las.curves])
    data_arr = las.data
    nrows, ncols = data_arr.shape
    logger.debug("Data section shape: {}".format((nrows, ncols)))

    logger.debug("len_numeric_field = {}".format(len_numeric_field))
    if len_numeric_field is None:
        logger.debug("Calculating len_numeric_field. fmt = {}".format(fmt))
        len_numeric_field = 10
        test_fmt = fmt % np.pi
        while len(test_fmt) > (len_numeric_field - 1):
            logger.debug("test_fmt = {}".format(test_fmt))
            len_numeric_field += 1

    def format_data_section_line(n, fmt, l=len_numeric_field, spacer=" "):
        try:
            if np.isnan(n):
                return spacer + str(las.well["NULL"].value).rjust(l)
            else:
                return spacer + (fmt % n).rjust(l)
        except TypeError:
            return spacer + str(n).rjust(l)

    twrapper = textwrap.TextWrapper(width=data_width)

    for i in range(nrows):
        logger.debug("Writing data array row {} of {}".format(i + 1, nrows))
        depth_slice = ""
        for j in range(ncols):
            col_fmt = fmt
            if j in column_fmt:
                col_fmt = column_fmt[j]
            depth_slice += format_data_section_line(data_arr[i, j], col_fmt)

        if wrap:
            lines = twrapper.wrap(depth_slice)
            logger.debug(
                "LASFile.write Wrapped %d lines out of %s" % (len(lines), depth_slice)
            )
        else:
            lines = [depth_slice]

        for line in lines:
            if las.version["VERS"].value == 1.2 and len(line) > 255:
                logger.warning(
                    "[v1.2] line #{} has {} chars (>256)".format(
                        line_counter + 1, len(line)
                    )
                )
            file_object.write(line + "\n")
            line_counter += 1

def get_formatter_function(order, left_width=None, middle_width=None):
    """Create function to format a LAS header item for output.

    Arguments:
        order: format of item, either 'descr:value' or 'value:descr'

    Keyword Arguments:
        left_width (int): number of characters to the left hand side of the
            first period
        middle_width (int): total number of characters minus 1 between the
            first period from the left and the first colon from the left.

    Returns:
        A function which takes a header item
        (e.g. :class:`lasio.las_items.HeaderItem`) as its single argument and
        which in turn returns a string which is the correctly formatted LAS
        header line.

    """
    if left_width is None:
        left_width = 10
    if middle_width is None:
        middle_width = 40
    mnemonic_func = lambda mnemonic: mnemonic.ljust(left_width)
    middle_func = lambda unit, right_hand_item: (
        unit
        + " " * (middle_width - len(str(unit)) - len(right_hand_item))
        + right_hand_item
    )
    if order == "descr:value":
        return lambda item: "%s.%s : %s" % (
            mnemonic_func(item.original_mnemonic),
            middle_func(str(item.unit), str(item.descr)),
            item.value,
        )
    elif order == "value:descr":
        return lambda item: "%s.%s : %s" % (
            mnemonic_func(item.original_mnemonic),
            middle_func(str(item.unit), str(item.value)),
            item.descr,
        )

def get_section_order_function(
    section, version, order_definitions=defaults.ORDER_DEFINITIONS
):
    """Get a function that returns the order per the mnemonic and section.

    Arguments:
        section (str): either 'well', 'params', 'curves', 'version'
        version (float): either 1.2 and 2.0

    Keyword Arguments:
        order_definitions (dict): see source of defaults.py for more information

    Returns:
        A function which takes a mnemonic (str) as its only argument, and
        in turn returns the order 'value:descr' or 'descr:value'.

    """
    section_orders = order_definitions[version][section]
    default_order = section_orders[0]
    orders = {}
    for order, mnemonics in section_orders[1:]:
        for mnemonic in mnemonics:
            orders[mnemonic] = order
    return lambda mnemonic: orders.get(mnemonic, default_order)

def get_section_widths(section_name, items, version, order_func):
    """Find minimum section widths fitting the content in *items*.

    Arguments:
        section_name (str): either 'version', 'well', 'curves', or 'params'
        items (SectionItems): section items
        version (float): either 1.2 or 2.0
        order_func (func): see :func:`lasio.writer.get_section_order_function`

    """
    section_widths = {"left_width": None, "middle_width": None}
    if len(items) > 0:
        section_widths["left_width"] = max([len(i.original_mnemonic) for i in items])
        middle_widths = []
        for i in items:
            order = order_func(i.mnemonic)
            rhs_element = order.split(":")[0]
            logger.debug(
                "get_section_widths %s\n\torder=%s rhs_element=%s"
                % (i, order, rhs_element)
            )
            middle_widths.append(len(str(i.unit)) + 1 + len(str(i[rhs_element])))
        section_widths["middle_width"] = max(middle_widths)
    return section_widths
<|endoftext|>


<commit_before>import io

from django.template import loader
from django.template.response import SimpleTemplateResponse
from django.http import HttpResponse
from django.db.models import Q, Count

from staff.models import HelperJob

import odswriter

def mail_export(modeladmin, request, queryset):
    """Creates a list of email addresses in "prename lastname <email@example.net>" format.
    This should be suitable for mass subscription and similar purposes.
    """
    template = loader.get_template("staff/mail_export.html")
    context = {'persons' : queryset}
    return SimpleTemplateResponse(template, context)

mail_export.short_description = "E-Mail Mass Subscription Export"

def staff_nametag_export(modeladmin, request, queryset):
    """Exports certain staff data in ods format, containing the necessary information for the name tag production application.
    The produced ods file is the input for the name tag Java aplication.
    """
    table = []
    empty = '~'
    for person in queryset.filter(Q(is_tutor=True) | Q(is_orga=True)):
        row = [person.prename, person.name]
        if person.is_tutor:
            if "master" in str(person.tutor_for).lower():
                row.append('M')
                row.append('MASTER')
            else:
                row.append('T')
                row.append('TUTOR')
        else:
            row.extend([empty]*2)
        if person.is_orga:
            row.append('ORGA')
        else:
            row.append(empty)
        row.extend([empty]*4)
        table.append(row)

    out_stream = io.BytesIO()
    with odswriter.writer(out_stream) as out:
        # need to specify number of columns for jOpenDocument compatibility
        sheet = out.new_sheet("Staff", cols=9)
        sheet.writerows(table)

    response = HttpResponse(out_stream.getvalue(), content_type="application/vnd.oasis.opendocument.spreadsheet")
    # name the file according to the expectations of the Java name tag application
    response['Content-Disposition'] = 'attachment; filename="tutoren.ods"'
    return response

staff_nametag_export.short_description = "Namensschilderexport"

def staff_overview_export(modeladmin, request, queryset):
    """Exports an overview of the staff containing contact data and field of duty.
    """
    orgas = []
    tutors = []
    helpers = []
    for person in queryset:
        row = [person.prename, person.name, person.email, person.phone]
        if person.is_orga:
            jobs = ' / '.join(sorted([str(job) for job in person.orga_jobs.all()]))
            orgas.append(row + [jobs])
        if person.is_tutor:
            tutors.append(row + [str(person.tutor_for)])
        if person.is_helper:
            jobs = ' / '.join(sorted([str(job) for job in person.helper_jobs.all()]))
            helpers.append(row + [jobs])

    orgas.sort(key=lambda row: row[1])
    tutors.sort(key=lambda row: row[1])
    helpers.sort(key=lambda row: row[1])

    out_stream = io.BytesIO()
    with odswriter.writer(out_stream) as out:
        orga_sheet = out.new_sheet("Orgas")
        orga_sheet.writerow(["Vorname", "Nachname", "E-Mail", "Handy", "Verantwortlich für ..."])
        orga_sheet.writerows(orgas)
        tutor_sheet = out.new_sheet("Tutoren")
        tutor_sheet.writerow(["Vorname", "Nachname", "E-Mail", "Handy", "Betreut ..."])
        tutor_sheet.writerows(tutors)
        helper_sheet = out.new_sheet("Helfer")
        helper_sheet.writerow(["Vorname", "Nachname", "E-Mail", "Handy", "Hilft bei ..."])
        helper_sheet.writerows(helpers)

    response = HttpResponse(out_stream.getvalue(), content_type="application/vnd.oasis.opendocument.spreadsheet")
    response['Content-Disposition'] = 'attachment; filename="Personal.ods"'
    return response

staff_overview_export.short_description = "Übersicht exportieren"

def helper_job_overview(modeladmin, request, queryset):
    """Display a matrix to show helpers with associated helper jobs.
    """
    template = loader.get_template("staff/helper_matrix.html")

    helper = queryset.filter(is_helper=True)
    jobs = HelperJob.objects.all().annotate(num_helper=Count('person'))

    for h in helper:
        job_interest = []
        for j in jobs:
            if h.helper_jobs.filter(id=j.id).exists():
                job_interest.append(True)
            else:
                job_interest.append(False)
        h.job_interest = job_interest

    context = {
        'helper' : helper,
        'jobs' : jobs,
    }

    return SimpleTemplateResponse(template, context)

helper_job_overview.short_description = "Helfer-Übersicht anzeigen"
<commit_msg>helperjobs are sorted in matrix overview<commit_after>import io

from django.template import loader
from django.template.response import SimpleTemplateResponse
from django.http import HttpResponse
from django.db.models import Q, Count

from staff.models import HelperJob

import odswriter

def mail_export(modeladmin, request, queryset):
    """Creates a list of email addresses in "prename lastname <email@example.net>" format.
    This should be suitable for mass subscription and similar purposes.
    """
    template = loader.get_template("staff/mail_export.html")
    context = {'persons' : queryset}
    return SimpleTemplateResponse(template, context)

mail_export.short_description = "E-Mail Mass Subscription Export"

def staff_nametag_export(modeladmin, request, queryset):
    """Exports certain staff data in ods format, containing the necessary information for the name tag production application.
    The produced ods file is the input for the name tag Java aplication.
    """
    table = []
    empty = '~'
    for person in queryset.filter(Q(is_tutor=True) | Q(is_orga=True)):
        row = [person.prename, person.name]
        if person.is_tutor:
            if "master" in str(person.tutor_for).lower():
                row.append('M')
                row.append('MASTER')
            else:
                row.append('T')
                row.append('TUTOR')
        else:
            row.extend([empty]*2)
        if person.is_orga:
            row.append('ORGA')
        else:
            row.append(empty)
        row.extend([empty]*4)
        table.append(row)

    out_stream = io.BytesIO()
    with odswriter.writer(out_stream) as out:
        # need to specify number of columns for jOpenDocument compatibility
        sheet = out.new_sheet("Staff", cols=9)
        sheet.writerows(table)

    response = HttpResponse(out_stream.getvalue(), content_type="application/vnd.oasis.opendocument.spreadsheet")
    # name the file according to the expectations of the Java name tag application
    response['Content-Disposition'] = 'attachment; filename="tutoren.ods"'
    return response

staff_nametag_export.short_description = "Namensschilderexport"

def staff_overview_export(modeladmin, request, queryset):
    """Exports an overview of the staff containing contact data and field of duty.
    """
    orgas = []
    tutors = []
    helpers = []
    for person in queryset:
        row = [person.prename, person.name, person.email, person.phone]
        if person.is_orga:
            jobs = ' / '.join(sorted([str(job) for job in person.orga_jobs.all()]))
            orgas.append(row + [jobs])
        if person.is_tutor:
            tutors.append(row + [str(person.tutor_for)])
        if person.is_helper:
            jobs = ' / '.join(sorted([str(job) for job in person.helper_jobs.all()]))
            helpers.append(row + [jobs])

    orgas.sort(key=lambda row: row[1])
    tutors.sort(key=lambda row: row[1])
    helpers.sort(key=lambda row: row[1])

    out_stream = io.BytesIO()
    with odswriter.writer(out_stream) as out:
        orga_sheet = out.new_sheet("Orgas")
        orga_sheet.writerow(["Vorname", "Nachname", "E-Mail", "Handy", "Verantwortlich für ..."])
        orga_sheet.writerows(orgas)
        tutor_sheet = out.new_sheet("Tutoren")
        tutor_sheet.writerow(["Vorname", "Nachname", "E-Mail", "Handy", "Betreut ..."])
        tutor_sheet.writerows(tutors)
        helper_sheet = out.new_sheet("Helfer")
        helper_sheet.writerow(["Vorname", "Nachname", "E-Mail", "Handy", "Hilft bei ..."])
        helper_sheet.writerows(helpers)

    response = HttpResponse(out_stream.getvalue(), content_type="application/vnd.oasis.opendocument.spreadsheet")
    response['Content-Disposition'] = 'attachment; filename="Personal.ods"'
    return response

staff_overview_export.short_description = "Übersicht exportieren"

def helper_job_overview(modeladmin, request, queryset):
    """Display a matrix to show helpers with associated helper jobs.
    """
    template = loader.get_template("staff/helper_matrix.html")

    helper = queryset.filter(is_helper=True)
    jobs = HelperJob.objects.all().annotate(num_helper=Count('person')).order_by('label')

    for h in helper:
        job_interest = []
        for j in jobs:
            if h.helper_jobs.filter(id=j.id).exists():
                job_interest.append(True)
            else:
                job_interest.append(False)
        h.job_interest = job_interest

    context = {
        'helper' : helper,
        'jobs' : jobs,
    }

    return SimpleTemplateResponse(template, context)

helper_job_overview.short_description = "Helfer-Übersicht anzeigen"
<|endoftext|>


<commit_before>#!/usr/bin/env python2.7

import matplotlib.pyplot as plt
import os
import re
import sys

def plot(filename, direction, entries):
    items = entries.items()
    degrees, occurences = zip(*items)

    plt.yscale('log')
    plt.xscale('log')
    plt.xlabel((direction + "degree").capitalize())
    plt.ylabel("Number of occurences")

    plt.plot(degrees, occurences, label=direction.capitalize() + "degree for " + os.path.basename(filename))

def main():
    direction=None
    filename=None
    entries=None

    headerPattern = re.compile('Distribution of (in|out)degree for (.*)$')
    entryPattern = re.compile('\s*(\d+)(\s+)(\d+)$')

    for line in sys.stdin:
        m = headerPattern.match(line)
        if m:
            if filename:
                plot(filename, direction, entries)

            direction = m.group(1)
            filename = m.group(2)
            entries = {}
        else:
            m = entryPattern.match(line)
            occurence = int(m.group(1))
            degree = int(m.group(3))
            entries[degree] = occurence

    if filename:
        plot(filename, direction, entries)
    else:
        print "No data provided"
        sys.exit(1)

    plt.legend()
    plt.savefig("degree-distributions.pdf")

if __name__ == "__main__":
    main()
<commit_msg>Verbeter analysescript.<commit_after>#!/usr/bin/env python2.7

import matplotlib.pyplot as plt
import os
import re
import sys

def plot(filename, direction, entries):
    items = entries.items()
    items.sort()
    degrees, occurences = zip(*items)

    plt.yscale('log')
    plt.xscale('log')
    plt.xlabel("Degree")
    plt.ylabel("Number of occurences")

    plt.plot(degrees, occurences, label=direction.capitalize() + "degree for " + os.path.basename(filename))

def main():
    direction=None
    filename=None
    entries=None

    headerPattern = re.compile('Distribution of (in|out)degree for (.*)$')
    entryPattern = re.compile('\s*(\d+)(\s+)(\d+)$')

    for line in sys.stdin:
        m = headerPattern.match(line)
        if m:
            if filename:
                plot(filename, direction, entries)

            direction = m.group(1)
            filename = m.group(2)
            entries = {}
        else:
            m = entryPattern.match(line)
            occurence = int(m.group(1))
            degree = int(m.group(3))
            entries[degree] = occurence

    if filename:
        plot(filename, direction, entries)
    else:
        print "No data provided"
        sys.exit(1)

    plt.legend()
    plt.savefig("degree-distributions.pdf")

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