<commit_before>#
# This file is part of my.gpodder.org.
#
# my.gpodder.org is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# my.gpodder.org is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with my.gpodder.org. If not, see <http://www.gnu.org/licenses/>.
#

from datetime import datetime
from functools import wraps

import dateutil.parser

from django.shortcuts import render
from django.http import HttpResponseRedirect, Http404
from django.contrib.auth.decorators import login_required
from django.contrib.sites.models import RequestSite
from django.contrib.contenttypes.models import ContentType
from django.views.decorators.vary import vary_on_cookie
from django.views.decorators.cache import never_cache, cache_control
from django.contrib import messages
from django.utils.translation import ugettext as _

from mygpo.podcasts.models import Podcast, Episode
from mygpo.api.constants import EPISODE_ACTION_TYPES
from mygpo.core.tasks import flattr_thing
from mygpo.utils import parse_time, get_timestamp
from mygpo.users.settings import FLATTR_TOKEN
from mygpo.web.heatmap import EpisodeHeatmap
from mygpo.history.stats import last_played_episodes
from mygpo.publisher.utils import check_publisher_permission
from mygpo.web.utils import get_episode_link_target, check_restrictions
from mygpo.history.models import EpisodeHistoryEntry
from mygpo.favorites.models import FavoriteEpisode
from mygpo.userfeeds.feeds import FavoriteFeed

@vary_on_cookie
@cache_control(private=True)
def episode(request, episode):

    podcast = episode.podcast

    podcast = check_restrictions(podcast)

    user = request.user

    if not podcast:
        raise Http404

    if user.is_authenticated():

        is_fav = FavoriteEpisode.objects.filter(user=user, episode=episode)\
                                        .exists()

        # pre-populate data for fetch_data
        podcasts_dict = {podcast.get_id(): podcast}
        episodes_dict = {episode.id.hex: episode}

        has_history = EpisodeHistoryEntry.objects.filter(user=user,
                                                         episode=episode)\
                                                 .exists()

        played_parts = EpisodeHeatmap(podcast, episode, user, episode.duration)

        devices = {c.id.hex: c for c in user.client_set.all()}
        can_flattr = user.profile.settings.get_wksetting(FLATTR_TOKEN) and episode.flattr_url

    else:
        has_history = False
        is_fav = False
        played_parts = None
        devices = {}
        can_flattr = False

    is_publisher = check_publisher_permission(user, podcast)

    prev = None #podcast.get_episode_before(episode)
    next = None #podcast.get_episode_after(episode)

    return render(request, 'episode.html', {
        'episode': episode,
        'podcast': podcast,
        'prev': prev,
        'next': next,
        'has_history': has_history,
        'is_favorite': is_fav,
        'played_parts': played_parts,
        'actions': EPISODE_ACTION_TYPES,
        'devices': devices,
        'can_flattr': can_flattr,
        'is_publisher': is_publisher,
    })

@never_cache
@login_required
@vary_on_cookie
@cache_control(private=True)
def history(request, episode):
    """ shows the history of the episode """

    user = request.user
    podcast = episode.podcast

    history = EpisodeHistoryEntry.objects.filter(user=user,
                                                 episode=episode,)\
                                         .order_by('-timestamp')\
                                         .prefetch_related('episode',
                                                           'episode__slugs',
                                                           'episode__podcast',
                                                           'episode__podcast__slugs',
                                                           'client')

    clients = user.client_set.all()

    return render(request, 'episode-history.html', {
        'episode': episode,
        'podcast': podcast,
        'history': history,
        'actions': EPISODE_ACTION_TYPES,
        'clients': clients,
    })

@never_cache
@login_required
def toggle_favorite(request, episode):
    user = request.user

    fav, created = FavoriteEpisode.objects.get_or_create(
        user=user,
        episode=episode,
    )

    # if the episode was already a favorite, remove it
    if not created:
        fav.delete()

    podcast = episode.podcast
    return HttpResponseRedirect(get_episode_link_target(episode, podcast))

@vary_on_cookie
@cache_control(private=True)
@login_required
def list_favorites(request):
    user = request.user
    site = RequestSite(request)

    favorites = FavoriteEpisode.episodes_for_user(user)

    recently_listened = last_played_episodes(user)

    favfeed = FavoriteFeed(user)
    feed_url = favfeed.get_public_url(site.domain)

    podcast = Podcast.objects.filter(urls__url=feed_url).first()

    token = request.user.profile.favorite_feeds_token

    return render(request, 'favorites.html', {
        'episodes': favorites,
        'feed_token': token,
        'site': site,
        'podcast': podcast,
        'recently_listened': recently_listened,
        })

@never_cache
def add_action(request, episode):

    user = request.user
    client = user.client_set.get(id=request.POST.get('device'))

    action_str = request.POST.get('action')
    timestamp = request.POST.get('timestamp', '')

    if timestamp:
        try:
            timestamp = dateutil.parser.parse(timestamp)
        except (ValueError, AttributeError):
            timestamp = datetime.utcnow()
    else:
        timestamp = datetime.utcnow()

    EpisodeHistoryEntry.create_entry(user, episode, action_str, client,
                                     timestamp)
    podcast = episode.podcast
    return HttpResponseRedirect(get_episode_link_target(episode, podcast))

@never_cache
@login_required
def flattr_episode(request, episode):
    """ Flattrs an episode, records an event and redirects to the episode """

    user = request.user
    site = RequestSite(request)

    # Flattr via the tasks queue, but wait for the result
    task = flattr_thing.delay(user, episode._id, site.domain,
            request.is_secure(), 'Episode')
    success, msg = task.get()

    if success:
        messages.success(request, _("Flattr\'d"))

    else:
        messages.error(request, msg)

    podcast = episode.podcast
    return HttpResponseRedirect(get_episode_link_target(episode, podcast))

# To make all view accessible via either IDs or Slugs
# a decorator queries the episode and passes the Id on to the
# regular views

def slug_decorator(f):
    @wraps(f)
    def _decorator(request, p_slug, e_slug, *args, **kwargs):

        pquery = Podcast.objects.filter(
            slugs__slug=p_slug,
            slugs__scope='',
        )

        try:
            podcast = pquery.prefetch_related('slugs').get()
        except Podcast.DoesNotExist:
            raise Http404

        equery = Episode.objects.filter(
            podcast = podcast,
            slugs__slug=e_slug,
            slugs__scope=podcast.id.hex,
        )

        try:
            episode = equery.prefetch_related('urls', 'slugs').get()

            # set previously fetched podcast, to avoid additional query
            episode.podcast = podcast

        except Episode.DoesNotExist:
            raise Http404

        # redirect when Id or a merged (non-cannonical) slug is used
        if episode.slug and episode.slug != e_slug:
            return HttpResponseRedirect(
                    get_episode_link_target(episode, podcast))

        return f(request, episode, *args, **kwargs)

    return _decorator

def id_decorator(f):
    @wraps(f)
    def _decorator(request, p_id, e_id, *args, **kwargs):

        try:
            query = Episode.objects.filter(id=e_id,
                                           podcast_id=p_id)
            episode = query.select_related('podcast').get()

        except Episode.DoesNotExist:
            raise Http404

        # redirect when Id or a merged (non-cannonical) slug is used
        if episode.slug and episode.slug != e_id:
            podcast = episode.podcast
            return HttpResponseRedirect(
                    get_episode_link_target(episode, podcast))

        return f(request, episode, *args, **kwargs)

    return _decorator

show_slug            = slug_decorator(episode)
toggle_favorite_slug = slug_decorator(toggle_favorite)
add_action_slug      = slug_decorator(add_action)
flattr_episode_slug  = slug_decorator(flattr_episode)
episode_history_slug = slug_decorator(history)

show_id            = id_decorator(episode)
toggle_favorite_id = id_decorator(toggle_favorite)
add_action_id      = id_decorator(add_action)
flattr_episode_id  = id_decorator(flattr_episode)
episode_history_id = id_decorator(history)
<commit_msg>[History] handle TypeError when adding action via web<commit_after>#
# This file is part of my.gpodder.org.
#
# my.gpodder.org is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# my.gpodder.org is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with my.gpodder.org. If not, see <http://www.gnu.org/licenses/>.
#

from datetime import datetime
from functools import wraps

import dateutil.parser

from django.shortcuts import render
from django.http import HttpResponseRedirect, Http404
from django.contrib.auth.decorators import login_required
from django.contrib.sites.models import RequestSite
from django.contrib.contenttypes.models import ContentType
from django.views.decorators.vary import vary_on_cookie
from django.views.decorators.cache import never_cache, cache_control
from django.contrib import messages
from django.utils.translation import ugettext as _

from mygpo.podcasts.models import Podcast, Episode
from mygpo.api.constants import EPISODE_ACTION_TYPES
from mygpo.core.tasks import flattr_thing
from mygpo.utils import parse_time, get_timestamp
from mygpo.users.settings import FLATTR_TOKEN
from mygpo.web.heatmap import EpisodeHeatmap
from mygpo.history.stats import last_played_episodes
from mygpo.publisher.utils import check_publisher_permission
from mygpo.web.utils import get_episode_link_target, check_restrictions
from mygpo.history.models import EpisodeHistoryEntry
from mygpo.favorites.models import FavoriteEpisode
from mygpo.userfeeds.feeds import FavoriteFeed

@vary_on_cookie
@cache_control(private=True)
def episode(request, episode):

    podcast = episode.podcast

    podcast = check_restrictions(podcast)

    user = request.user

    if not podcast:
        raise Http404

    if user.is_authenticated():

        is_fav = FavoriteEpisode.objects.filter(user=user, episode=episode)\
                                        .exists()

        # pre-populate data for fetch_data
        podcasts_dict = {podcast.get_id(): podcast}
        episodes_dict = {episode.id.hex: episode}

        has_history = EpisodeHistoryEntry.objects.filter(user=user,
                                                         episode=episode)\
                                                 .exists()

        played_parts = EpisodeHeatmap(podcast, episode, user, episode.duration)

        devices = {c.id.hex: c for c in user.client_set.all()}
        can_flattr = user.profile.settings.get_wksetting(FLATTR_TOKEN) and episode.flattr_url

    else:
        has_history = False
        is_fav = False
        played_parts = None
        devices = {}
        can_flattr = False

    is_publisher = check_publisher_permission(user, podcast)

    prev = None #podcast.get_episode_before(episode)
    next = None #podcast.get_episode_after(episode)

    return render(request, 'episode.html', {
        'episode': episode,
        'podcast': podcast,
        'prev': prev,
        'next': next,
        'has_history': has_history,
        'is_favorite': is_fav,
        'played_parts': played_parts,
        'actions': EPISODE_ACTION_TYPES,
        'devices': devices,
        'can_flattr': can_flattr,
        'is_publisher': is_publisher,
    })

@never_cache
@login_required
@vary_on_cookie
@cache_control(private=True)
def history(request, episode):
    """ shows the history of the episode """

    user = request.user
    podcast = episode.podcast

    history = EpisodeHistoryEntry.objects.filter(user=user,
                                                 episode=episode,)\
                                         .order_by('-timestamp')\
                                         .prefetch_related('episode',
                                                           'episode__slugs',
                                                           'episode__podcast',
                                                           'episode__podcast__slugs',
                                                           'client')

    clients = user.client_set.all()

    return render(request, 'episode-history.html', {
        'episode': episode,
        'podcast': podcast,
        'history': history,
        'actions': EPISODE_ACTION_TYPES,
        'clients': clients,
    })

@never_cache
@login_required
def toggle_favorite(request, episode):
    user = request.user

    fav, created = FavoriteEpisode.objects.get_or_create(
        user=user,
        episode=episode,
    )

    # if the episode was already a favorite, remove it
    if not created:
        fav.delete()

    podcast = episode.podcast
    return HttpResponseRedirect(get_episode_link_target(episode, podcast))

@vary_on_cookie
@cache_control(private=True)
@login_required
def list_favorites(request):
    user = request.user
    site = RequestSite(request)

    favorites = FavoriteEpisode.episodes_for_user(user)

    recently_listened = last_played_episodes(user)

    favfeed = FavoriteFeed(user)
    feed_url = favfeed.get_public_url(site.domain)

    podcast = Podcast.objects.filter(urls__url=feed_url).first()

    token = request.user.profile.favorite_feeds_token

    return render(request, 'favorites.html', {
        'episodes': favorites,
        'feed_token': token,
        'site': site,
        'podcast': podcast,
        'recently_listened': recently_listened,
        })

@never_cache
def add_action(request, episode):

    user = request.user
    client = user.client_set.get(id=request.POST.get('device'))

    action_str = request.POST.get('action')
    timestamp = request.POST.get('timestamp', '')

    if timestamp:
        try:
            timestamp = dateutil.parser.parse(timestamp)
        except (ValueError, AttributeError, TypeError):
            timestamp = datetime.utcnow()
    else:
        timestamp = datetime.utcnow()

    EpisodeHistoryEntry.create_entry(user, episode, action_str, client,
                                     timestamp)
    podcast = episode.podcast
    return HttpResponseRedirect(get_episode_link_target(episode, podcast))

@never_cache
@login_required
def flattr_episode(request, episode):
    """ Flattrs an episode, records an event and redirects to the episode """

    user = request.user
    site = RequestSite(request)

    # Flattr via the tasks queue, but wait for the result
    task = flattr_thing.delay(user, episode._id, site.domain,
            request.is_secure(), 'Episode')
    success, msg = task.get()

    if success:
        messages.success(request, _("Flattr\'d"))

    else:
        messages.error(request, msg)

    podcast = episode.podcast
    return HttpResponseRedirect(get_episode_link_target(episode, podcast))

# To make all view accessible via either IDs or Slugs
# a decorator queries the episode and passes the Id on to the
# regular views

def slug_decorator(f):
    @wraps(f)
    def _decorator(request, p_slug, e_slug, *args, **kwargs):

        pquery = Podcast.objects.filter(
            slugs__slug=p_slug,
            slugs__scope='',
        )

        try:
            podcast = pquery.prefetch_related('slugs').get()
        except Podcast.DoesNotExist:
            raise Http404

        equery = Episode.objects.filter(
            podcast = podcast,
            slugs__slug=e_slug,
            slugs__scope=podcast.id.hex,
        )

        try:
            episode = equery.prefetch_related('urls', 'slugs').get()

            # set previously fetched podcast, to avoid additional query
            episode.podcast = podcast

        except Episode.DoesNotExist:
            raise Http404

        # redirect when Id or a merged (non-cannonical) slug is used
        if episode.slug and episode.slug != e_slug:
            return HttpResponseRedirect(
                    get_episode_link_target(episode, podcast))

        return f(request, episode, *args, **kwargs)

    return _decorator

def id_decorator(f):
    @wraps(f)
    def _decorator(request, p_id, e_id, *args, **kwargs):

        try:
            query = Episode.objects.filter(id=e_id,
                                           podcast_id=p_id)
            episode = query.select_related('podcast').get()

        except Episode.DoesNotExist:
            raise Http404

        # redirect when Id or a merged (non-cannonical) slug is used
        if episode.slug and episode.slug != e_id:
            podcast = episode.podcast
            return HttpResponseRedirect(
                    get_episode_link_target(episode, podcast))

        return f(request, episode, *args, **kwargs)

    return _decorator

show_slug            = slug_decorator(episode)
toggle_favorite_slug = slug_decorator(toggle_favorite)
add_action_slug      = slug_decorator(add_action)
flattr_episode_slug  = slug_decorator(flattr_episode)
episode_history_slug = slug_decorator(history)

show_id            = id_decorator(episode)
toggle_favorite_id = id_decorator(toggle_favorite)
add_action_id      = id_decorator(add_action)
flattr_episode_id  = id_decorator(flattr_episode)
episode_history_id = id_decorator(history)
<|endoftext|>


<commit_before>"""
Storage for all of the HTML/Javascript which powers the web frontend.
"""

NOT_FOUND_PAGE = b'Not Found'

AJAX = b'''
function ajax(uri, data, headers, on_ready) {
    var xhr = new XMLHttpRequest();

    xhr.onreadystatechange = (function() {
        if (xhr.readyState == 4) {
            on_ready(xhr.responseText);
        }
    });

    xhr.open('POST', uri, true);
    for (var key in headers) {
        xhr.setRequestHeader(key, headers[key].toString());
    }

    xhr.send(data);
}
'''

###############################################################################

SEARCH_PAGE = b'''

    <title>MyWeb Search</title>

        <input type="text" id="query" style="width:100%" onkeyup="handle_keypress(event);" />

        <input type="button" value="Create" style="width:100%" onclick="do_new();" />

'''.replace(b'%AJAX%', AJAX)

###############################################################################

NEW_PAGE = b'''

    <title>MyWeb - New Article</title>

        <input type="text" style="width:100%" id="uri" />

        <textarea id="content" style="width:100%;height:75%"> </textarea>

        <input type="text" style="width:100%" id="tags" />

        <input type="button" value="Submit" style="width:100%" onclick="do_submit();" />

'''.replace(b'%AJAX%', AJAX)

################################################################################

EDIT_PAGE = b'''

    <title>MyWeb - Edit Article</title>

        <textarea id="content" style="width:100%;height:75%" ></textarea>

        <input type="text" style="width:100%" id="tags" />

        <input type="button" value="Submit" style="width:100%" onclick="do_submit();" />

'''.replace(b'%AJAX%', AJAX)

################################################################################

VIEW_PAGE = b'''

    <title>MyWeb - View Article</title>

        <input type="button" value="Edit" style="width:30%"" onclick="do_edit();" />
        <input type="button" value="Refresh" style="width:30%" onclick="load_article_content();" />
        <input type="button" value="Delete" style="width:30%" onclick="do_delete();" />

'''.replace(b'%AJAX%', AJAX)
<commit_msg>Added "View" buttons to the create and edit pages.<commit_after>"""
Storage for all of the HTML/Javascript which powers the web frontend.
"""

NOT_FOUND_PAGE = b'Not Found'

AJAX = b'''
function ajax(uri, data, headers, on_ready) {
    var xhr = new XMLHttpRequest();

    xhr.onreadystatechange = (function() {
        if (xhr.readyState == 4) {
            on_ready(xhr.responseText);
        }
    });

    xhr.open('POST', uri, true);
    for (var key in headers) {
        xhr.setRequestHeader(key, headers[key].toString());
    }

    xhr.send(data);
}
'''

###############################################################################

SEARCH_PAGE = b'''

    <title>MyWeb Search</title>

        <input type="text" id="query" style="width:100%" onkeyup="handle_keypress(event);" />

        <input type="button" value="Create" style="width:100%" onclick="do_new();" />

'''.replace(b'%AJAX%', AJAX)

###############################################################################

NEW_PAGE = b'''

    <title>MyWeb - New Article</title>

        <input type="text" style="width:100%" id="uri" />

        <textarea id="content" style="width:100%;height:75%"> </textarea>

        <input type="text" style="width:100%" id="tags" />

        <input type="button" value="Submit" style="width:45%" onclick="do_submit();" />
        <input type="button" value="View" style="width:45%" onclick="do_view();" />

'''.replace(b'%AJAX%', AJAX)

################################################################################

EDIT_PAGE = b'''

    <title>MyWeb - Edit Article</title>

        <textarea id="content" style="width:100%;height:75%" ></textarea>

        <input type="text" style="width:100%" id="tags" />

        <input type="button" value="Submit" style="width:45%" onclick="do_submit();" />
        <input type="button" value="View" style="width:45%" onclick="do_view();" />

'''.replace(b'%AJAX%', AJAX)

################################################################################

VIEW_PAGE = b'''

    <title>MyWeb - View Article</title>

        <input type="button" value="Edit" style="width:30%"" onclick="do_edit();" />
        <input type="button" value="Refresh" style="width:30%" onclick="load_article_content();" />
        <input type="button" value="Delete" style="width:30%" onclick="do_delete();" />

'''.replace(b'%AJAX%', AJAX)
<|endoftext|>


<commit_before># Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from master import master_config
from master.factory import chromium_factory

defaults = {}

helper = master_config.Helper(defaults)
B = helper.Builder
F = helper.Factory
S = helper.Scheduler

def win(): return chromium_factory.ChromiumFactory('src/build', 'win32')
def linux(): return chromium_factory.ChromiumFactory('src/build', 'linux2')
def mac(): return chromium_factory.ChromiumFactory('src/build', 'darwin')

defaults['category'] = '1lkgr'

# Global scheduler
S('chromium_lkgr', branch='src', treeStableTimer=1, categories=['lkgr'])

################################################################################
## Windows
################################################################################

B('Win', 'win_full', 'compile|windows', 'chromium_lkgr')
F('win_full', win().ChromiumFactory(
    clobber=True,
    project='all.sln',
    factory_properties={'archive_build': True,
                        'gs_bucket': 'gs://chromium-browser-continuous',
                        'gs_acl': 'public-read',}))

################################################################################
## Mac
################################################################################

B('Mac', 'mac_full', 'compile|testers', 'chromium_lkgr')
F('mac_full', mac().ChromiumFactory(
    clobber=True,
    factory_properties={'archive_build': True,
                        'gs_bucket': 'gs://chromium-browser-continuous',
                        'gs_acl': 'public-read',}))

B('Mac ASAN Release', 'mac_asan_rel', 'compile', 'chromium_lkgr')
F('mac_asan_rel', linux().ChromiumASANFactory(
    clobber=True,
    options=['--compiler=goma-clang', '--disable-aslr', '--', '-target',
             'chromium_builder_asan_mac'],
    factory_properties={
       'asan_archive_build': True,
       'gs_bucket': 'gs://chromium-browser-asan',
       'gs_acl': 'public-read',
       'gclient_env': {'GYP_DEFINES': 'asan=1 '}}))

B('Mac ASAN Debug', 'mac_asan_dbg', 'compile', 'chromium_lkgr')
F('mac_asan_dbg', linux().ChromiumASANFactory(
    clobber=True,
    target='Debug',
    options=['--compiler=goma-clang', '--disable-aslr', '--', '-target',
             'chromium_builder_asan_mac'],
    factory_properties={
       'asan_archive_build': True,
       'gs_bucket': 'gs://chromium-browser-asan',
       'gs_acl': 'public-read',
       'gclient_env': {'GYP_DEFINES': 'asan=1 '}}))

################################################################################
## Linux
################################################################################

B('Linux', 'linux_full', 'compile|testers', 'chromium_lkgr')
F('linux_full', linux().ChromiumFactory(
    clobber=True,
    factory_properties={'archive_build': True,
                        'gs_bucket': 'gs://chromium-browser-continuous',
                        'gs_acl': 'public-read',}))

B('Linux x64', 'linux64_full', 'compile|testers', 'chromium_lkgr')
F('linux64_full', linux().ChromiumFactory(
    clobber=True,
    factory_properties={
        'archive_build': True,
        'gs_bucket': 'gs://chromium-browser-continuous',
        'gs_acl': 'public-read',
        'gclient_env': {'GYP_DEFINES':'target_arch=x64'}}))

B('ASAN Release', 'linux_asan_rel', 'compile', 'chromium_lkgr')
F('linux_asan_rel', linux().ChromiumASANFactory(
    clobber=True,
    options=['--compiler=clang', 'chrome', 'dns_fuzz_stub', 'DumpRenderTree'],
    factory_properties={
       'asan_archive_build': True,
       'gs_bucket': 'gs://chromium-browser-asan',
       'gs_acl': 'public-read',
       'gclient_env': {'GYP_DEFINES': 'asan=1 linux_use_tcmalloc=0 '}}))

asan_gyp = ('asan=1 linux_use_tcmalloc=0 '
            'release_extra_cflags="-g -O1 -fno-inline-functions -fno-inline"')

B('ASAN Release (symbolized)', 'linux_asan_rel_sym', 'compile', 'chromium_lkgr')
F('linux_asan_rel_sym', linux().ChromiumASANFactory(
    clobber=True,
    options=['--compiler=clang', 'chrome', 'dns_fuzz_stub', 'DumpRenderTree'],
    factory_properties={
       'asan_archive_build': True,
       'asan_archive_name': 'asan-symbolized',
       'gs_bucket': 'gs://chromium-browser-asan',
       'gs_acl': 'public-read',
       'gclient_env': {'GYP_DEFINES': asan_gyp}}))

B('ASAN Debug', 'linux_asan_dbg', 'compile', 'chromium_lkgr')
F('linux_asan_dbg', linux().ChromiumASANFactory(
    clobber=True,
    target='Debug',
    options=['--compiler=clang', 'chrome', 'dns_fuzz_stub', 'DumpRenderTree'],
    factory_properties={
       'asan_archive_build': True,
       'gs_bucket': 'gs://chromium-browser-asan',
       'gs_acl': 'public-read',
       'gclient_env': {'GYP_DEFINES': 'asan=1 linux_use_tcmalloc=0 '}}))

def Update(config, active_master, c):
  return helper.Update(c)
<commit_msg>Force asan debug to use component=static_library<commit_after># Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from master import master_config
from master.factory import chromium_factory

defaults = {}

helper = master_config.Helper(defaults)
B = helper.Builder
F = helper.Factory
S = helper.Scheduler

def win(): return chromium_factory.ChromiumFactory('src/build', 'win32')
def linux(): return chromium_factory.ChromiumFactory('src/build', 'linux2')
def mac(): return chromium_factory.ChromiumFactory('src/build', 'darwin')

defaults['category'] = '1lkgr'

# Global scheduler
S('chromium_lkgr', branch='src', treeStableTimer=1, categories=['lkgr'])

################################################################################
## Windows
################################################################################

B('Win', 'win_full', 'compile|windows', 'chromium_lkgr')
F('win_full', win().ChromiumFactory(
    clobber=True,
    project='all.sln',
    factory_properties={'archive_build': True,
                        'gs_bucket': 'gs://chromium-browser-continuous',
                        'gs_acl': 'public-read',}))

################################################################################
## Mac
################################################################################

B('Mac', 'mac_full', 'compile|testers', 'chromium_lkgr')
F('mac_full', mac().ChromiumFactory(
    clobber=True,
    factory_properties={'archive_build': True,
                        'gs_bucket': 'gs://chromium-browser-continuous',
                        'gs_acl': 'public-read',}))

B('Mac ASAN Release', 'mac_asan_rel', 'compile', 'chromium_lkgr')
F('mac_asan_rel', linux().ChromiumASANFactory(
    clobber=True,
    options=['--compiler=goma-clang', '--disable-aslr', '--', '-target',
             'chromium_builder_asan_mac'],
    factory_properties={
       'asan_archive_build': True,
       'gs_bucket': 'gs://chromium-browser-asan',
       'gs_acl': 'public-read',
       'gclient_env': {'GYP_DEFINES': 'asan=1 '}}))

B('Mac ASAN Debug', 'mac_asan_dbg', 'compile', 'chromium_lkgr')
F('mac_asan_dbg', linux().ChromiumASANFactory(
    clobber=True,
    target='Debug',
    options=['--compiler=goma-clang', '--disable-aslr', '--', '-target',
             'chromium_builder_asan_mac'],
    factory_properties={
       'asan_archive_build': True,
       'gs_bucket': 'gs://chromium-browser-asan',
       'gs_acl': 'public-read',
       'gclient_env': {'GYP_DEFINES': 'asan=1 component=static_library '}}))

################################################################################
## Linux
################################################################################

B('Linux', 'linux_full', 'compile|testers', 'chromium_lkgr')
F('linux_full', linux().ChromiumFactory(
    clobber=True,
    factory_properties={'archive_build': True,
                        'gs_bucket': 'gs://chromium-browser-continuous',
                        'gs_acl': 'public-read',}))

B('Linux x64', 'linux64_full', 'compile|testers', 'chromium_lkgr')
F('linux64_full', linux().ChromiumFactory(
    clobber=True,
    factory_properties={
        'archive_build': True,
        'gs_bucket': 'gs://chromium-browser-continuous',
        'gs_acl': 'public-read',
        'gclient_env': {'GYP_DEFINES':'target_arch=x64'}}))

B('ASAN Release', 'linux_asan_rel', 'compile', 'chromium_lkgr')
F('linux_asan_rel', linux().ChromiumASANFactory(
    clobber=True,
    options=['--compiler=clang', 'chrome', 'dns_fuzz_stub', 'DumpRenderTree'],
    factory_properties={
       'asan_archive_build': True,
       'gs_bucket': 'gs://chromium-browser-asan',
       'gs_acl': 'public-read',
       'gclient_env': {'GYP_DEFINES': 'asan=1 linux_use_tcmalloc=0 '}}))

asan_gyp = ('asan=1 linux_use_tcmalloc=0 '
            'release_extra_cflags="-g -O1 -fno-inline-functions -fno-inline"')

B('ASAN Release (symbolized)', 'linux_asan_rel_sym', 'compile', 'chromium_lkgr')
F('linux_asan_rel_sym', linux().ChromiumASANFactory(
    clobber=True,
    options=['--compiler=clang', 'chrome', 'dns_fuzz_stub', 'DumpRenderTree'],
    factory_properties={
       'asan_archive_build': True,
       'asan_archive_name': 'asan-symbolized',
       'gs_bucket': 'gs://chromium-browser-asan',
       'gs_acl': 'public-read',
       'gclient_env': {'GYP_DEFINES': asan_gyp}}))

B('ASAN Debug', 'linux_asan_dbg', 'compile', 'chromium_lkgr')
F('linux_asan_dbg', linux().ChromiumASANFactory(
    clobber=True,
    target='Debug',
    options=['--compiler=clang', 'chrome', 'dns_fuzz_stub', 'DumpRenderTree'],
    factory_properties={
       'asan_archive_build': True,
       'gs_bucket': 'gs://chromium-browser-asan',
       'gs_acl': 'public-read',
       'gclient_env': {'GYP_DEFINES': 'asan=1 linux_use_tcmalloc=0 '}}))

def Update(config, active_master, c):
  return helper.Update(c)
<|endoftext|>


<commit_before>###############################################################################
#   lazyflow: data flow based lazy parallel computation framework
#
#       Copyright (C) 2011-2014, the ilastik developers
#                                <team@ilastik.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the Lesser GNU General Public License
# as published by the Free Software Foundation; either version 2.1
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# See the files LICENSE.lgpl2 and LICENSE.lgpl3 for full text of the
# GNU Lesser General Public License version 2.1 and 3 respectively.
# This information is also available on the ilastik web site at:
#                 http://ilastik.org/license/
###############################################################################
import os

class PathComponents(object):
    """
    Provides a convenient access to path components of a combined external/internal path to a dataset.
    Also, each of the properties listed below is writable, in which case ALL properties are updated accordingly.
    """

    # Only files with these extensions are allowed to have an 'internal' path
    HDF5_EXTS = ['.ilp', '.h5', '.hdf5']

    def __init__(self, totalPath, cwd=None):
        """
        Initialize the path components.

        :param totalPath: The entire path to the dataset, including any internal path (e.g. the path to an hdf5 dataset).
                          For example, ``totalPath='/some/path/to/file.h5/with/internal/dataset'``

        :param cwd: If provided, relative paths will be converted to absolute paths using this arg as the working directory.
        """
        self._externalPath = None
        self._externalDirectory = None
        self._filename = None
        self._filenameBase = None
        self._extension = None
        self._internalPath = None
        self._internalDatasetName = None
        self._internalDirectory = None

        self._cwd = cwd
        self._init(totalPath, cwd)
        self._initialized = True

    def _init(self, totalPath, cwd):
        ext = None
        extIndex = -1

        if cwd is not None:
            absPath, relPath = getPathVariants( totalPath, cwd )
            totalPath = absPath

        #convention for Windows: use "/"
        totalPath = totalPath.replace("\\","/")

        # For hdf5 paths, split into external, extension, and internal paths
        for x in self.HDF5_EXTS:
            if totalPath.find(x) > extIndex:
                extIndex = totalPath.find(x)
                ext = x

        # Comments below refer to this example path:
        # /some/path/to/file.h5/with/internal/dataset
        if ext is not None:
            self._extension = ext                              # .h5
            parts = totalPath.split(ext)

            # Must deal with pathological filenames such as /path/to/file.h5_with_duplicate_ext.h5
            while len(parts) > 2:
                parts[0] = parts[0] + ext + parts[1]
                del parts[1]
            self._externalPath = parts[0] + ext # /some/path/to/file.h5
            self._internalPath = parts[1].replace('\\', '/') # /with/internal/dataset

            self._internalDirectory = os.path.split( self.internalPath )[0]   # /with/internal
            self._internalDatasetName = os.path.split( self.internalPath )[1] # dataset
        else:
            # For non-hdf5 files, use normal path/extension (no internal path)
            (self._externalPath, self._extension) = os.path.splitext(totalPath)
            self._externalPath += self._extension
            self._internalPath = None
            self._internalDatasetName = None
            self._internalDirectory = None

        self._externalDirectory = os.path.split( self._externalPath )[0] # /some/path/to
        self._filename = os.path.split( self._externalPath )[1]          # file.h5
        self._filenameBase = os.path.splitext(self._filename)[0]         # file

    def __setattr__(self, attr, value):
        """
        This prevents us from accidentally writing to a non-existant attribute.
        e.g. if the user tries to say components.fIlEnAmE = 'newfile.h5', raise an error.
        """
        if hasattr( self, '_initialized' ):
            # Attempt to get the old attribute first
            oldval = getattr(self, attr)
        object.__setattr__( self, attr, value )

    def totalPath(self):
        """
        Return the (reconstructed) totalPath to the dataset.
        """
        total = self.externalPath
        if self.internalPath:
            total += self.internalPath
        return total

    #
    # Getters
    #

    @property
    def externalPath(self):
        """
        Example: ``/some/path/to/file.h5``
        """
        return self._externalPath

    @property
    def externalDirectory(self):
        """
        Example: ``/some/path/to``
        """
        return self._externalDirectory

    @property
    def filename(self):
        """
        Example: ``file.h5``
        """
        return self._filename

    @property
    def filenameBase(self):
        """
        Example: ``file``
        """
        return self._filenameBase

    @property
    def extension(self):
        """
        Example: ``.h5``
        """
        return self._extension

    @property
    def internalPath(self):
        """
        Example: ``/with/internal/dataset``
        """
        return self._internalPath

    @property
    def internalDatasetName(self):
        """
        Example: ``/dataset``
        """
        return self._internalDatasetName

    @property
    def internalDirectory(self):
        """
        Example: ``/with/internal``
        """
        return self._internalDirectory

    #
    # Setters
    #

    @externalPath.setter
    def externalPath(self, new):
        assert new[-1] != '/'
        if self._internalPath:
            self._init( new + self._internalPath, self._cwd )
        else:
            self._init( new, self._cwd )

    @externalDirectory.setter
    def externalDirectory(self, new):
        new_external = os.path.join(new, self._filename)
        self.externalPath = new_external

    @filename.setter
    def filename(self, new):
        new_external = os.path.join( self._externalDirectory, new )
        self.externalPath = new_external

    @filenameBase.setter
    def filenameBase(self, new):
        new_external = os.path.join( self._externalDirectory, new + self._extension )
        self.externalPath = new_external

    @extension.setter
    def extension(self, new):
        assert (not self._internalPath) or (new in self.HDF5_EXTS), \
            "This PathComponents has an internal path ({}), but you are "\
            "attempting to assign a non-hdf5 extension to it ({})"\
            .format( self._internalPath, new )
        new_external = os.path.join( self._externalDirectory, self._filenameBase + new )
        self.externalPath = new_external

    @internalPath.setter
    def internalPath(self, new):
        assert self._extension in self.HDF5_EXTS, \
            "Can't set an internal path on a filename with extension {}".format( self._extension )
        if new:
            self._init( self._externalPath + new, self._cwd )
        else:
            self._init( self._externalPath, self._cwd )

    @internalDatasetName.setter
    def internalDatasetName(self, new):
        new_internal = os.path.join(self._internalDirectory, new)
        self.internalPath = new_internal

    @internalDirectory.setter
    def internalDirectory(self, new):
        if new and new[0] != '/':
            new = '/' + new
        new_internal = os.path.join( new, self._internalDatasetName )
        self.internalPath = new_internal

def areOnSameDrive(path1,path2):
    #if one path is relative, assume they are on same drive
    if isUrl(path1) or isUrl(path2):
        return False
    if not os.path.isabs(path1) or not os.path.isabs(path2):
        return True
    drive1,path1 = os.path.splitdrive(path1)
    drive2,path2 = os.path.splitdrive(path2)
    return drive1==drive2

def compressPathForDisplay(pathstr,maxlength):
    '''Add alternatingly parts of the start and the end of the path
    until maxlength is exceeded. Result: Drive/Dir1/.../Dirn/file'''
    if len(pathstr) <= maxlength:
        return pathstr
    dots = '...'
    component_list = pathstr.split("/")
    prefix = ""
    suffix = "/" + component_list.pop(-1)
    while component_list:
        restlength = maxlength - len(prefix) - len(dots)
        suffix = '/' + component_list.pop(-1) + suffix
        if len(suffix) > restlength:
            suffix = suffix[-restlength:]
            break
        if not component_list:
            break
        c = prefix + component_list.pop(0) + "/"
        if len(c)+len(dots)+len(suffix) > maxlength:
            break
        prefix = c
    return prefix + dots + suffix

def isUrl(path):
    # For now, the simplest rule will work.
    return '://' in path

def getPathVariants(originalPath, workingDirectory):
    """
    Take the given filePath (which can be absolute or relative, and may include an internal path suffix),
    and return a tuple of the absolute and relative paths to the file.
    """
    # urls are considered absolute
    if isUrl(originalPath):
        return originalPath, None

    if len(originalPath) > 0 and originalPath[0] == '~':
        originalPath = os.path.expanduser(originalPath)

    relPath = originalPath

    if os.path.isabs(originalPath):
        absPath = originalPath
        if areOnSameDrive(originalPath,workingDirectory):
            relPath = os.path.relpath(absPath, workingDirectory).replace("\\","/")
        else:
            # Relative path does not always exist.  Caller must check for None.
            relPath = None
    else:
        relPath = originalPath
        absPath = os.path.normpath( os.path.join(workingDirectory, relPath) )

    return (absPath, relPath)
<commit_msg>nanshe/util/pathHelpers.py: Just update the copy of path helpers from `lazyflow` ( ilastik/lazyflow@513274af8eccce109092f33c2b6c5beb8e81579f ).<commit_after>###############################################################################
#   lazyflow: data flow based lazy parallel computation framework
#
#       Copyright (C) 2011-2014, the ilastik developers
#                                <team@ilastik.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the Lesser GNU General Public License
# as published by the Free Software Foundation; either version 2.1
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# See the files LICENSE.lgpl2 and LICENSE.lgpl3 for full text of the
# GNU Lesser General Public License version 2.1 and 3 respectively.
# This information is also available on the ilastik web site at:
#                 http://ilastik.org/license/
###############################################################################
import os

class PathComponents(object):
    """
    Provides a convenient access to path components of a combined external/internal path to a dataset.
    Also, each of the properties listed below is writable, in which case ALL properties are updated accordingly.
    """

    # Only files with these extensions are allowed to have an 'internal' path
    HDF5_EXTS = ['.ilp', '.h5', '.hdf5']

    def __init__(self, totalPath, cwd=None):
        """
        Initialize the path components.

        :param totalPath: The entire path to the dataset, including any internal path (e.g. the path to an hdf5 dataset).
                          For example, ``totalPath='/some/path/to/file.h5/with/internal/dataset'``

        :param cwd: If provided, relative paths will be converted to absolute paths using this arg as the working directory.
        """
        self._externalPath = None
        self._externalDirectory = None
        self._filename = None
        self._filenameBase = None
        self._extension = None
        self._internalPath = None
        self._internalDatasetName = None
        self._internalDirectory = None

        self._cwd = cwd
        self._init(totalPath, cwd)
        self._initialized = True

    def _init(self, totalPath, cwd):
        ext = None
        extIndex = -1

        if cwd is not None:
            absPath, relPath = getPathVariants( totalPath, cwd )
            totalPath = absPath

        #convention for Windows: use "/"
        totalPath = totalPath.replace("\\","/")

        # For hdf5 paths, split into external, extension, and internal paths
        for x in self.HDF5_EXTS:
            if totalPath.find(x) > extIndex:
                extIndex = totalPath.find(x)
                ext = x

        # Comments below refer to this example path:
        # /some/path/to/file.h5/with/internal/dataset
        if ext is not None:
            self._extension = ext                              # .h5
            parts = totalPath.split(ext)

            # Must deal with pathological filenames such as /path/to/file.h5_with_duplicate_ext.h5
            while len(parts) > 2:
                parts[0] = parts[0] + ext + parts[1]
                del parts[1]
            self._externalPath = parts[0] + ext # /some/path/to/file.h5
            self._internalPath = parts[1].replace('\\', '/') # /with/internal/dataset

            self._internalDirectory = os.path.split( self.internalPath )[0]   # /with/internal
            self._internalDatasetName = os.path.split( self.internalPath )[1] # dataset
        else:
            # For non-hdf5 files, use normal path/extension (no internal path)
            (self._externalPath, self._extension) = os.path.splitext(totalPath)
            self._externalPath += self._extension
            self._internalPath = None
            self._internalDatasetName = None
            self._internalDirectory = None

        self._externalDirectory = os.path.split( self._externalPath )[0] # /some/path/to
        self._filename = os.path.split( self._externalPath )[1]          # file.h5
        self._filenameBase = os.path.splitext(self._filename)[0]         # file

    def __setattr__(self, attr, value):
        """
        This prevents us from accidentally writing to a non-existant attribute.
        e.g. if the user tries to say components.fIlEnAmE = 'newfile.h5', raise an error.
        """
        if hasattr( self, '_initialized' ):
            # Attempt to get the old attribute first
            oldval = getattr(self, attr)
        object.__setattr__( self, attr, value )

    def totalPath(self):
        """
        Return the (reconstructed) totalPath to the dataset.
        """
        total = self.externalPath
        if self.internalPath:
            total += self.internalPath
        return total

    #
    # Getters
    #

    @property
    def externalPath(self):
        """
        Example: ``/some/path/to/file.h5``
        """
        return self._externalPath

    @property
    def externalDirectory(self):
        """
        Example: ``/some/path/to``
        """
        return self._externalDirectory

    @property
    def filename(self):
        """
        Example: ``file.h5``
        """
        return self._filename

    @property
    def filenameBase(self):
        """
        Example: ``file``
        """
        return self._filenameBase

    @property
    def extension(self):
        """
        Example: ``.h5``
        """
        return self._extension

    @property
    def internalPath(self):
        """
        Example: ``/with/internal/dataset``
        """
        return self._internalPath

    @property
    def internalDatasetName(self):
        """
        Example: ``/dataset``
        """
        return self._internalDatasetName

    @property
    def internalDirectory(self):
        """
        Example: ``/with/internal``
        """
        return self._internalDirectory

    #
    # Setters
    #

    @externalPath.setter
    def externalPath(self, new):
        assert new[-1] != '/'
        if self._internalPath:
            self._init( new + self._internalPath, self._cwd )
        else:
            self._init( new, self._cwd )

    @externalDirectory.setter
    def externalDirectory(self, new):
        new_external = os.path.join(new, self._filename)
        self.externalPath = new_external

    @filename.setter
    def filename(self, new):
        new_external = os.path.join( self._externalDirectory, new )
        self.externalPath = new_external

    @filenameBase.setter
    def filenameBase(self, new):
        new_external = os.path.join( self._externalDirectory, new + self._extension )
        self.externalPath = new_external

    @extension.setter
    def extension(self, new):
        assert (not self._internalPath) or (new in self.HDF5_EXTS), \
            "This PathComponents has an internal path ({}), but you are "\
            "attempting to assign a non-hdf5 extension to it ({})"\
            .format( self._internalPath, new )
        new_external = os.path.join( self._externalDirectory, self._filenameBase + new )
        self.externalPath = new_external

    @internalPath.setter
    def internalPath(self, new):
        assert self._extension in self.HDF5_EXTS, \
            "Can't set an internal path on a filename with extension {}".format( self._extension )
        if new:
            self._init( self._externalPath + new, self._cwd )
        else:
            self._init( self._externalPath, self._cwd )

    @internalDatasetName.setter
    def internalDatasetName(self, new):
        new_internal = os.path.join(self._internalDirectory, new)
        self.internalPath = new_internal

    @internalDirectory.setter
    def internalDirectory(self, new):
        if new and new[0] != '/':
            new = '/' + new
        new_internal = os.path.join( new, self._internalDatasetName )
        self.internalPath = new_internal

def areOnSameDrive(path1,path2):
    #if one path is relative, assume they are on same drive
    if isUrl(path1) or isUrl(path2):
        return False
    if not os.path.isabs(path1) or not os.path.isabs(path2):
        return True
    drive1,path1 = os.path.splitdrive(path1)
    drive2,path2 = os.path.splitdrive(path2)
    return drive1==drive2

def compressPathForDisplay(pathstr,maxlength):
    '''Add alternatingly parts of the start and the end of the path
    until maxlength is exceeded. Result: Drive/Dir1/.../Dirn/file'''
    if len(pathstr) <= maxlength:
        return pathstr
    dots = '...'
    component_list = pathstr.split("/")
    prefix = ""
    suffix = "/" + component_list.pop(-1)
    while component_list:
        restlength = maxlength - len(prefix) - len(dots)
        suffix = '/' + component_list.pop(-1) + suffix
        if len(suffix) > restlength:
            suffix = suffix[-restlength:]
            break
        if not component_list:
            break
        c = prefix + component_list.pop(0) + "/"
        if len(c)+len(dots)+len(suffix) > maxlength:
            break
        prefix = c
    return prefix + dots + suffix

def isUrl(path):
    # For now, the simplest rule will work.
    return '://' in path

def getPathVariants(originalPath, workingDirectory):
    """
    Take the given filePath (which can be absolute or relative, and may include an internal path suffix),
    and return a tuple of the absolute and relative paths to the file.
    """
    # urls are considered absolute
    if isUrl(originalPath):
        return originalPath, None

    if len(originalPath) > 0 and originalPath[0] == '~':
        originalPath = os.path.expanduser(originalPath)

    relPath = originalPath

    if os.path.isabs(originalPath):
        absPath = originalPath
        if areOnSameDrive(originalPath,workingDirectory):
            relPath = os.path.relpath(absPath, workingDirectory).replace("\\","/")
        else:
            # Relative path does not always exist.  Caller must check for None.
            relPath = None
    else:
        relPath = originalPath
        absPath = os.path.normpath( os.path.join(workingDirectory, relPath) )

    return (absPath, relPath)
<|endoftext|>


<commit_before># ======================================================================
# matscipy - Python materials science tools
# https://github.com/libAtoms/matscipy
#
# Copyright (2014-2018) James Kermode, King's College London
#                       Lars Pastewka, University of Freiburg
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# ======================================================================

from __future__ import division

import os

import sys

import time

import numpy as np

from scipy.special import factorial2

import ase

from ase.calculators.calculator import Calculator

from matscipy.neighbours import neighbour_list, first_neighbours

###

class IPL():
    """
    Functional form for a smoothed inverse-power-law potential (IPL) with an exponent of 10.

    Parameters
    ----------
    epsilon : float
        Energy scale
    cutoff : float
        Cutoff for the pair-interaction
    minSize : float
        Minimal size of a particle. Lower bound of distribtuion
    maxSize : float
        Maximal size of a particle. Upper bound of distribtuion
    na : float
        Non-additivity paramter for pair sizes
    q : int
        Smooth the potential up to the q-th derivative.
        For q=0 the potential is smoothed, for q=1 the potential
        and its first derivative are zero at the cutoff.

    Reference:
    ----------
        E. Lerner, Journal of Non-Crystalline Solids, 522, 119570.
    """

    def __init__(self, epsilon, cutoff, na, q, minSize, maxSize):
        self.epsilon = epsilon
        self.cutoff = cutoff
        self.minSize = minSize
        self.maxSize = maxSize
        self.na = na
        self.q = q
        self.coeffs = []
        for index in range(0,q+1):
            first_expr = np.power(-1, index+1)/(factorial2(2*q-2*index, exact=True)*factorial2(2*index, exact=True))
            second_expr = factorial2(10+2*q, exact=True)/(factorial2(10-2)*(10+2*index))
            third_expr = np.power(cutoff, -(10+2*index))
            self.coeffs.append(first_expr*second_expr*third_expr)

    def __call__(self, r, ijsize):
        """
        Return function value (potential energy)
        """
        ipl = self.epsilon*np.power(ijsize,10)/np.power(r,10)
        for l in range(0,self.q+1):
            ipl += self.epsilon*self.coeffs[l]*np.power(r/ijsize,2*l)

        return ipl

    def mix_sizes(self, isize, jsize):
        """
        Nonadditive interaction rule for the cross size of particles i and j.
        """
        return 0.5*(isize+jsize)*(1 - self.na * np.absolute(isize-jsize))

    def get_cutoff(self):
        """
        Return the cutoff.
        """
        return self.cutoff

    def get_coeffs(self):
        """
        Return the smoothing coefficients of the potential.
        """
        return self.coeffs

    def get_maxSize(self):
        """
        Return the maximal size of a particle (=Upper boundary of distribution)
        """
        return self.maxSize

    def get_minSize(self):
        """
        Return the minimal size of a particle (=Lower boundary of distribution)
        """
        return self.minSize

    def first_derivative(self, r, ijsize):
        """
        Return first derivative
        """
        dipl = -10*self.epsilon*np.power(ijsize,10)/np.power(r,11)
        for l in range(0,self.q+1):
            dipl += self.epsilon*2*l*self.coeffs[l]*np.power(r, 2*l-1)/np.power(ijsize, 2*l)

        return dipl

    def second_derivative(self, r, ijsize):
        """
        Return second derivative
        """
        ddipl = 110*self.epsilon*np.power(ijsize,10)/np.power(r,12)
        for l in range(0,self.q+1):
            ddipl = self.epsilon*(4*np.power(l,2)-2*l)*self.coeffs[l]*np.power(r, 2*l-2)/np.power(ijsize,2*l)
        return ddipl

    def derivative(self, n=1):
        if n == 1:
            return self.first_derivative
        elif n == 2:
            return self.second_derivative
        else:
            raise ValueError(
                "Don't know how to compute {}-th derivative.".format(n))

###

class Polydisperse(Calculator):
    implemented_properties = ["energy", "stress", "forces"]
    default_parameters = {}
    name = "Polydisperse"

    def __init__(self, f, cutoff=None):
        Calculator.__init__(self)
        self.f = f

    def calculate(self, atoms, properties, system_changes):
        Calculator.calculate(self, atoms, properties, system_changes)

        f = self.f
        nat = len(self.atoms)
        if atoms.has("size"):
            size = self.atoms.get_array("size")
        else:
            raise AttributeError(
                "Attribute error: Unable to load atom sizes from atoms object! Probably missing size array.")

        i_n, j_n, dr_nc, abs_dr_n = neighbour_list("ijDd", self.atoms, f.get_maxSize()*f.get_cutoff())
        ijsize = f.mix_sizes(size[i_n], size[j_n])

        # Mask neighbour list to consider only true neighbors
        mask = abs_dr_n <= f.get_cutoff()*ijsize
        i_n = i_n[mask]
        j_n = j_n[mask]
        dr_nc = dr_nc[mask]
        abs_dr_n = abs_dr_n[mask]
        ijsize = ijsize[mask]

        e_n = np.zeros_like(abs_dr_n)
        de_n = np.zeros_like(abs_dr_n)
        e_n = f(abs_dr_n, ijsize)
        de_n[mask] = f.first_derivative(abs_dr_n, ijsize)

        # Energy
        epot = 0.5*np.sum(e_n)

        # Forces
        df_nc = -0.5*de_n.reshape(-1,1)*dr_nc/abs_dr_n.reshape(-1,1)

        # Sum for each atom
        fx_i = np.bincount(j_n, weights=df_nc[:, 0], minlength=nat) - \
            np.bincount(i_n, weights=df_nc[:, 0], minlength=nat)
        fy_i = np.bincount(j_n, weights=df_nc[:, 1], minlength=nat) - \
            np.bincount(i_n, weights=df_nc[:, 1], minlength=nat)
        fz_i = np.bincount(j_n, weights=df_nc[:, 2], minlength=nat) - \
            np.bincount(i_n, weights=df_nc[:, 2], minlength=nat)

        # Virial
        virial_v = -np.array([dr_nc[:, 0]*df_nc[:, 0],               # xx
                              dr_nc[:, 1]*df_nc[:, 1],               # yy
                              dr_nc[:, 2]*df_nc[:, 2],               # zz
                              dr_nc[:, 1]*df_nc[:, 2],               # yz
                              dr_nc[:, 0]*df_nc[:, 2],               # xz
                              dr_nc[:, 0]*df_nc[:, 1]]).sum(axis=1)  # xy

        self.results = {'energy': epot,
                        'stress': virial_v/self.atoms.get_volume(),
                        'forces': np.transpose([fx_i, fy_i, fz_i])}

    ###

    def hessian_matrix(self, atoms, H_format="dense", divide_by_masses=False):
        """
        Calculate the Hessian matrix for a polydisperse systems where atoms interact via a pair potential.
        For an atomic configuration with N atoms in d dimensions the hessian matrix is a symmetric, hermitian matrix
        with a shape of (d*N,d*N). The matrix is due to the cutoff function a sparse matrix, which consists of dense blocks of shape (d,d), which
        are the mixed second derivatives. The result of the derivation for a pair potential can be found in:
        L. Pastewka et. al. "Seamless elastic boundaries for atomistic calculations", Phys. Ev. B 86, 075459 (2012).

        Parameters
        ----------
        atoms: ase.Atoms
            Atomic configuration in a local or global minima.
        H_format: "dense" or "sparse"
            Output format of the hessian matrix.
            The format "sparse" is only possible if matscipy was build with scipy.
        divide_by_masses: bool
            Divide the block "l,m" by the corresponding atomic masses "sqrt(m_l, m_m)" to obtain dynamical matrix.

        Restrictions
        ----------
        This method is currently only implemented for three dimensional systems

        """

        if H_format == "sparse":
            try:
                from scipy.sparse import bsr_matrix
            except ImportError:
                raise ImportError(
                    "Import Error: Can not output the hessian matrix since scipy.sparse could not be loaded!")

        f = self.f
        nat = len(self.atoms)
        if atoms.has("size"):
            size = self.atoms.get_array("size")
        else:
            raise AttributeError(
                "Attribute error: Unable to load atom sizes from atoms object! Probably missing size array.")

        i_n, j_n, dr_nc, abs_dr_n = neighbour_list("ijDd", self.atoms, f.get_maxSize()*f.get_cutoff())
        ijsize = f.mix_sizes(size[i_n], size[j_n])

        # Mask neighbour list to consider only true neighbors
        mask = abs_dr_n <= f.get_cutoff()*ijsize
        i_n = i_n[mask]
        j_n = j_n[mask]
        dr_nc = dr_nc[mask]
        abs_dr_n = abs_dr_n[mask]
        ijsize = ijsize[mask]

        first_i = first_neighbours(nat, i_n)
        if divide_by_masses:
            mass_nat = self.atoms.get_masses()
            geom_mean_mass_n = np.sqrt(mass_nat[i_n]*mass_nat[j_n])

        e_n = np.zeros_like(abs_dr_n)
        de_n = np.zeros_like(abs_dr_n)
        dde_n = np.zeros_like(abs_dr_n)

        e_n = f(abs_dr_n, ijsize)
        de_n = f.first_derivative(abs_dr_n, ijsize)
        dde_n = f.second_derivative(abs_dr_n, ijsize)

        # Hessian in sparse matrix format
        if H_format == "sparse":
            e_nc = (dr_nc.T/abs_dr_n).T
            H_ncc = -(dde_n * (e_nc.reshape(-1,3,1) * e_nc.reshape(-1,1,3)).T).T
            H_ncc += -(de_n/abs_dr_n * (np.eye(3, dtype=e_nc.dtype) - (e_nc.reshape(-1,3,1) * e_nc.reshape(-1,1,3))).T)

            if divide_by_masses:
                H = bsr_matrix(((H_ncc/geom_mean_mass_n).T, j_n, first_i), shape=(3*nat, 3*nat))
            else:
                H = bsr_matrix((H_ncc.T, j_n, first_i), shape=(3*nat, 3*nat))

            Hdiag_icc = np.empty((nat, 3, 3))

            for x in range(3):
                for y in range(3):
                    Hdiag_icc[:, x, y] = - np.bincount(i_n, weights=H_ncc.T[:, x, y])

            if divide_by_masses:
                Hdiag_icc /= mass_nat

            H += bsr_matrix((Hdiag_ncc, np.arange(nat), np.arange(nat+1)), shape=(3*nat, 3*nat))

            return H

        # Hessian in dense matrix format
        else:
            e_nc = (dr_nc.T/abs_dr_n).T
            H_ncc = -(dde_n * (e_nc.reshape(-1,3,1) * e_nc.reshape(-1,1,3)).T).T
            H_ncc += -(de_n/abs_dr_n * (np.eye(3, dtype=e_nc.dtype) - (e_nc.reshape(-1,3,1) * e_nc.reshape(-1,1,3))).T)

            H = np.zeros((3*nat, 3*nat))
            if divide_by_masses:
                for atom in range(len(i_n)):
                    H[3*i_n[atom]:3*i_n[atom]+3,3*j_n[atom]:3*j_n[atom]+3] += H_ncc[atom]/geom_mean_mass_n[atom]
            else:
                for atom in range(len(i_n)):
                    H[3*i_n[atom]:3*i_n[atom]+3,3*j_n[atom]:3*j_n[atom]+3] += H_ncc[atom]

            Hdiag_icc = np.empty((nat, 3, 3))
            for x in range(3):
               for y in range(3):
                   Hdiag_icc[:, x, y] = -np.bincount(i_n, weights=H_ncc[:, x, y])

            if divided_by_masses:
                for atom in range(nat):
                    H[3*atom:3*atom+3,3*atom:3*atom+3] += Hdiag_icc[atom]/mass_nat[atom]
            else:
                for atom in range(nat):
                    H[3*atom:3*atom+3,3*atom:3*atom+3] += Hdiag_icc[atom]

            return H
<commit_msg> - Corrected masking error<commit_after># ======================================================================
# matscipy - Python materials science tools
# https://github.com/libAtoms/matscipy
#
# Copyright (2014-2018) James Kermode, King's College London
#                       Lars Pastewka, University of Freiburg
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# ======================================================================

from __future__ import division

import os

import sys

import time

import numpy as np

from scipy.special import factorial2

import ase

from ase.calculators.calculator import Calculator

from matscipy.neighbours import neighbour_list, first_neighbours

###

class IPL():
    """
    Functional form for a smoothed inverse-power-law potential (IPL) with an exponent of 10.

    Parameters
    ----------
    epsilon : float
        Energy scale
    cutoff : float
        Cutoff for the pair-interaction
    minSize : float
        Minimal size of a particle. Lower bound of distribtuion
    maxSize : float
        Maximal size of a particle. Upper bound of distribtuion
    na : float
        Non-additivity paramter for pair sizes
    q : int
        Smooth the potential up to the q-th derivative.
        For q=0 the potential is smoothed, for q=1 the potential
        and its first derivative are zero at the cutoff.

    Reference:
    ----------
        E. Lerner, Journal of Non-Crystalline Solids, 522, 119570.
    """

    def __init__(self, epsilon, cutoff, na, q, minSize, maxSize):
        self.epsilon = epsilon
        self.cutoff = cutoff
        self.minSize = minSize
        self.maxSize = maxSize
        self.na = na
        self.q = q
        self.coeffs = []
        for index in range(0,q+1):
            first_expr = np.power(-1, index+1)/(factorial2(2*q-2*index, exact=True)*factorial2(2*index, exact=True))
            second_expr = factorial2(10+2*q, exact=True)/(factorial2(10-2)*(10+2*index))
            third_expr = np.power(cutoff, -(10+2*index))
            self.coeffs.append(first_expr*second_expr*third_expr)

    def __call__(self, r, ijsize):
        """
        Return function value (potential energy)
        """
        ipl = self.epsilon*np.power(ijsize,10)/np.power(r,10)
        for l in range(0,self.q+1):
            ipl += self.epsilon*self.coeffs[l]*np.power(r/ijsize,2*l)

        return ipl

    def mix_sizes(self, isize, jsize):
        """
        Nonadditive interaction rule for the cross size of particles i and j.
        """
        return 0.5*(isize+jsize)*(1 - self.na * np.absolute(isize-jsize))

    def get_cutoff(self):
        """
        Return the cutoff.
        """
        return self.cutoff

    def get_coeffs(self):
        """
        Return the smoothing coefficients of the potential.
        """
        return self.coeffs

    def get_maxSize(self):
        """
        Return the maximal size of a particle (=Upper boundary of distribution)
        """
        return self.maxSize

    def get_minSize(self):
        """
        Return the minimal size of a particle (=Lower boundary of distribution)
        """
        return self.minSize

    def first_derivative(self, r, ijsize):
        """
        Return first derivative
        """
        dipl = -10*self.epsilon*np.power(ijsize,10)/np.power(r,11)
        for l in range(0,self.q+1):
            dipl += self.epsilon*2*l*self.coeffs[l]*np.power(r, 2*l-1)/np.power(ijsize, 2*l)

        return dipl

    def second_derivative(self, r, ijsize):
        """
        Return second derivative
        """
        ddipl = 110*self.epsilon*np.power(ijsize,10)/np.power(r,12)
        for l in range(0,self.q+1):
            ddipl = self.epsilon*(4*np.power(l,2)-2*l)*self.coeffs[l]*np.power(r, 2*l-2)/np.power(ijsize,2*l)
        return ddipl

    def derivative(self, n=1):
        if n == 1:
            return self.first_derivative
        elif n == 2:
            return self.second_derivative
        else:
            raise ValueError(
                "Don't know how to compute {}-th derivative.".format(n))

###

class Polydisperse(Calculator):
    implemented_properties = ["energy", "stress", "forces"]
    default_parameters = {}
    name = "Polydisperse"

    def __init__(self, f, cutoff=None):
        Calculator.__init__(self)
        self.f = f

    def calculate(self, atoms, properties, system_changes):
        Calculator.calculate(self, atoms, properties, system_changes)

        f = self.f
        nat = len(self.atoms)
        if atoms.has("size"):
            size = self.atoms.get_array("size")
        else:
            raise AttributeError(
                "Attribute error: Unable to load atom sizes from atoms object! Probably missing size array.")

        i_n, j_n, dr_nc, abs_dr_n = neighbour_list("ijDd", self.atoms, f.get_maxSize()*f.get_cutoff())
        ijsize = f.mix_sizes(size[i_n], size[j_n])

        # Mask neighbour list to consider only true neighbors
        mask = abs_dr_n <= f.get_cutoff()*ijsize
        i_n = i_n[mask]
        j_n = j_n[mask]
        dr_nc = dr_nc[mask]
        abs_dr_n = abs_dr_n[mask]
        ijsize = ijsize[mask]

        e_n = np.zeros_like(abs_dr_n)
        de_n = np.zeros_like(abs_dr_n)
        e_n = f(abs_dr_n, ijsize)
        de_n = f.first_derivative(abs_dr_n, ijsize)

        # Energy
        epot = 0.5*np.sum(e_n)

        # Forces
        df_nc = -0.5*de_n.reshape(-1,1)*dr_nc/abs_dr_n.reshape(-1,1)

        # Sum for each atom
        fx_i = np.bincount(j_n, weights=df_nc[:, 0], minlength=nat) - \
            np.bincount(i_n, weights=df_nc[:, 0], minlength=nat)
        fy_i = np.bincount(j_n, weights=df_nc[:, 1], minlength=nat) - \
            np.bincount(i_n, weights=df_nc[:, 1], minlength=nat)
        fz_i = np.bincount(j_n, weights=df_nc[:, 2], minlength=nat) - \
            np.bincount(i_n, weights=df_nc[:, 2], minlength=nat)

        # Virial
        virial_v = -np.array([dr_nc[:, 0]*df_nc[:, 0],               # xx
                              dr_nc[:, 1]*df_nc[:, 1],               # yy
                              dr_nc[:, 2]*df_nc[:, 2],               # zz
                              dr_nc[:, 1]*df_nc[:, 2],               # yz
                              dr_nc[:, 0]*df_nc[:, 2],               # xz
                              dr_nc[:, 0]*df_nc[:, 1]]).sum(axis=1)  # xy

        self.results = {'energy': epot,
                        'stress': virial_v/self.atoms.get_volume(),
                        'forces': np.transpose([fx_i, fy_i, fz_i])}

    ###

    def hessian_matrix(self, atoms, H_format="dense", divide_by_masses=False):
        """
        Calculate the Hessian matrix for a polydisperse systems where atoms interact via a pair potential.
        For an atomic configuration with N atoms in d dimensions the hessian matrix is a symmetric, hermitian matrix
        with a shape of (d*N,d*N). The matrix is due to the cutoff function a sparse matrix, which consists of dense blocks of shape (d,d), which
        are the mixed second derivatives. The result of the derivation for a pair potential can be found in:
        L. Pastewka et. al. "Seamless elastic boundaries for atomistic calculations", Phys. Ev. B 86, 075459 (2012).

        Parameters
        ----------
        atoms: ase.Atoms
            Atomic configuration in a local or global minima.
        H_format: "dense" or "sparse"
            Output format of the hessian matrix.
            The format "sparse" is only possible if matscipy was build with scipy.
        divide_by_masses: bool
            Divide the block "l,m" by the corresponding atomic masses "sqrt(m_l, m_m)" to obtain dynamical matrix.

        Restrictions
        ----------
        This method is currently only implemented for three dimensional systems

        """

        if H_format == "sparse":
            try:
                from scipy.sparse import bsr_matrix
            except ImportError:
                raise ImportError(
                    "Import Error: Can not output the hessian matrix since scipy.sparse could not be loaded!")

        f = self.f
        nat = len(self.atoms)
        if atoms.has("size"):
            size = self.atoms.get_array("size")
        else:
            raise AttributeError(
                "Attribute error: Unable to load atom sizes from atoms object! Probably missing size array.")

        i_n, j_n, dr_nc, abs_dr_n = neighbour_list("ijDd", self.atoms, f.get_maxSize()*f.get_cutoff())
        ijsize = f.mix_sizes(size[i_n], size[j_n])

        # Mask neighbour list to consider only true neighbors
        mask = abs_dr_n <= f.get_cutoff()*ijsize
        i_n = i_n[mask]
        j_n = j_n[mask]
        dr_nc = dr_nc[mask]
        abs_dr_n = abs_dr_n[mask]
        ijsize = ijsize[mask]

        first_i = first_neighbours(nat, i_n)
        if divide_by_masses:
            mass_nat = self.atoms.get_masses()
            geom_mean_mass_n = np.sqrt(mass_nat[i_n]*mass_nat[j_n])

        e_n = np.zeros_like(abs_dr_n)
        de_n = np.zeros_like(abs_dr_n)
        dde_n = np.zeros_like(abs_dr_n)

        e_n = f(abs_dr_n, ijsize)
        de_n = f.first_derivative(abs_dr_n, ijsize)
        dde_n = f.second_derivative(abs_dr_n, ijsize)

        # Hessian in sparse matrix format
        if H_format == "sparse":
            e_nc = (dr_nc.T/abs_dr_n).T
            H_ncc = -(dde_n * (e_nc.reshape(-1,3,1) * e_nc.reshape(-1,1,3)).T).T
            H_ncc += -(de_n/abs_dr_n * (np.eye(3, dtype=e_nc.dtype) - (e_nc.reshape(-1,3,1) * e_nc.reshape(-1,1,3))).T)

            if divide_by_masses:
                H = bsr_matrix(((H_ncc/geom_mean_mass_n).T, j_n, first_i), shape=(3*nat, 3*nat))
            else:
                H = bsr_matrix((H_ncc.T, j_n, first_i), shape=(3*nat, 3*nat))

            Hdiag_icc = np.empty((nat, 3, 3))

            for x in range(3):
                for y in range(3):
                    Hdiag_icc[:, x, y] = - np.bincount(i_n, weights=H_ncc.T[:, x, y])

            if divide_by_masses:
                Hdiag_icc /= mass_nat

            H += bsr_matrix((Hdiag_ncc, np.arange(nat), np.arange(nat+1)), shape=(3*nat, 3*nat))

            return H

        # Hessian in dense matrix format
        else:
            e_nc = (dr_nc.T/abs_dr_n).T
            H_ncc = -(dde_n * (e_nc.reshape(-1,3,1) * e_nc.reshape(-1,1,3)).T).T
            H_ncc += -(de_n/abs_dr_n * (np.eye(3, dtype=e_nc.dtype) - (e_nc.reshape(-1,3,1) * e_nc.reshape(-1,1,3))).T)

            H = np.zeros((3*nat, 3*nat))
            if divide_by_masses:
                for atom in range(len(i_n)):
                    H[3*i_n[atom]:3*i_n[atom]+3,3*j_n[atom]:3*j_n[atom]+3] += H_ncc[atom]/geom_mean_mass_n[atom]
            else:
                for atom in range(len(i_n)):
                    H[3*i_n[atom]:3*i_n[atom]+3,3*j_n[atom]:3*j_n[atom]+3] += H_ncc[atom]

            Hdiag_icc = np.empty((nat, 3, 3))
            for x in range(3):
               for y in range(3):
                   Hdiag_icc[:, x, y] = -np.bincount(i_n, weights=H_ncc[:, x, y])

            if divided_by_masses:
                for atom in range(nat):
                    H[3*atom:3*atom+3,3*atom:3*atom+3] += Hdiag_icc[atom]/mass_nat[atom]
            else:
                for atom in range(nat):
                    H[3*atom:3*atom+3,3*atom:3*atom+3] += Hdiag_icc[atom]

            return H
<|endoftext|>


<commit_before>from __future__ import unicode_literals

import os
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.contrib.auth.models import User
from django.utils.html import format_html

@python_2_unicode_compatible
class Address(models.Model):
    address_line = models.CharField('address line', max_length=100)
    county = models.CharField('country', max_length=50)
    postcode = models.CharField('postcode', max_length=10)

    def __str__(self):
        return self.address_line + " " + self.county

@python_2_unicode_compatible
class Contact(models.Model):
    first_name = models.CharField('first name', max_length=30)
    surname = models.CharField('surname', max_length=30)
    telephone = models.CharField('telephone', max_length=15)
    mobile = models.CharField('mobile', max_length=15)
    email = models.EmailField('email', max_length=50)
    description = models.TextField('description')
    address = models.OneToOneField(Address, on_delete=models.CASCADE)

    def __str__(self):
        return self.first_name + " " + self.surname

@python_2_unicode_compatible
class Item(models.Model):
    name = models.CharField('name', max_length=50)
    description = models.TextField('description')

    def __str__(self):
        return self.name

def get_logo_file_name(instance, filename):
    return os.path.join('uploads', instance.name, 'logo' + os.path.splitext(filename)[1])

@python_2_unicode_compatible
class Organisation(models.Model):
    name = models.CharField('name', max_length=30)
    image = models.ImageField(upload_to=get_logo_file_name, blank=True)
    primary_contact = models.OneToOneField(Contact, on_delete=models.CASCADE)
    address = models.OneToOneField(Address, on_delete=models.CASCADE)
    description = models.TextField('description')
    just_giving_link = models.URLField('just giving link', max_length=255, blank=True)
    raised = models.DecimalField('raised', max_digits=25, decimal_places=2, blank=True)
    goal = models.DecimalField('goal', max_digits=25, decimal_places=2, blank=True)

    def __str__(self):
        return str(self.id) + " " + str(self.name)

    def image_preview_large(self):
        if self.image:
            return format_html(
                '',
                self.image.url
            )
        else:
            return 'No Logo'
    image_preview_large.short_description = 'Image Preview'

    def image_preview_small(self):
        if self.image:
            return format_html(
                '',
                self.image.url
            )
        else:
            return 'No Logo'
    image_preview_small.short_description = 'Image Preview'

    def associated_user_accounts(self):
        return ','.join(str(item.user.id) +': ' + item.user.username for item in self.organisationuser_set.all())
    associated_user_accounts.short_description = 'User Accounts'

    def percentage_to_fund_raising_goal(self):
        val = int(round(self.raised / self.goal * 100))
        if val > 100:
            return 100
        return val

@python_2_unicode_compatible
class Wishlist(models.Model):
    organisation = models.OneToOneField(Organisation, on_delete=models.CASCADE)
    start_time = models.DateTimeField('start_time')
    end_time = models.DateTimeField('end_time')
    reoccurring = models.BooleanField('reoccurring')
    items = models.ManyToManyField(Item)

    def __str__(self):
        return self.organisation.name + " Wishlist"

@python_2_unicode_compatible
class OrganisationUser(models.Model):
    user = models.OneToOneField(User, verbose_name="User account details")
    contact = models.OneToOneField(Contact, on_delete=models.CASCADE, verbose_name='Contact details')
    organisation = models.ForeignKey(Organisation, on_delete=models.CASCADE)

    def __str__(self):
        return self.organisation.name + " Organisation User " + str(self.user.username)<commit_msg>Remove non alphanumeric chars when creating logo path<commit_after>from __future__ import unicode_literals

import os, re
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.contrib.auth.models import User
from django.utils.html import format_html

@python_2_unicode_compatible
class Address(models.Model):
    address_line = models.CharField('address line', max_length=100)
    county = models.CharField('country', max_length=50)
    postcode = models.CharField('postcode', max_length=10)

    def __str__(self):
        return self.address_line + " " + self.county

@python_2_unicode_compatible
class Contact(models.Model):
    first_name = models.CharField('first name', max_length=30)
    surname = models.CharField('surname', max_length=30)
    telephone = models.CharField('telephone', max_length=15)
    mobile = models.CharField('mobile', max_length=15)
    email = models.EmailField('email', max_length=50)
    description = models.TextField('description')
    address = models.OneToOneField(Address, on_delete=models.CASCADE)

    def __str__(self):
        return self.first_name + " " + self.surname

@python_2_unicode_compatible
class Item(models.Model):
    name = models.CharField('name', max_length=50)
    description = models.TextField('description')

    def __str__(self):
        return self.name

def get_logo_file_name(instance, filename):
    org_name = re.sub('[^0-9a-zA-Z]+','', instance.name)
    return os.path.join('uploads', org_name, 'logo' + os.path.splitext(filename)[1])

@python_2_unicode_compatible
class Organisation(models.Model):
    name = models.CharField('name', max_length=30)
    image = models.ImageField(upload_to=get_logo_file_name, blank=True)
    primary_contact = models.OneToOneField(Contact, on_delete=models.CASCADE)
    address = models.OneToOneField(Address, on_delete=models.CASCADE)
    description = models.TextField('description')
    just_giving_link = models.URLField('just giving link', max_length=255, blank=True)
    raised = models.DecimalField('raised', max_digits=25, decimal_places=2, blank=True)
    goal = models.DecimalField('goal', max_digits=25, decimal_places=2, blank=True)

    def __str__(self):
        return str(self.id) + " " + self.name

    def image_preview_large(self):
        if self.image:
            return format_html(
                '',
                self.image.url
            )
        else:
            return 'No Logo'
    image_preview_large.short_description = 'Image Preview'

    def image_preview_small(self):
        if self.image:
            return format_html(
                '',
                self.image.url
            )
        else:
            return 'No Logo'
    image_preview_small.short_description = 'Image Preview'

    def associated_user_accounts(self):
        return ','.join(str(item.user.id) +': ' + item.user.username for item in self.organisationuser_set.all())
    associated_user_accounts.short_description = 'User Accounts'

    def percentage_to_fund_raising_goal(self):
        val = int(round(self.raised / self.goal * 100))
        if val > 100:
            return 100
        return val

@python_2_unicode_compatible
class Wishlist(models.Model):
    organisation = models.OneToOneField(Organisation, on_delete=models.CASCADE)
    start_time = models.DateTimeField('start_time')
    end_time = models.DateTimeField('end_time')
    reoccurring = models.BooleanField('reoccurring')
    items = models.ManyToManyField(Item)

    def __str__(self):
        return self.organisation.name + " Wishlist"

@python_2_unicode_compatible
class OrganisationUser(models.Model):
    user = models.OneToOneField(User, verbose_name="User account details")
    contact = models.OneToOneField(Contact, on_delete=models.CASCADE, verbose_name='Contact details')
    organisation = models.ForeignKey(Organisation, on_delete=models.CASCADE)

    def __str__(self):
        return self.organisation.name + " Organisation User " + str(self.user.username)<|endoftext|>


<commit_before># Copyright 2014-2015 ARM Limited
#
# Licensed under the Apache License, Version 2.0
# See LICENSE file for details.

# These tests assume a client with the following resources
# endpoint name = 64754207-5e02-4d03-904b-82151ad55ea6
# /ci-object - type:'ci-endpoint'
# 		/static - observable:false,
#		/dynamic - observable:true, postable:true, this resource will incriment its value every second

import mbed_connector_api
from nose.tools import *
import os

_ep  = '64754207-5e02-4d03-904b-82151ad55ea6'
_objID = 'ci-object'
_resID = 'dynamic'
_res = "/"+_objID+"/0/"+_resID

# Grab the connector token from the 'ACCESS_KEY' environment variable
if 'ACCESS_KEY' in os.environ.keys():
	token = os.environ['ACCESS_KEY'] # get access key from environment variable
else:
	token = "ChangeMe" # replace with your API token

class test_connector_live:
	# this function is called before every test function in this class
	# Initialize the mbed connector object and start longpolling
	def setUp(self):
		self.connector = mbed_connector_api.connector(token)
		self.longPollThread = self.connector.startLongPolling()
		#self.connector.debug(True,level='INFO')

	# this function is called after every test function in this class
	# stop longpolling
	def tearDown(self):
		self.connector.stopLongPolling()

	# This function takes an async object and waits untill it is completed
	def waitOnAsync(self,asyncObject):
		while asyncObject.isDone() == False:
			None
		return

	# test the getLimits function
	@timed(10)
	def test_getLimits(self):
		x = self.connector.getLimits()
		self.waitOnAsync(x)
		assert x.error == False # check for errors

	# test the getConnectorVersion function
	@timed(10)
	def test_getConnectorVersion(self):
		x = self.connector.getConnectorVersion()
		self.waitOnAsync(x)
		assert x.error == False

	# test the getApiVersion function
	@timed(10)
	def test_getApiVersion(self):
		x = self.connector.getApiVersions()
		self.waitOnAsync(x)
		assert x.error == False

	# test the getEndpoints function
	@timed(10)
	def test_getEndpoints(self):
		x = self.connector.getEndpoints()
		self.waitOnAsync(x)
		assert x.error == False

	# test the getEndpoints function, subfuntion typeFilter
	@timed(10)
	def test_getEndpointsByType(self):
		x = self.connector.getEndpoints(typeOfEndpoint="ci-endpoint")
		self.waitOnAsync(x)
		assert x.error == False

	# test the getResources function
	@timed(10)
	def test_getResources(self):
		x = self.connector.getResources(_ep) # use first endpoint returned
		self.waitOnAsync(x)
		assert x.error == False

	@timed(10)
	def test_getResourceValue(self):
		x = self.connector.getResourceValue(_ep,_res)
		self.waitOnAsync(x)
		assert x.error == False

	@timed(10)
	def test_postResource(self):
		# test POST without data
		x = self.connector.postResource(_ep,_res)
		self.waitOnAsync(x)
		assert x.error == False
		# test POST with data
		x = self.connector.postResource(_ep,_res,"Hello World from the CI")
		self.waitOnAsync(x)
		assert x.error == False

	@timed(10)
	def test_deleteEndpoint(self):
		#TODO
		return

	@timed(10)
	def test_putResourceSubscription(self):
		x = self.connector.putResourceSubscription(_ep,_res)
		self.waitOnAsync(x)
		assert x.error == False

	@timed(10)
	def test_deleteEndpointSubscriptions(self):
		x = self.connector.deleteEndpointSubscriptions(_ep)
		self.waitOnAsync(x)
		assert x.error == False

	@timed(10)
	def test_deleteResourceSubscription(self):
		# TODO, may need to first subscribe, then unsubscribe?
		x = self.connector.deleteResourceSubscription(_ep,_res)
		self.waitOnAsync(x)
		assert x.error == False

	@timed(10)
	def test_deleteAllSubscriptions(self):
		#TODO
		return

	@timed(10)
	def test_getEndpointSubscriptions(self):
		#TODO
		return

	@timed(10)
	def test_getResourceSubscription(self):
		#TODO
		return

	@timed(10)
	def test_putPreSubscription(self):
		# check subscription is put-able
		j = [{
				'endpoint-name': "node-001",
				'resource-path': ["/dev"]},
			{
				'endpoint-type': "Light",
				'resource-path': ["/sen/*"]},
			{
				'resource-path': ["/dev/temp","/dev/hum"]
			}]
		e = self.connector.putPreSubscription(j)
		self.waitOnAsync(e)
		assert e.error == False

	@timed(10)
	def test_getPreSubscription(self):
		# Check subscription put can be retrieved
		j = [{
				'endpoint-name': "node-001",
				'resource-path': ["/dev"]},
			{
				'endpoint-type': "Light",
				'resource-path': ["/sen/*"]},
			{
				'resource-path': ["/dev/temp","/dev/hum"]
			}]
		e = self.connector.putPreSubscription(j)
		self.waitOnAsync(e)
		ok_(e.error == False, msg="There was an error putting the pre-subscription ")
		e = self.connector.getPreSubscription()
		self.waitOnAsync(e)
		ok_(e.error == False, msg="There was an error getting the pre-subscription ")
		assert e.result == j

	@timed(10)
	def test_putCallbackURL(self):
		#TODO
		return

	@timed(10)
	def test_getCallbackURL(self):
		#TODO
		return

	@timed(10)
	def test_deleteCallbackURL(self):
		#TODO
		return

<commit_msg>adding extra tests<commit_after># Copyright 2014-2015 ARM Limited
#
# Licensed under the Apache License, Version 2.0
# See LICENSE file for details.

# These tests assume a client with the following resources
# endpoint name = 64754207-5e02-4d03-904b-82151ad55ea6
# /ci-object - type:'ci-endpoint'
# 		/static - observable:false,
#		/dynamic - observable:true, postable:true, this resource will incriment its value every second

import mbed_connector_api
from nose.tools import *
import os

_ep  = '64754207-5e02-4d03-904b-82151ad55ea6'
_objID = 'ci-object'
_resID = 'dynamic'
_res = "/"+_objID+"/0/"+_resID

# Grab the connector token from the 'ACCESS_KEY' environment variable
if 'ACCESS_KEY' in os.environ.keys():
	token = os.environ['ACCESS_KEY'] # get access key from environment variable
else:
	token = "ChangeMe" # replace with your API token

class test_connector_live:
	# this function is called before every test function in this class
	# Initialize the mbed connector object and start longpolling
	def setUp(self):
		self.connector = mbed_connector_api.connector(token)
		self.longPollThread = self.connector.startLongPolling()
		#self.connector.debug(True,level='INFO')

	# this function is called after every test function in this class
	# stop longpolling
	def tearDown(self):
		self.connector.stopLongPolling()

	# This function takes an async object and waits untill it is completed
	def waitOnAsync(self,asyncObject):
		while asyncObject.isDone() == False:
			None
		return

	# test the getLimits function
	@timed(10)
	def test_getLimits(self):
		x = self.connector.getLimits()
		self.waitOnAsync(x)
		assert x.error == False # check for errors

	# test the getConnectorVersion function
	@timed(10)
	def test_getConnectorVersion(self):
		x = self.connector.getConnectorVersion()
		self.waitOnAsync(x)
		assert x.error == False

	# test the getApiVersion function
	@timed(10)
	def test_getApiVersion(self):
		x = self.connector.getApiVersions()
		self.waitOnAsync(x)
		assert x.error == False

	# test the getEndpoints function
	@timed(10)
	def test_getEndpoints(self):
		x = self.connector.getEndpoints()
		self.waitOnAsync(x)
		assert x.error == False

	# test the getEndpoints function, subfuntion typeFilter
	@timed(10)
	def test_getEndpointsByType(self):
		x = self.connector.getEndpoints(typeOfEndpoint="ci-endpoint")
		self.waitOnAsync(x)
		assert x.error == False

	# test the getResources function
	@timed(10)
	def test_getResources(self):
		x = self.connector.getResources(_ep) # use first endpoint returned
		self.waitOnAsync(x)
		assert x.error == False

	@timed(10)
	def test_getResourceValue(self):
		x = self.connector.getResourceValue(_ep,_res)
		self.waitOnAsync(x)
		assert x.error == False

	@timed(10)
	def test_postResource(self):
		# test POST without data
		x = self.connector.postResource(_ep,_res)
		self.waitOnAsync(x)
		assert x.error == False
		# test POST with data
		x = self.connector.postResource(_ep,_res,"Hello World from the CI")
		self.waitOnAsync(x)
		assert x.error == False

	@timed(10)
	def test_deleteEndpoint(self):
		#TODO
		return

	@timed(10)
	def test_putResourceSubscription(self):
		x = self.connector.putResourceSubscription(_ep,_res)
		self.waitOnAsync(x)
		assert x.error == False

	@timed(10)
	def test_getEndpointSubscriptions(self):
		x = self.connector.getEndpointSubscriptions(_ep)
		self.waitOnAsync(x)
		assert x.error == False

	@timed(10)
	def test_getResourceSubscription(self):
		x = self.connector.getResourceSubscription(_ep,_res)
		self.waitOnAsync(x)
		assert x.error == False

	@timed(10)
	def test_deleteResourceSubscription(self):
		# TODO, may need to first subscribe, then unsubscribe?
		x = self.connector.deleteResourceSubscription(_ep,_res)
		self.waitOnAsync(x)
		assert x.error == False

	@timed(10)
	def test_deleteEndpointSubscriptions(self):
		x = self.connector.deleteEndpointSubscriptions(_ep)
		self.waitOnAsync(x)
		assert x.error == False

	@timed(10)
	def test_deleteAllSubscriptions(self):
		x = self.connector.deleteAllSubscriptions()
		self.waitOnAsync(x)
		assert x.error == False

	@timed(10)
	def test_putPreSubscription(self):
		# check subscription is put-able
		j = [{
				'endpoint-name': "node-001",
				'resource-path': ["/dev"]},
			{
				'endpoint-type': "Light",
				'resource-path': ["/sen/*"]},
			{
				'resource-path': ["/dev/temp","/dev/hum"]
			}]
		e = self.connector.putPreSubscription(j)
		self.waitOnAsync(e)
		assert e.error == False

	@timed(10)
	def test_getPreSubscription(self):
		# Check subscription put can be retrieved
		j = [{
				'endpoint-name': "node-001",
				'resource-path': ["/dev"]},
			{
				'endpoint-type': "Light",
				'resource-path': ["/sen/*"]},
			{
				'resource-path': ["/dev/temp","/dev/hum"]
			}]
		e = self.connector.putPreSubscription(j)
		self.waitOnAsync(e)
		ok_(e.error == False, msg="There was an error putting the pre-subscription ")
		e = self.connector.getPreSubscription()
		self.waitOnAsync(e)
		ok_(e.error == False, msg="There was an error getting the pre-subscription ")
		assert e.result == j

	@timed(10)
	def test_putCallbackURL(self):
		#TODO
		return

	@timed(10)
	def test_getCallbackURL(self):
		#TODO
		return

	@timed(10)
	def test_deleteCallbackURL(self):
		#TODO
		return

<|endoftext|>