<commit_before>from ga4gh.client import client
import configparser

class ClientManager:

    def __init__(self, args):
        self.clientList=[]
        self.restriction_mapping_datasets={}
        self.restriction_mapping_featuresets={}
        self.restriction_mapping_phenotypeassociationsets={}

    def add_client(self, datasets=None, featuresets=None, phenotypeassociationsets=None):
        """Add a g2p client to manager. Optionally restrict to specified
        datasets, featuresets, and phenotypeassociatonsets."""

    def add_http_client(self, url_prefix, datasets=None, featuresets=None, phenotypeassociationsets=None):
        """Add a g2p HTTP client to manager. Optionally restrict to specified datasets, featuresets, and phenotypeassociatonsets."""
        c = client.HttpClient(url_prefix)
        self.clientList.append(c)
        self.restrictClient(c,datasets, featuresets, phenotypeassociationsets)

    #HTTP and Local client methods are seperate because local client constructor can take more parameters although I'm not using currently.
    def add_local_client(self,backend, datasets=None, featuresets=None, phenotypeassociationsets=None):
        """Add a g2p local client to manager."""
        c = client.LocalClient(backend)
        self.clientList.append(c)
        self.restrictClient(c,datasets, featuresets, phenotypeassociationsets)

    def restrictClient(self, client, datasets=None, featuresets=None, phenotypeassociationsets=None):
        """Restrict the client to specified datasets, featuresets, and phenotypeassociatonsets."""
        if datasets is not None:
            self.restriction_mapping_datasets[client]=datasets
        if featuresets is not None:
            self.restriction_mapping_featuresets[client]=featuresets
        if phenotypeassociationsets is not None:
            self.restriction_mapping_phenotypeassociationsets[client]=phenotypeassociationsets

    def load_clients_from_config(self, config_file):
        """Add g2p clients from a specified configparser-compliant config
        file."""
        pass

    def federated_featurephenotypeassociaton_query(self, args):
        """Search all clients for feature-phenotype associations as defined by
        args."""
        pass

#Code for trial
clientManager = ClientManager("")
clientManager.add_http_client("http://1kgenomes.ga4gh.org", datasets=["1kgenomes","anotherOne"])
dataset = clientManager.clientList[0].search_datasets().next()
print dataset
print clientManager.restriction_mapping_datasets
print clientManager.restriction_mapping_featuresets
print clientManager.restriction_mapping_phenotypeassociationsets<commit_msg>addClient functions for HTTP and local clients are created in client.py<commit_after>from ga4gh.client import client
import configparser

class ClientManager:

    def __init__(self, args):
        self.clientList=[]
        self.restriction_mapping_datasets={}
        self.restriction_mapping_featuresets={}
        self.restriction_mapping_phenotypeassociationsets={}

    def add_client(self, datasets=None, featuresets=None, phenotypeassociationsets=None):
        """Add a g2p client to manager. Optionally restrict to specified
        datasets, featuresets, and phenotypeassociatonsets."""
        pass

    def add_http_client(self, url_prefix, datasets=None, featuresets=None, phenotypeassociationsets=None):
        """Add a g2p HTTP client to manager. Optionally restrict to specified datasets, featuresets, and phenotypeassociatonsets."""
        c = client.HttpClient(url_prefix)
        self.clientList.append(c)
        self.restrictClient(c,datasets, featuresets, phenotypeassociationsets)

    #HTTP and Local client methods are seperate because local client constructor can take more parameters although I'm not using currently.
    def add_local_client(self,backend, datasets=None, featuresets=None, phenotypeassociationsets=None):
        """Add a g2p local client to manager."""
        c = client.LocalClient(backend)
        self.clientList.append(c)
        self.restrictClient(c,datasets, featuresets, phenotypeassociationsets)

    def restrictClient(self, client, datasets=None, featuresets=None, phenotypeassociationsets=None):
        """Restrict the client to specified datasets, featuresets, and phenotypeassociatonsets."""
        if datasets is not None:
            self.restriction_mapping_datasets[client]=datasets
        if featuresets is not None:
            self.restriction_mapping_featuresets[client]=featuresets
        if phenotypeassociationsets is not None:
            self.restriction_mapping_phenotypeassociationsets[client]=phenotypeassociationsets

    def load_clients_from_config(self, config_file):
        """Add g2p clients from a specified configparser-compliant config
        file."""
        pass

    def federated_featurephenotypeassociaton_query(self, args):
        """Search all clients for feature-phenotype associations as defined by
        args."""
        pass

#Code for trial
clientManager = ClientManager("")
clientManager.add_http_client("http://1kgenomes.ga4gh.org", datasets=["1kgenomes","anotherOne"])
dataset = clientManager.clientList[0].search_datasets().next()
print dataset
print clientManager.restriction_mapping_datasets
print clientManager.restriction_mapping_featuresets
print clientManager.restriction_mapping_phenotypeassociationsets<|endoftext|>


<commit_before>from django.core.validators import validate_email
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
from pygeocoder import Geocoder
from rest_framework import serializers
from rest_framework.reverse import reverse

from api.users.serializers import InvitedSerializer
from tarambay.events.models import Category, Event
from tarambay.users.models import Invited, User

class CategorySerializer(serializers.HyperlinkedModelSerializer):
    id = serializers.UUIDField(source='uuid')

    class Meta:
        model = Category
        fields = ('id', 'self', 'name', 'description')
        extra_kwargs = {
            'self': {'lookup_field': 'uuid'}
        }

class EventSerializer(serializers.HyperlinkedModelSerializer):
    id = serializers.UUIDField(source='uuid', read_only=True)
    invited = InvitedSerializer(many=True)
    going = InvitedSerializer(many=True)
    invite_url = serializers.SerializerMethodField()
    join_url = serializers.SerializerMethodField()

    class Meta:
        model = Event
        fields = ('id', 'self', 'category', 'title', 'description', 'latitude',
                  'longitude', 'start', 'end', 'admin', 'tags', 'invited',
                  'going', 'invite_url', 'join_url', 'private')
        extra_kwargs = {
            'self': {'lookup_field': 'uuid'},
            'admin': {'lookup_field': 'uuid'},
            'category': {'lookup_field': 'uuid'},
        }

    def get_invite_url(self, obj):
        return reverse('event-invite', args=[obj.uuid], request=self.context['request'])

    def get_join_url(self, obj):
        return reverse('event-join', args=[obj.uuid], request=self.context['request'])

class CreateEventSerializer(EventSerializer):
    location = serializers.CharField(write_only=True, required=False, allow_blank=True)
    latitude = serializers.CharField(required=False, allow_blank=True)
    longitude = serializers.CharField(required=False, allow_blank=True)

    class Meta:
        model = Event
        fields = ('id', 'self', 'category', 'title', 'description', 'location',
                  'latitude', 'longitude', 'start', 'end', 'tags', 'private')
        extra_kwargs = {
            'self': {'lookup_field': 'uuid'},
            'admin': {'lookup_field': 'uuid'},
            'category': {'lookup_field': 'uuid'},
        }

    def validate(self, data):
        """
        Check that location is a valid address
        """
        location = data.pop('location', None)
        start = data.get('start', None)
        end = data.get('end', None)
        if location:
            result = Geocoder.geocode(location)
            if result.valid_address:
                data['latitude'] = result.latitude
                data['longitude'] = result.longitude
            else:
                raise serializers.ValidationError(_("That is not a valid location."))
        if start and end:
            if end <= start:
                raise serializers.ValidationError("The end date and time must be \
                    after the start date and time")
        elif not self.partial:
            latitude = data.get('latitude', None)
            longitude = data.get('longitude', None)
            if not latitude or not longitude:
                raise serializers.ValidationError(_(
                    "Either a valid address for location should be provided or"
                    " latitude and longitude should be provided."))
        if self.partial:
            return data
        data['admin'] = self.context['request'].user
        return data

    def update(self, instance, validated_data):
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()
        return instance

class InviteEventSerializer(serializers.ModelSerializer):
    invited = serializers.CharField(write_only=True)

    class Meta:
        model = Event
        fields = ('invited',)

    def update(self, instance, validated_data):
        # invited is a comma-separated string of either usernames or emails
        # disregards input that is not a valid username or email
        invited_list = validated_data['invited'].split(", ")
        for item in invited_list:
            user = None
            email = None
            try:
                user = User.objects.get(username=item)
            except User.DoesNotExist:
                try:
                    validate_email(item)
                    email = item
                except ValidationError:
                    continue
            if email:
                try:
                    user = User.objects.get(email=email)
                except User.DoesNotExist:
                    invited, created = Invited.objects.get_or_create(email=email)
            if user:
                invited, created = Invited.objects.get_or_create(user=user)
            instance.invited.add(invited)
        return instance

class JoinEventSerializer(serializers.Serializer):
    join = serializers.BooleanField(write_only=True)

    def update(self, instance, validated_data):
        join = validated_data.get('join')
        user = self.context['request'].user
        try:
            instance.going.get(user=user)
            return instance
        except Invited.DoesNotExist:
            pass
        if join:
            if instance.admin:
                try:
                    invited = instance.invited.get(user=user)
                except Invited.DoesNotExist:
                    invited, created = Invited.objects.get_or_create(user=user)
                instance.invited.remove(invited)
                instance.going.add(invited)
            elif instance.private:
                try:
                    invited = instance.invited.get(user=user)
                    instance.invited.remove(invited)
                except Invited.DoesNotExist:
                    raise serializers.ValidationError(_("You can only join "
                        "private events you have been invited to."))
                instance.going.add(invited)
            else:
                try:
                    invited = instance.invited.get(user=user)
                    instance.invited.remove(invited)
                except Invited.DoesNotExist:
                    invited, created = Invited.objects.get_or_create(user=user)
                instance.going.add(invited)
        return instance

class ReadOnlyEventSerializer(EventSerializer):
    class Meta:
        model = Event
        fields = ('id', 'self', 'category', 'title', 'description', 'latitude',
                  'longitude', 'start', 'end', 'admin', 'tags', 'invited',
                  'going', 'invite_url', 'join_url', 'private')
        read_only_fields = ('id', 'self', 'category', 'title', 'description', 'latitude',
                  'longitude', 'start', 'end', 'admin', 'tags', 'invited',
                  'going', 'invite_url', 'join_url', 'private')
        extra_kwargs = {
            'self': {'lookup_field': 'uuid'},
            'admin': {'lookup_field': 'uuid'},
            'category': {'lookup_field': 'uuid'},
        }<commit_msg>add location to serializers<commit_after>from django.core.validators import validate_email
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
from pygeocoder import Geocoder
from rest_framework import serializers
from rest_framework.reverse import reverse

from api.users.serializers import InvitedSerializer
from tarambay.events.models import Category, Event
from tarambay.users.models import Invited, User

class CategorySerializer(serializers.HyperlinkedModelSerializer):
    id = serializers.UUIDField(source='uuid')

    class Meta:
        model = Category
        fields = ('id', 'self', 'name', 'description')
        extra_kwargs = {
            'self': {'lookup_field': 'uuid'}
        }

class EventSerializer(serializers.HyperlinkedModelSerializer):
    id = serializers.UUIDField(source='uuid', read_only=True)
    invited = InvitedSerializer(many=True)
    going = InvitedSerializer(many=True)
    invite_url = serializers.SerializerMethodField()
    join_url = serializers.SerializerMethodField()

    class Meta:
        model = Event
        fields = ('id', 'self', 'category', 'title', 'description', 'latitude',
                  'longitude', 'start', 'end', 'admin', 'tags', 'invited',
                  'going', 'invite_url', 'join_url', 'private', 'location')
        extra_kwargs = {
            'self': {'lookup_field': 'uuid'},
            'admin': {'lookup_field': 'uuid'},
            'category': {'lookup_field': 'uuid'},
        }

    def get_invite_url(self, obj):
        return reverse('event-invite', args=[obj.uuid], request=self.context['request'])

    def get_join_url(self, obj):
        return reverse('event-join', args=[obj.uuid], request=self.context['request'])

class CreateEventSerializer(EventSerializer):
    location = serializers.CharField(required=False, allow_blank=True)
    latitude = serializers.CharField(required=False, allow_blank=True)
    longitude = serializers.CharField(required=False, allow_blank=True)

    class Meta:
        model = Event
        fields = ('id', 'self', 'category', 'title', 'description', 'location',
                  'latitude', 'longitude', 'start', 'end', 'tags', 'private')
        extra_kwargs = {
            'self': {'lookup_field': 'uuid'},
            'admin': {'lookup_field': 'uuid'},
            'category': {'lookup_field': 'uuid'},
        }

    def validate(self, data):
        """
        Check that location is a valid address
        """
        location = data.pop('location', None)
        start = data.get('start', None)
        end = data.get('end', None)
        if location:
            result = Geocoder.geocode(location)
            if result.valid_address:
                data['latitude'] = result.latitude
                data['longitude'] = result.longitude
                data['location'] = result.formatted_address
            else:
                raise serializers.ValidationError(_("That is not a valid location."))
        if start and end:
            if end <= start:
                raise serializers.ValidationError("The end date and time must be \
                    after the start date and time")
        elif not self.partial:
            latitude = data.get('latitude', None)
            longitude = data.get('longitude', None)
            if not latitude or not longitude:
                raise serializers.ValidationError(_(
                    "Either a valid address for location should be provided or"
                    " latitude and longitude should be provided."))
        if self.partial:
            return data
        data['admin'] = self.context['request'].user
        return data

    def update(self, instance, validated_data):
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()
        return instance

class InviteEventSerializer(serializers.ModelSerializer):
    invited = serializers.CharField(write_only=True)

    class Meta:
        model = Event
        fields = ('invited',)

    def update(self, instance, validated_data):
        # invited is a comma-separated string of either usernames or emails
        # disregards input that is not a valid username or email
        invited_list = validated_data['invited'].split(", ")
        for item in invited_list:
            user = None
            email = None
            try:
                user = User.objects.get(username=item)
            except User.DoesNotExist:
                try:
                    validate_email(item)
                    email = item
                except ValidationError:
                    continue
            if email:
                try:
                    user = User.objects.get(email=email)
                except User.DoesNotExist:
                    invited, created = Invited.objects.get_or_create(email=email)
            if user:
                invited, created = Invited.objects.get_or_create(user=user)
            instance.invited.add(invited)
        return instance

class JoinEventSerializer(serializers.Serializer):
    join = serializers.BooleanField(write_only=True)

    def update(self, instance, validated_data):
        join = validated_data.get('join')
        user = self.context['request'].user
        try:
            instance.going.get(user=user)
            return instance
        except Invited.DoesNotExist:
            pass
        if join:
            if instance.admin:
                try:
                    invited = instance.invited.get(user=user)
                except Invited.DoesNotExist:
                    invited, created = Invited.objects.get_or_create(user=user)
                instance.invited.remove(invited)
                instance.going.add(invited)
            elif instance.private:
                try:
                    invited = instance.invited.get(user=user)
                    instance.invited.remove(invited)
                except Invited.DoesNotExist:
                    raise serializers.ValidationError(_("You can only join "
                        "private events you have been invited to."))
                instance.going.add(invited)
            else:
                try:
                    invited = instance.invited.get(user=user)
                    instance.invited.remove(invited)
                except Invited.DoesNotExist:
                    invited, created = Invited.objects.get_or_create(user=user)
                instance.going.add(invited)
        return instance

class ReadOnlyEventSerializer(EventSerializer):
    class Meta:
        model = Event
        fields = ('id', 'self', 'category', 'title', 'description', 'latitude',
                  'longitude', 'start', 'end', 'admin', 'tags', 'invited',
                  'going', 'invite_url', 'join_url', 'private', 'location')
        read_only_fields = ('id', 'self', 'category', 'title', 'description', 'latitude',
                  'longitude', 'start', 'end', 'admin', 'tags', 'invited',
                  'going', 'invite_url', 'join_url', 'private', 'location')
        extra_kwargs = {
            'self': {'lookup_field': 'uuid'},
            'admin': {'lookup_field': 'uuid'},
            'category': {'lookup_field': 'uuid'},
        }<|endoftext|>


<commit_before>import sys
import django

__all__ = [
    'json',
    'BufferIO',
    'urlopen',
    'urlparse',
    'quote',
    'quote_plus',
    'URLError',
    'force_unicode', 'text_type'
]

PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3

# Django version

if django.VERSION < (1, 5):
    from django.utils import simplejson as json
    from django.utils.encoding import force_unicode
else:
    import json
    from django.utils.encoding import force_text as force_unicode

# Python 2 and 3

if PY3:
    from urllib.error import URLError
    from urllib.request import urlopen
    from urllib.request import quote, quote_plus

    import urllib.parse as urlparse

    from io import BytesIO as BufferIO

    text_type = str
    string_type = str

    def encode(value):
        return value.encode('utf-8')

elif PY2:
    from urllib2 import URLError
    from urllib import urlopen
    from urllib import quote, quote_plus

    import urlparse

    from cStringIO import StringIO as BufferIO

    text_type = unicode
    string_type = basestring

    def encode(value):
        return unicode(value, errors='ignore').encode('utf-8')
<commit_msg>Fixes incorrect import for Python 3.3<commit_after>import sys
import django

__all__ = [
    'json',
    'BufferIO',
    'urlopen',
    'urlparse',
    'quote',
    'quote_plus',
    'URLError',
    'force_unicode', 'text_type'
]

PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3

# Django version

if django.VERSION < (1, 5):
    from django.utils import simplejson as json
    from django.utils.encoding import force_unicode
else:
    import json
    from django.utils.encoding import force_text as force_unicode

# Python 2 and 3

if PY3:
    from urllib.error import URLError
    from urllib.request import urlopen
    from urllib.parse import quote, quote_plus

    import urllib.parse as urlparse

    from io import BytesIO as BufferIO

    text_type = str
    string_type = str

    def encode(value):
        return value.encode('utf-8')

elif PY2:
    from urllib2 import URLError
    from urllib import urlopen
    from urllib import quote, quote_plus

    import urlparse

    from cStringIO import StringIO as BufferIO

    text_type = unicode
    string_type = basestring

    def encode(value):
        return unicode(value, errors='ignore').encode('utf-8')
<|endoftext|>


<commit_before>'''
Fetch newest articles from my blogroll
'''

from datetime import datetime
from hashlib import sha256
from pathlib import Path
import logging
import json
import re

import feedparser
import yaml

logging.basicConfig(format='%(levelname)-8s %(message)s', level=logging.INFO)
log = logging.getLogger(__name__)

JSON_PARAMS = dict(
    indent=2,
    ensure_ascii=False,
    default=repr,
)

def main():
    reader = CachingFeedReader('cache')
    webring = []
    for section in blogroll('content/blogroll.yml'):
        for blog in section['blogs'] or []:
            if not 'feed' in blog:
                continue
            try:
                feed = reader.feed(title=blog['title'], url=blog['feed'])
            except Exception:
                log.exception(f'Error while fetching {blog["feed"]}')
                continue
            entries = sorted(feed.entries, key=lambda x: x.updated_parsed, reverse=True)
            latest = entries[0]
            webring.append(dict(blog=blog, entry=latest))
    print(json.dumps(webring, **JSON_PARAMS))

def blogroll(filepath):
    '''Parse blogroll from YAML file'''
    with open(filepath) as f:
        return yaml.safe_load(f)

class CachingFeedReader:
    '''RSS/Atom feed reader with local cache'''

    def __init__(self, cachedir):
        self.cachedir = Path(cachedir).resolve()
        if not self.cachedir.is_dir():
            raise ValueError(f'cache directory does not exist: {self.cachedir}')

    def feed(self, title, url):
        '''Parse feed from URL, use cache if applicable'''
        cache = self._cache(title, url)
        if cache.hot():
            return cache.read()
        fetch_params = dict()
        if cache.exists():
            for key in ['etag', 'modified']:
                if key in cache.metadata:
                    fetch_params[key] = cache_metadata[key]
        feed = feedparser.parse(url, **fetch_params)
        if feed.status == 200:
            cache.save(feed)
            return feed
        elif cache.exists():
            log.error(f'HTTP {feed.status}: {url}, continuing from cache: {cache.directory}')
            return cache.read()
        else:
            raise RuntimeError(f'HTTP {feed.status}: {url}')

    def _cache(self, title, url):
        '''Return cache object for a given feed'''
        return FeedCache(self.cachedir, title, url)

class FeedCache:
    '''Cache object for a single feed'''

    LIFETIME_MINUTES = 24*60
    METADATA_VERSION = 1

    def __init__(self, cachedir, title, url):
        sanitized_title = re.sub(r'\W', '_', title)
        url_hash = sha256(url.encode()).hexdigest()[-8:]
        safe_dirname = f'{sanitized_title}_{url_hash}'
        safe_dirname = re.sub(r'_+', '_', safe_dirname)

        self._directory = cachedir / safe_dirname
        self._metadata = self._directory / 'metadata'
        self._feed = self._directory / 'feed'

    def timestamp(self):
        return datetime.now().timestamp()

    @property
    def metadata(self):
        with self._metadata.open() as f:
            metadata = json.load(f)
        if metadata.get('version') == self.METADATA_VERSION:
            return metadata
        else:
            log.error(f'Mismatching metadata version ({self._metadata}): '
                      f'got {metadata.get("version")} instead of {self.METADATA_VERSION}')
            return dict()

    def exists(self):
        return self._metadata.exists() and self._feed.exists()

    def hot(self):
        '''Check if cache is still hot'''
        if not self.exists():
            return False
        timestamp = self.metadata.get('cache_created')
        if timestamp and self.timestamp() - timestamp < self.LIFETIME_MINUTES * 60:
            return True
        return False

    def save(self, feed):
        '''Save feed to cache'''
        log.info(f'Saving cache: {self._directory}')
        self._directory.mkdir(exist_ok=True)
        with self._feed.open('w') as f:
            json.dump(feed, f, **JSON_PARAMS)
        metadata = dict()
        for key in ['etag', 'modified', 'modified_parsed']:
            if key in feed:
                metadata[key] = feed[key]
        metadata['cache_created'] = self.timestamp()
        metadata['version'] = self.METADATA_VERSION
        with self._metadata.open('w') as f:
            json.dump(metadata, f, **JSON_PARAMS)

    def read(self):
        '''Read feed from cache'''
        log.info(f'Reading cache: {self._directory}')
        with self._feed.open() as f:
            return json.load(f, object_hook=feedparser.util.FeedParserDict)

if __name__ == '__main__':
    main()
<commit_msg>Fix polite HTTP fetching with Etab/Last-Modified headers<commit_after>'''
Fetch newest articles from my blogroll
'''

from datetime import datetime
from hashlib import sha256
from pathlib import Path
import logging
import json
import re

import feedparser
import yaml

logging.basicConfig(format='%(levelname)-8s %(message)s', level=logging.INFO)
log = logging.getLogger(__name__)

JSON_PARAMS = dict(
    indent=2,
    ensure_ascii=False,
    default=repr,
)

def main():
    reader = CachingFeedReader('cache')
    webring = []
    for section in blogroll('content/blogroll.yml'):
        for blog in section['blogs'] or []:
            if not 'feed' in blog:
                continue
            try:
                feed = reader.feed(title=blog['title'], url=blog['feed'])
            except Exception:
                log.exception(f'Error while fetching {blog["feed"]}')
                continue
            entries = sorted(feed.entries, key=lambda x: x.updated_parsed, reverse=True)
            latest = entries[0]
            webring.append(dict(blog=blog, entry=latest))
    print(json.dumps(webring, **JSON_PARAMS))

def blogroll(filepath):
    '''Parse blogroll from YAML file'''
    with open(filepath) as f:
        return yaml.safe_load(f)

class CachingFeedReader:
    '''RSS/Atom feed reader with local cache'''

    def __init__(self, cachedir):
        self.cachedir = Path(cachedir).resolve()
        if not self.cachedir.is_dir():
            raise ValueError(f'cache directory does not exist: {self.cachedir}')

    def feed(self, title, url):
        '''Parse feed from URL, use cache if applicable'''
        cache = self._cache(title, url)
        if cache.hot():
            return cache.read()
        fetch_params = dict()
        if cache.exists():
            for key in ['etag', 'modified']:
                if key in cache.metadata:
                    fetch_params[key] = cache.metadata[key]
        feed = feedparser.parse(url, **fetch_params)
        if feed.status == 200:
            cache.save(feed)
            return feed
        elif cache.exists():
            if feed.status < 400:
                report = log.info
            else:
                report = log.error
            report(f'HTTP {feed.status}: {url}, continuing from {cache}')
            return cache.read()
        else:
            raise RuntimeError(f'HTTP {feed.status}: {url}')

    def _cache(self, title, url):
        '''Return cache object for a given feed'''
        return FeedCache(self.cachedir, title, url)

class FeedCache:
    '''Cache object for a single feed'''

    LIFETIME_MINUTES = 24*60
    METADATA_VERSION = 1

    def __init__(self, cachedir, title, url):
        sanitized_title = re.sub(r'\W', '_', title)
        url_hash = sha256(url.encode()).hexdigest()[-8:]
        safe_dirname = f'{sanitized_title}_{url_hash}'
        safe_dirname = re.sub(r'_+', '_', safe_dirname)

        self._directory = cachedir / safe_dirname
        self._metadata = self._directory / 'metadata'
        self._feed = self._directory / 'feed'

    def __repr__(self):
        return f'{self.__class__.__name__}: {self._directory}'

    def timestamp(self):
        return datetime.now().timestamp()

    @property
    def metadata(self):
        with self._metadata.open() as f:
            metadata = json.load(f)
        if metadata.get('version') == self.METADATA_VERSION:
            return metadata
        else:
            log.error(f'Mismatching metadata version ({self._metadata}): '
                      f'got {metadata.get("version")} instead of {self.METADATA_VERSION}')
            return dict()

    def exists(self):
        return self._metadata.exists() and self._feed.exists()

    def hot(self):
        '''Check if cache is still hot'''
        if not self.exists():
            return False
        timestamp = self.metadata.get('cache_created')
        if timestamp and self.timestamp() - timestamp < self.LIFETIME_MINUTES * 60:
            return True
        return False

    def save(self, feed):
        '''Save feed to cache'''
        log.info(f'Saving cache: {self._directory}')
        self._directory.mkdir(exist_ok=True)
        with self._feed.open('w') as f:
            json.dump(feed, f, **JSON_PARAMS)
        metadata = dict()
        for key in ['etag', 'modified', 'modified_parsed']:
            if key in feed:
                metadata[key] = feed[key]
        metadata['cache_created'] = self.timestamp()
        metadata['version'] = self.METADATA_VERSION
        with self._metadata.open('w') as f:
            json.dump(metadata, f, **JSON_PARAMS)

    def read(self):
        '''Read feed from cache'''
        log.info(f'Reading cache: {self._directory}')
        with self._feed.open() as f:
            return json.load(f, object_hook=feedparser.util.FeedParserDict)

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


<commit_before># A service for movie info

from api.movie.tmdb_api import get_credits
from api.movie.tmdb_api import get_movies
from api.movie.tmdb_api import load_credits_for_name
from api.movie.tmdb_api import load_movie_for_title
from pal.grammars import get_grammar_for_service
from pal.grammars.parser import extract
from pal.grammars.parser import parse
from pal.services.service import Service
from pal.services.service import wrap_response

class MovieService(Service):

    def __init__(self):
        self.grammar = get_grammar_for_service(self.__class__.short_name())
        self.cached_parse = None

    def applies_to_me(self, client, feature_request_type):
        return True

    def get_confidence(self, params):
        query = params['query']

        # TODO: shouldn't have to do this
        if query[-1] == '?':
            query = query[:-1]

        self.cached_parse = (query, parse(query, self.grammar))
        return 100 if self.cached_parse else 0

    @wrap_response
    def go(self, params):
        query = params['query']

        # TODO: shouldn't have to do this
        if query[-1] == '?':
            query = query[:-1]

        if self.cached_parse and self.cached_parse[0] == query:
            parse_tree = self.cached_parse[1]
        else:
            parse_tree = parse(query, self.grammar)

        print parse_tree
        if parse_tree:
            intent = self.extract_intent(parse_tree)
            object_ = self.extract_object(parse_tree)
            self.update_kb(intent, object_)
            result = self.query_kb(intent, object_)
            summary = self.generate_summary(intent, object_, result)
            return ('SUCCESS', summary)
        else:
            return ('ERROR', 'I don\'t understand.')

    @staticmethod
    def extract_intent(parse_tree):
        name = extract('person_concrete', parse_tree)
        title = extract('movie_concrete', parse_tree)
        if title:
            intent = ('MOVIES', 'YEAR_OF')
        if name:
            intent = ('CREDITS', 'COUNT_OF')
        if parse_tree[1][0][0] == 'aux':
            intent = (intent[0], 'BOOLEAN_OF')
        return intent

    @staticmethod
    def extract_object(parse_tree):
        name = extract('name', parse_tree)
        title = extract('title', parse_tree)
        year = extract('year', parse_tree)
        return {'name': name, 'title': title, 'year': year}

    def update_kb(self, intent, object_):
        """ Adds data to the KB that may be relevant to this query. """
        if object_['name']:
            load_credits_for_name(object_['name'])
        if object_['title']:
            load_movie_for_title(object_['title'])

    def query_kb(self, intent, object_, modifier=None, frame=None):
        """ Makes a query to the knowledge base. """
        if intent[0] == 'CREDITS':
            credits = get_credits(**object_)
            if intent[1] == 'BOOLEAN_OF':
                return not not credits
            if intent[1] == 'COUNT_OF':
                return len(credits)
        elif intent[0] == 'MOVIES':
            movies = get_movies(**object_)
            if intent[1] == 'YEAR_OF':
                return movies[0].date_.year

    def generate_summary(self, intent, object_, result):
        if intent[0] == 'CREDITS':
            name = object_['name'].title()
            if intent[1] == 'COUNT_OF':
                return '{0} was in {1} movies.'.format(name, result)
            if intent[1] == 'BOOLEAN_OF':
                return 'Yes.' if result else 'No.'
        elif intent[0] == 'MOVIES':
            if intent[1] == 'YEAR_OF':
                title = object_['title'].title()
                return '{0} was in the year {1}.'.format(title, result)

if __name__ == "__main__":
    print MovieService().go({
        'query': 'what year was the movie blade runner?'
    })
<commit_msg>JSON, I understand<commit_after># A service for movie info

from api.movie.tmdb_api import get_credits
from api.movie.tmdb_api import get_movies
from api.movie.tmdb_api import load_credits_for_name
from api.movie.tmdb_api import load_movie_for_title
from pal.grammars import get_grammar_for_service
from pal.grammars.parser import extract
from pal.grammars.parser import parse
from pal.services.service import Service
from pal.services.service import wrap_response

class MovieService(Service):

    def __init__(self):
        self.grammar = get_grammar_for_service(self.__class__.short_name())
        self.cached_parse = None

    def applies_to_me(self, client, feature_request_type):
        return True

    def get_confidence(self, params):
        query = params['query']

        # TODO: shouldn't have to do this
        if query[-1] == '?':
            query = query[:-1]

        parse_ = parse(query, self.grammar)
        self.cached_parse = (query, parse_)
        return 100 if parse_ else 0

    @wrap_response
    def go(self, params):
        query = params['query']

        # TODO: shouldn't have to do this
        if query[-1] == '?':
            query = query[:-1]

        if self.cached_parse and self.cached_parse[0] == query:
            parse_tree = self.cached_parse[1]
        else:
            parse_tree = parse(query, self.grammar)

        print parse_tree
        if parse_tree:
            intent = self.extract_intent(parse_tree)
            object_ = self.extract_object(parse_tree)
            self.update_kb(intent, object_)
            result = self.query_kb(intent, object_)
            summary = self.generate_summary(intent, object_, result)
            return ('SUCCESS', summary)
        else:
            return ('ERROR', 'I don\'t understand.')

    @staticmethod
    def extract_intent(parse_tree):
        name = extract('person_concrete', parse_tree)
        title = extract('movie_concrete', parse_tree)
        if title:
            intent = ('MOVIES', 'YEAR_OF')
        if name:
            intent = ('CREDITS', 'COUNT_OF')
        if parse_tree[1][0][0] == 'aux':
            intent = (intent[0], 'BOOLEAN_OF')
        return intent

    @staticmethod
    def extract_object(parse_tree):
        name = extract('name', parse_tree)
        title = extract('title', parse_tree)
        year = extract('year', parse_tree)
        return {'name': name, 'title': title, 'year': year}

    def update_kb(self, intent, object_):
        """ Adds data to the KB that may be relevant to this query. """
        if object_['name']:
            load_credits_for_name(object_['name'])
        if object_['title']:
            load_movie_for_title(object_['title'])

    def query_kb(self, intent, object_, modifier=None, frame=None):
        """ Makes a query to the knowledge base. """
        if intent[0] == 'CREDITS':
            credits = get_credits(**object_)
            if intent[1] == 'BOOLEAN_OF':
                return not not credits
            if intent[1] == 'COUNT_OF':
                return len(credits)
        elif intent[0] == 'MOVIES':
            movies = get_movies(**object_)
            if intent[1] == 'YEAR_OF':
                return movies[0].date_.year

    def generate_summary(self, intent, object_, result):
        if intent[0] == 'CREDITS':
            name = object_['name'].title()
            if intent[1] == 'COUNT_OF':
                return '{0} was in {1} movies.'.format(name, result)
            if intent[1] == 'BOOLEAN_OF':
                return 'Yes.' if result else 'No.'
        elif intent[0] == 'MOVIES':
            if intent[1] == 'YEAR_OF':
                title = object_['title'].title()
                return '{0} was in the year {1}.'.format(title, result)

if __name__ == "__main__":
    print MovieService().go({
        'query': 'what year was the movie blade runner?'
    })
<|endoftext|>


<commit_before>'''
Created on Feb 7, 2012

@author: marat
'''
import string
from array import *
class PDBRecord:
    '''
    classdocs
    '''
    irecord=[0,6]
    inum=[6,11]
    iname=[12,16]
    iresname=[17,20]
    iresid=[22,26]
    ix=[30,38]
    iy=[38,46]
    iz=[46,54]
    iel=[76,78]

#     1 -  6      Record name      "ATOM    "
#     7 - 11      Integer          serial     Atom serial number.
#    13 - 16      Atom             name       Atom name.
#    17           Character        altLoc     Alternate location indicator.
#    18 - 20      Residue name     resName    Residue name.
#    22           Character        chainID    Chain identifier.
#    23 - 26      Integer          resSeq     Residue sequence number.
#    27           AChar            iCode      Code for insertion of residues.
#    31 - 38      Real(8.3)        x          Orthogonal coordinates for X in
#                                             Angstroms
#    39 - 46      Real(8.3)        y          Orthogonal coordinates for Y in
#                                             Angstroms
#    47 - 54      Real(8.3)        z          Orthogonal coordinates for Z in
#                                             Angstroms
#    55 - 60      Real(6.2)        occupancy  Occupancy.
#    61 - 66      Real(6.2)        tempFactor Temperature factor.
#    77 - 78      LString(2)       element    Element symbol, right-justified.
#    79 - 80      LString(2)       charge     Charge on the atom.

    def __init__(self,line):
        '''
        Constructor
        '''
        self.buf=line

    def recordName(self):
        return PDBRecord.genrecord(self.buf,self.irecord)

    def atomName(self):
        return PDBRecord.genrecord(self.buf,self.iname)

    def resName(self):
        return PDBRecord.genrecord(self.buf,self.iresname)

    def elemName(self):
        return PDBRecord.genrecord(self.buf,self.iel)

    def resId(self):
        return int(PDBRecord.genrecord(self.buf,self.iresid))

    def atomCoord(self):
        return [float(PDBRecord.genrecord(self.buf,self.ix)),
                float(PDBRecord.genrecord(self.buf,self.iy)),
                float(PDBRecord.genrecord(self.buf,self.iz))]

    def getDict(self):
        d = {}
        d["element"]=self.elemName()
        d["coords"]=self.atomCoord()
        d["name"]=self.atomName()
        d["resid"]=self.resId()
        d["resname"]=self.resName()

        return d

    @staticmethod
    def genrecord(buf,ir):
        return buf[ir[0]:ir[1]]

    def __str__(self):
        return self.buf

if __name__ == '__main__':
    aline1="ATOM    588 1HG  GLU    18     -13.363  -4.163  -2.372  1.00  0.00           H"
    pdb1 = PDBRecord(aline1)
    print aline1
    print pdb1.recordName()
    print pdb1.atomName()
    print pdb1.resName()
    print pdb1.resId()
    print pdb1.elemName()
    print pdb1.atomCoord()
    print pdb1.getDict()

#    Example
#             1         2         3         4         5         6         7         8
#    12345678901234567890123456789012345678901234567890123456789012345678901234567890
#    MODEL        1
#    ATOM      1  N   ALA     1      11.104   6.134  -6.504  1.00  0.00           N
#    ATOM      2  CA  ALA     1      11.639   6.071  -5.147  1.00  0.00           C
#    ...
#    ...
#    ATOM    293 1HG  GLU    18     -14.861  -4.847   0.361  1.00  0.00           H
#    ATOM    294 2HG  GLU    18     -13.518  -3.769   0.084  1.00  0.00           H

        <commit_msg>all static methods now<commit_after>'''
Created on Feb 7, 2012

@author: marat
'''
import string
from array import *
class PDBRecord:
    '''
    classdocs
    '''
    irecord=[0,6]
    inum=[6,11]
    iname=[12,16]
    iresname=[17,20]
    iresid=[22,26]
    ix=[30,38]
    iy=[38,46]
    iz=[46,54]
    iel=[76,78]

#     1 -  6      Record name      "ATOM    "
#     7 - 11      Integer          serial     Atom serial number.
#    13 - 16      Atom             name       Atom name.
#    17           Character        altLoc     Alternate location indicator.
#    18 - 20      Residue name     resName    Residue name.
#    22           Character        chainID    Chain identifier.
#    23 - 26      Integer          resSeq     Residue sequence number.
#    27           AChar            iCode      Code for insertion of residues.
#    31 - 38      Real(8.3)        x          Orthogonal coordinates for X in
#                                             Angstroms
#    39 - 46      Real(8.3)        y          Orthogonal coordinates for Y in
#                                             Angstroms
#    47 - 54      Real(8.3)        z          Orthogonal coordinates for Z in
#                                             Angstroms
#    55 - 60      Real(6.2)        occupancy  Occupancy.
#    61 - 66      Real(6.2)        tempFactor Temperature factor.
#    77 - 78      LString(2)       element    Element symbol, right-justified.
#    79 - 80      LString(2)       charge     Charge on the atom.

#    def __init__(self,line):
#        '''
#        Constructor
#        '''
#        pass

    @staticmethod
    def recordName(buf):
        return PDBRecord.genrecord(buf,PDBRecord.irecord)

    @staticmethod
    def atomName(buf):
        return PDBRecord.genrecord(buf,PDBRecord.iname)

    @staticmethod
    def resName(buf):
        return PDBRecord.genrecord(buf,PDBRecord.iresname)

    @staticmethod
    def elemName(buf):
        return PDBRecord.genrecord(buf,PDBRecord.iel)

    @staticmethod
    def resId(buf):
        return int(PDBRecord.genrecord(buf,PDBRecord.iresid))

    @staticmethod
    def atomCoord(buf):
        return [float(PDBRecord.genrecord(buf,PDBRecord.ix)),
                float(PDBRecord.genrecord(buf,PDBRecord.iy)),
                float(PDBRecord.genrecord(buf,PDBRecord.iz))]

    def getDict(self):
        d = {}
        d["element"]=self.elemName()
        d["coords"]=self.atomCoord()
        d["name"]=self.atomName()
        d["resid"]=self.resId()
        d["resname"]=self.resName()

        return d

    @staticmethod
    def genrecord(buf,ir):
        return buf[ir[0]:ir[1]]

    def __str__(self):
        return self.buf

if __name__ == '__main__':
    aline1="ATOM    588 1HG  GLU    18     -13.363  -4.163  -2.372  1.00  0.00           H"

    print aline1
    print PDBRecord.recordName(aline1)
    print PDBRecord.atomName(aline1)
    print PDBRecord.resName(aline1)
    print PDBRecord.resId(aline1)
    print PDBRecord.elemName(aline1)
    print PDBRecord.atomCoord(aline1)
#    print pdb1.getDict()

#    Example
#             1         2         3         4         5         6         7         8
#    12345678901234567890123456789012345678901234567890123456789012345678901234567890
#    MODEL        1
#    ATOM      1  N   ALA     1      11.104   6.134  -6.504  1.00  0.00           N
#    ATOM      2  CA  ALA     1      11.639   6.071  -5.147  1.00  0.00           C
#    ...
#    ...
#    ATOM    293 1HG  GLU    18     -14.861  -4.847   0.361  1.00  0.00           H
#    ATOM    294 2HG  GLU    18     -13.518  -3.769   0.084  1.00  0.00           H

        <|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# © 2013 - TODAY Denero Team. (www.deneroteam.com>)
# © 2017 Didotech srl (www.didotech.com)

from openerp.osv import orm, fields
from openerp import addons
from openerp.tools.translate import _

class res_partner_title(orm.Model):
    _inherit = "res.partner.title"
    _order = "sequence"
    _columns = {
        'sequence': fields.integer('Sequence'),
    }
    _defaults = {
        'sequence': 1,
    }

class res_contact_function(orm.Model):
    _name = "res.contact.function"
    _description = "Contact Function"
    _order = "name"
    _columns = {
        'name': fields.char('Name', size=32, required=1, select=1),
        'code': fields.char('Code', size=8),
    }

class res_partner_address_contact(orm.Model):
    _name = "res.partner.address.contact"
    _description = "Address Contact"

    def name_get(self, cr, uid, ids, context=None):
        res = []
        for rec in self.browse(cr, uid, ids, context=context):
            name = u"{name} {surname}".format(name=rec.last_name or '', surname=rec.first_name or '')
            if rec.title:
                name = u"{title} {name}".format(title=rec.title.name, name=name)
            res.append((rec.id, name))
        return res

    def _name_get_full(self, cr, uid, ids, prop, unknow_none, context=None):
        result = {}
        for rec in self.browse(cr, uid, ids, context=context):
            name = u"{name} {surname}".format(name=rec.last_name or '', surname=rec.first_name or '')
            if rec.title:
                name = u"{title} {name}".format(title=rec.title.name, name=name)
            result[rec.id] = name
        return result

    _columns = {
        'complete_name': fields.function(
            _name_get_full, string='Name', size=64, type="char", store=False, select=True),
        'name': fields.char('Name', size=64, ),
        'last_name': fields.char('Last Name', size=64),
        'first_name': fields.char('First Name', size=64),
        'mobile': fields.char('Mobile', size=64),
        'fisso': fields.char('Phone', size=64),
        'title': fields.many2one('res.partner.title', 'Title', domain=[('domain', '=', 'contact')]),
        'website': fields.char('Website', size=120),
        'address_id': fields.many2one('res.partner.address', 'Address'),
        'partner_id': fields.related(
            'address_id', 'partner_id', type='many2one', relation='res.partner', string='Main Employer'),
        'lang_id': fields.many2one('res.lang', 'Language'),
        'country_id': fields.many2one('res.country', 'Nationality'),
        'birthdate': fields.char('Birthdate', size=64),
        'active': fields.boolean('Active', help="If the active field is set to False,\
                 it will allow you to hide the partner contact without removing it."),
        'email': fields.char('E-Mail', size=240),
        'comment': fields.text('Notes', translate=True),
        'photo': fields.binary('Photo'),
        'function': fields.char("Function", size=64),
        'function_id': fields.many2one('res.contact.function', 'Function'),
        'opt_out': fields.related(
            'address_id', 'partner_id', 'opt_out', type='boolean', relation='res.partner', string='News Letter'),
    }

    def _get_photo(self, cr, uid, context=None):
        photo_path = addons.get_module_resource('base_address_contacts', 'images', 'photo.png')
        return open(photo_path, 'rb').read().encode('base64')

    _defaults = {
        'name': '/',
        'photo': _get_photo,
        'active': True,
        'address_id': lambda self, cr, uid, context: context.get('address_id', False),
    }

    _order = "last_name"

    def name_search(self, cr, uid, name='', args=None, operator='ilike', context=None, limit=None):
        if not args:
            args = []
        if context is None:
            context = self.pool['res.users'].context_get(cr, uid)
        if name:
            ids = self.search(
                cr, uid, ['|', ('last_name', operator, name), ('first_name', operator, name)] + args, limit=limit,
                context=context)
        else:
            ids = self.search(cr, uid, args, limit=limit, context=context)
        return self.name_get(cr, uid, ids, context=context)

    def create(self, cr, uid, vals, context=None):
        if context is None:
            context = self.pool['res.users'].context_get(cr, uid)
        name = ''
        update = False

        if vals.get('last_name', False):
            name += vals['last_name']
            update = True

        if vals.get('first_name', False):
            name += ' ' + vals['first_name']
            update = True

        if update:
            vals['name'] = name

        return super(res_partner_address_contact, self).create(cr, uid, vals, context=context)

    def write(self, cr, uid, ids, vals, context=None):
        if context is None:
            context = self.pool['res.users'].context_get(cr, uid)

        name = ''
        update = False

        if vals.get('last_name', False):
            name += vals['last_name']
            update = True

        if vals.get('first_name', False):
            name += ' ' + vals['first_name']
            update = True

        if update:
            vals['name'] = name

        return super(res_partner_address_contact, self).write(cr, uid, ids, vals, context)

class res_partner_address(orm.Model):
    _inherit = 'res.partner.address'

    def get_full_name(self, cr, uid, ids, field_name, arg, context=None):
        res = {}
        for re in self.browse(cr, uid, ids, context=context):
            addr = ''
            if re.partner_id:
                if re.partner_id.name != re.name:
                    addr = re.name or ''
                    if re.name and (re.city or re.country_id):
                        addr += ', '
            addr += (re.city or '') + ', ' + (re.street or '')
            if re.partner_id and context.get('contact_display', False) == 'partner_address':
                addr = "%s: %s" % (re.partner_id.name, addr.strip())
                # addr = re.partner_id.name + ': ' + addr
            else:
                addr = addr.strip()
            res[re.id] = addr or ''
        return res

    def name_get(self, cr, uid, ids, context=None):
        if not len(ids):
            return []
        res = []
        if not context:
            context = self.pool['res.users'].context_get(cr, uid)
        length = context.get('name_lenght', False) or 80
        for record in self.browse(cr, uid, ids, context=context):
            name = record.complete_name or record.name or ''
            # if len(name) > length:
            #    name = name[:length] + '...'
            res.append((record.id, name))
        return res

    def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100):
        if not args:
            args = []
        if context is None:
            context = self.pool['res.users'].context_get(cr, uid)
        ids = []
        name_array = name.split()
        search_domain = []
        for n in name_array:
            partner_ids = self.pool['res.partner'].search(cr, uid, [('name', operator, name)], limit=limit, context=context)
            search_domain.append('|')
            search_domain.append(('partner_id', 'in', partner_ids))
            search_domain.append(('name', operator, n))
            search_domain.append(('complete_name', operator, n))

        ids = self.search(cr, uid, search_domain + args, limit=limit, context=context)
        context['contact_display'] = 'partner_address'
        return self.name_get(cr, uid, ids, context=context)

    _columns = {
        'partner_id': fields.many2one('res.partner', 'Partner Name', ondelete='set null', select=True, help="Keep empty for a private address, not related to partner.", required=True),
        'contact_ids': fields.one2many('res.partner.address.contact', 'address_id', 'Functions and Contacts'),
        'mobile': fields.char('Mobile', size=64),
        'pec': fields.char('PEC', size=64),
        'complete_name': fields.function(get_full_name, method=True, type='char', size=1024, readonly=True, store=False),
    }

class res_partner(orm.Model):
    _inherit = 'res.partner'

    def _get_contacts(self, cr, uid, ids, field_name, arg, context=None):
        result = {}

        for partner in self.browse(cr, uid, ids, context):
            result[partner.id] = []
            for address in partner.address:
                result[partner.id] += [contact.id for contact in address.contact_ids]

        return result

    def create(self, cr, uid, vals, context):
        if context is None:
            context = self.pool['res.users'].context_get(cr, uid)
        if context.get('import', False):
            return super(res_partner, self).create(cr, uid, vals, context)
        if not vals.get('address', False) and context.get('default_type', '') != 'lead' and not context.get('install_mode', False):
            raise orm.except_orm(_('Error!'),
                                 _('At least one address of type "Default" is needed!'))
        is_default = False
        if context.get('default_type', '') == 'lead':
            return super(res_partner, self).create(cr, uid, vals, context)
        if vals.get('address', False):
            for address in vals['address']:
                if address[2].get('type') == 'default':
                    is_default = True
        if not is_default and not context.get('install_mode', False):
            raise orm.except_orm(_('Error!'),
                                 _('At least one address of type "Default" is needed!'))

        return super(res_partner, self).create(cr, uid, vals, context)

    def write(self, cr, uid, ids, vals, context=None):
        if context is None:
            context = self.pool['res.users'].context_get(cr, uid)
        if vals.get('address', False):
            address_model = self.pool['res.partner.address']
            default_address = 'unknown'
            for address in vals['address']:
                if address[0] == 0:   # 0 - create
                    if address[2].get('type', '') == 'default':
                        default_address = 'new'
                elif address[0] == 1:   # 0 - create, 1 - update
                    if address_model.browse(cr, uid, address[1], context).type == 'default':
                        default_address = 'setted'
                elif address[0] == 2:  # 2 means 'delete'
                    if address_model.browse(cr, uid, address[1], context).type == 'default':
                        if not default_address in ('new', 'setted'):
                            default_address = 'deleted'
            if default_address == 'deleted':
                raise orm.except_orm(
                    _('Error!'),
                    _('At least one address of type "Default" is needed!')
                )

            # Delete before adding new address, so we will escape a problem with duplicated addresses
            vals['address'].sort(key=lambda address: address[0], reverse=True)

        return super(res_partner, self).write(cr, uid, ids, vals, context)

    def unlink(self, cr, uid, ids, context):
        if context is None:
            context = self.pool['res.users'].context_get(cr, uid)
        for partner in self.browse(cr, uid, ids, context):
            if partner.address:
                raise orm.except_orm(
                    _('Error!'),
                    _('Before Deleting the Partner, you need to delete the Address from menù')
                )
        return super(res_partner, self).unlink(cr, uid, ids, context)

    _columns = {
        'contact_ids': fields.function(
            _get_contacts, string=_("Functions and Contacts"),
            type='one2many', method=True, obj='res.partner.address.contact'
        ),
        'opt_out': fields.boolean('Opt-out'),
    }
<commit_msg>force for partner address<commit_after># -*- coding: utf-8 -*-
# © 2013 - TODAY Denero Team. (www.deneroteam.com>)
# © 2017 Didotech srl (www.didotech.com)

from openerp.osv import orm, fields
from openerp import addons
from openerp.tools.translate import _

class res_partner_title(orm.Model):
    _inherit = "res.partner.title"
    _order = "sequence"
    _columns = {
        'sequence': fields.integer('Sequence'),
    }
    _defaults = {
        'sequence': 1,
    }

class res_contact_function(orm.Model):
    _name = "res.contact.function"
    _description = "Contact Function"
    _order = "name"
    _columns = {
        'name': fields.char('Name', size=32, required=1, select=1),
        'code': fields.char('Code', size=8),
    }

class res_partner_address_contact(orm.Model):
    _name = "res.partner.address.contact"
    _description = "Address Contact"

    def name_get(self, cr, uid, ids, context=None):
        res = []
        for rec in self.browse(cr, uid, ids, context=context):
            name = u"{name} {surname}".format(name=rec.last_name or '', surname=rec.first_name or '')
            if rec.title:
                name = u"{title} {name}".format(title=rec.title.name, name=name)
            res.append((rec.id, name))
        return res

    def _name_get_full(self, cr, uid, ids, prop, unknow_none, context=None):
        result = {}
        for rec in self.browse(cr, uid, ids, context=context):
            name = u"{name} {surname}".format(name=rec.last_name or '', surname=rec.first_name or '')
            if rec.title:
                name = u"{title} {name}".format(title=rec.title.name, name=name)
            result[rec.id] = name
        return result

    _columns = {
        'complete_name': fields.function(
            _name_get_full, string='Name', size=64, type="char", store=False, select=True),
        'name': fields.char('Name', size=64, ),
        'last_name': fields.char('Last Name', size=64),
        'first_name': fields.char('First Name', size=64),
        'mobile': fields.char('Mobile', size=64),
        'fisso': fields.char('Phone', size=64),
        'title': fields.many2one('res.partner.title', 'Title', domain=[('domain', '=', 'contact')]),
        'website': fields.char('Website', size=120),
        'address_id': fields.many2one('res.partner.address', 'Address'),
        'partner_id': fields.related(
            'address_id', 'partner_id', type='many2one', relation='res.partner', string='Main Employer'),
        'lang_id': fields.many2one('res.lang', 'Language'),
        'country_id': fields.many2one('res.country', 'Nationality'),
        'birthdate': fields.char('Birthdate', size=64),
        'active': fields.boolean('Active', help="If the active field is set to False,\
                 it will allow you to hide the partner contact without removing it."),
        'email': fields.char('E-Mail', size=240),
        'comment': fields.text('Notes', translate=True),
        'photo': fields.binary('Photo'),
        'function': fields.char("Function", size=64),
        'function_id': fields.many2one('res.contact.function', 'Function'),
        'opt_out': fields.related(
            'address_id', 'partner_id', 'opt_out', type='boolean', relation='res.partner', string='News Letter'),
    }

    def _get_photo(self, cr, uid, context=None):
        photo_path = addons.get_module_resource('base_address_contacts', 'images', 'photo.png')
        return open(photo_path, 'rb').read().encode('base64')

    _defaults = {
        'name': '/',
        'photo': _get_photo,
        'active': True,
        'address_id': lambda self, cr, uid, context: context.get('address_id', False),
    }

    _order = "last_name"

    def name_search(self, cr, uid, name='', args=None, operator='ilike', context=None, limit=None):
        if not args:
            args = []
        if context is None:
            context = self.pool['res.users'].context_get(cr, uid)
        if name:
            ids = self.search(
                cr, uid, ['|', ('last_name', operator, name), ('first_name', operator, name)] + args, limit=limit,
                context=context)
        else:
            ids = self.search(cr, uid, args, limit=limit, context=context)
        return self.name_get(cr, uid, ids, context=context)

    def create(self, cr, uid, vals, context=None):
        if context is None:
            context = self.pool['res.users'].context_get(cr, uid)
        name = ''
        update = False

        if vals.get('last_name', False):
            name += vals['last_name']
            update = True

        if vals.get('first_name', False):
            name += ' ' + vals['first_name']
            update = True

        if update:
            vals['name'] = name

        return super(res_partner_address_contact, self).create(cr, uid, vals, context=context)

    def write(self, cr, uid, ids, vals, context=None):
        if context is None:
            context = self.pool['res.users'].context_get(cr, uid)

        name = ''
        update = False

        if vals.get('last_name', False):
            name += vals['last_name']
            update = True

        if vals.get('first_name', False):
            name += ' ' + vals['first_name']
            update = True

        if update:
            vals['name'] = name

        return super(res_partner_address_contact, self).write(cr, uid, ids, vals, context)

class res_partner_address(orm.Model):
    _inherit = 'res.partner.address'

    def get_full_name(self, cr, uid, ids, field_name, arg, context=None):
        res = {}
        for re in self.browse(cr, uid, ids, context=context):
            addr = ''
            if re.partner_id:
                if re.partner_id.name != re.name:
                    addr = re.name or ''
                    if re.name and (re.city or re.country_id):
                        addr += ', '
            addr += (re.city or '') + ', ' + (re.street or '')
            if re.partner_id and context.get('contact_display', False) in ['partner_address', 'partner']:
                addr = "%s: %s" % (re.partner_id.name.upper(), addr.strip())
                # addr = re.partner_id.name + ': ' + addr
            else:
                addr = addr.strip()
            res[re.id] = addr or ''
        return res

    def name_get(self, cr, uid, ids, context=None):
        if not len(ids):
            return []
        res = []
        if not context:
            context = self.pool['res.users'].context_get(cr, uid)
        length = context.get('name_lenght', False) or 80
        for record in self.browse(cr, uid, ids, context=context):
            name = record.complete_name or record.name or ''
            # if len(name) > length:
            #    name = name[:length] + '...'
            res.append((record.id, name))
        return res

    def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100):
        if not args:
            args = []
        if context is None:
            context = self.pool['res.users'].context_get(cr, uid)
        ids = []
        name_array = name.split()
        search_domain = []
        for n in name_array:
            partner_ids = self.pool['res.partner'].search(cr, uid, [('name', operator, name)], limit=limit, context=context)
            search_domain.append('|')
            search_domain.append(('partner_id', 'in', partner_ids))
            search_domain.append(('name', operator, n))
            search_domain.append(('complete_name', operator, n))

        ids = self.search(cr, uid, search_domain + args, limit=limit, context=context)
        # context['contact_display'] = 'partner_address'
        return self.name_get(cr, uid, ids, context=context)

    _columns = {
        'partner_id': fields.many2one('res.partner', 'Partner Name', ondelete='set null', select=True, help="Keep empty for a private address, not related to partner.", required=True),
        'contact_ids': fields.one2many('res.partner.address.contact', 'address_id', 'Functions and Contacts'),
        'mobile': fields.char('Mobile', size=64),
        'pec': fields.char('PEC', size=64),
        'complete_name': fields.function(get_full_name, method=True, type='char', size=1024, readonly=True, store=False),
    }

class res_partner(orm.Model):
    _inherit = 'res.partner'

    def _get_contacts(self, cr, uid, ids, field_name, arg, context=None):
        result = {}

        for partner in self.browse(cr, uid, ids, context):
            result[partner.id] = []
            for address in partner.address:
                result[partner.id] += [contact.id for contact in address.contact_ids]

        return result

    def create(self, cr, uid, vals, context):
        if context is None:
            context = self.pool['res.users'].context_get(cr, uid)
        if context.get('import', False):
            return super(res_partner, self).create(cr, uid, vals, context)
        if not vals.get('address', False) and context.get('default_type', '') != 'lead' and not context.get('install_mode', False):
            raise orm.except_orm(_('Error!'),
                                 _('At least one address of type "Default" is needed!'))
        is_default = False
        if context.get('default_type', '') == 'lead':
            return super(res_partner, self).create(cr, uid, vals, context)
        if vals.get('address', False):
            for address in vals['address']:
                if address[2].get('type') == 'default':
                    is_default = True
        if not is_default and not context.get('install_mode', False):
            raise orm.except_orm(_('Error!'),
                                 _('At least one address of type "Default" is needed!'))

        return super(res_partner, self).create(cr, uid, vals, context)

    def write(self, cr, uid, ids, vals, context=None):
        if context is None:
            context = self.pool['res.users'].context_get(cr, uid)
        if vals.get('address', False):
            address_model = self.pool['res.partner.address']
            default_address = 'unknown'
            for address in vals['address']:
                if address[0] == 0:   # 0 - create
                    if address[2].get('type', '') == 'default':
                        default_address = 'new'
                elif address[0] == 1:   # 0 - create, 1 - update
                    if address_model.browse(cr, uid, address[1], context).type == 'default':
                        default_address = 'setted'
                elif address[0] == 2:  # 2 means 'delete'
                    if address_model.browse(cr, uid, address[1], context).type == 'default':
                        if not default_address in ('new', 'setted'):
                            default_address = 'deleted'
            if default_address == 'deleted':
                raise orm.except_orm(
                    _('Error!'),
                    _('At least one address of type "Default" is needed!')
                )

            # Delete before adding new address, so we will escape a problem with duplicated addresses
            vals['address'].sort(key=lambda address: address[0], reverse=True)

        return super(res_partner, self).write(cr, uid, ids, vals, context)

    def unlink(self, cr, uid, ids, context):
        if context is None:
            context = self.pool['res.users'].context_get(cr, uid)
        for partner in self.browse(cr, uid, ids, context):
            if partner.address:
                raise orm.except_orm(
                    _('Error!'),
                    _('Before Deleting the Partner, you need to delete the Address from menù')
                )
        return super(res_partner, self).unlink(cr, uid, ids, context)

    _columns = {
        'contact_ids': fields.function(
            _get_contacts, string=_("Functions and Contacts"),
            type='one2many', method=True, obj='res.partner.address.contact'
        ),
        'opt_out': fields.boolean('Opt-out'),
    }
<|endoftext|>


<commit_before># encoding=utf-8

from __future__ import unicode_literals, division
import os
import re

from django.core.files.base import File, ContentFile
from django.core.files.storage import Storage, default_storage
from django.utils.functional import LazyObject, empty
from sorl.thumbnail import default
from sorl.thumbnail.conf import settings
from sorl.thumbnail.compat import (json, urlopen, urlparse, urlsplit,
                                   quote, quote_plus,
                                   URLError, force_unicode, encode)
from sorl.thumbnail.helpers import ThumbnailError, tokey, get_module_class, deserialize
from sorl.thumbnail.parsers import parse_geometry

url_pat = re.compile(r'^(https?|ftp):\/\/')

def serialize_image_file(image_file):
    if image_file.size is None:
        raise ThumbnailError('Trying to serialize an ``ImageFile`` with a '
                             '``None`` size.')
    data = {
        'name': image_file.name,
        'storage': image_file.serialize_storage(),
        'size': image_file.size,
    }
    return json.dumps(data)

def deserialize_image_file(s):
    data = deserialize(s)

    class LazyStorage(LazyObject):
        def _setup(self):
            self._wrapped = get_module_class(data['storage'])()

    image_file = ImageFile(data['name'], LazyStorage())
    image_file.set_size(data['size'])
    return image_file

class BaseImageFile(object):
    size = []

    def exists(self):
        raise NotImplementedError()

    @property
    def width(self):
        return self.size[0]

    x = width

    @property
    def height(self):
        return self.size[1]

    y = height

    def is_portrait(self):
        return self.y > self.x

    @property
    def ratio(self):
        return float(self.x) / float(self.y)

    @property
    def url(self):
        raise NotImplementedError()

    src = url

class ImageFile(BaseImageFile):
    _size = None

    def __init__(self, file_, storage=None):
        if not file_:
            raise ThumbnailError('File is empty.')

        # figure out name
        if hasattr(file_, 'name'):
            self.name = file_.name
        else:
            self.name = force_unicode(file_)

        # figure out storage
        if storage is not None:
            self.storage = storage
        elif hasattr(file_, 'storage'):
            self.storage = file_.storage
        elif url_pat.match(self.name):
            self.storage = UrlStorage()
        else:
            self.storage = default_storage

        if hasattr(self.storage, 'location'):
            location = self.storage.location
            if not self.storage.location.endswith("/"):
                location += "/"
            if self.name.startswith(location):
                self.name = self.name[len(location):]

    def __unicode__(self):
        return self.name

    def exists(self):
        return self.storage.exists(self.name)

    def set_size(self, size=None):
        # set the size if given
        if size is not None:
            pass
        # Don't try to set the size the expensive way if it already has a
        # value.
        elif self._size is not None:
            return
        elif hasattr(self.storage, 'image_size'):
            # Storage backends can implement ``image_size`` method that
            # optimizes this.
            size = self.storage.image_size(self.name)
        else:
            # This is the worst case scenario
            image = default.engine.get_image(self)
            size = default.engine.get_image_size(image)
        self._size = list(size)

    @property
    def size(self):
        return self._size

    @property
    def url(self):
        return self.storage.url(self.name)

    def read(self):
        return self.storage.open(self.name).read()

    def write(self, content):
        if not isinstance(content, File):
            content = ContentFile(content)

        self._size = None
        self.name = self.storage.save(self.name, content)

        return self.name

    def delete(self):
        return self.storage.delete(self.name)

    def serialize_storage(self):
        if isinstance(self.storage, LazyObject):
            # if storage is wrapped in a lazy object we need to get the real
            # thing.
            if self.storage._wrapped is empty:
                self.storage._setup()
            cls = self.storage._wrapped.__class__
        else:
            cls = self.storage.__class__
        return '%s.%s' % (cls.__module__, cls.__name__)

    @property
    def key(self):
        return tokey(self.name, self.serialize_storage())

    def serialize(self):
        return serialize_image_file(self)

class DummyImageFile(BaseImageFile):
    def __init__(self, geometry_string):
        self.size = parse_geometry(
            geometry_string,
            settings.THUMBNAIL_DUMMY_RATIO,
        )

    def exists(self):
        return True

    @property
    def url(self):
        return settings.THUMBNAIL_DUMMY_SOURCE % (
            {'width': self.x, 'height': self.y}
        )

class UrlStorage(Storage):
    def normalize_url(self, url, charset='utf-8'):
        url = encode(url, charset, 'ignore')
        scheme, netloc, path, qs, anchor = urlsplit(url)

        # Encode to utf8 to prevent urllib KeyError
        path = encode(path, charset, 'ignore')

        path = quote(path, '/%')
        qs = quote_plus(qs, ':&%=')

        return urlparse.urlunsplit((scheme, netloc, path, qs, anchor))

    def open(self, name, mode='rb'):
        return urlopen(self.normalize_url(name))

    def exists(self, name):
        try:
            self.open(name)
        except URLError:
            return False
        return True

    def url(self, name):
        return name

    def delete(self, name):
        pass

def delete_all_thumbnails():
    storage = default.storage
    path = os.path.join(storage.location, settings.THUMBNAIL_PREFIX)

    def walk(path):
        dirs, files = storage.listdir(path)
        for f in files:
            storage.delete(os.path.join(path, f))
        for d in dirs:
            directory = os.path.join(path, d)
            walk(directory)
            try:
                full_path = storage.path(directory)
            except Exception:
                continue
            os.rmdir(full_path)

    walk(path)
<commit_msg>Fix default_storage to be from thumbnail.defaults and not from django<commit_after># encoding=utf-8

from __future__ import unicode_literals, division
import os
import re

from django.core.files.base import File, ContentFile
from django.core.files.storage import Storage#, default_storage
from django.utils.functional import LazyObject, empty
from sorl.thumbnail import default
from sorl.thumbnail.conf import settings
from sorl.thumbnail.compat import (json, urlopen, urlparse, urlsplit,
                                   quote, quote_plus,
                                   URLError, force_unicode, encode)
from sorl.thumbnail.default import storage as default_storage
from sorl.thumbnail.helpers import ThumbnailError, tokey, get_module_class, deserialize
from sorl.thumbnail.parsers import parse_geometry

url_pat = re.compile(r'^(https?|ftp):\/\/')

def serialize_image_file(image_file):
    if image_file.size is None:
        raise ThumbnailError('Trying to serialize an ``ImageFile`` with a '
                             '``None`` size.')
    data = {
        'name': image_file.name,
        'storage': image_file.serialize_storage(),
        'size': image_file.size,
    }
    return json.dumps(data)

def deserialize_image_file(s):
    data = deserialize(s)

    class LazyStorage(LazyObject):
        def _setup(self):
            self._wrapped = get_module_class(data['storage'])()

    image_file = ImageFile(data['name'], LazyStorage())
    image_file.set_size(data['size'])
    return image_file

class BaseImageFile(object):
    size = []

    def exists(self):
        raise NotImplementedError()

    @property
    def width(self):
        return self.size[0]

    x = width

    @property
    def height(self):
        return self.size[1]

    y = height

    def is_portrait(self):
        return self.y > self.x

    @property
    def ratio(self):
        return float(self.x) / float(self.y)

    @property
    def url(self):
        raise NotImplementedError()

    src = url

class ImageFile(BaseImageFile):
    _size = None

    def __init__(self, file_, storage=None):
        if not file_:
            raise ThumbnailError('File is empty.')

        # figure out name
        if hasattr(file_, 'name'):
            self.name = file_.name
        else:
            self.name = force_unicode(file_)

        # figure out storage
        if storage is not None:
            self.storage = storage
        elif hasattr(file_, 'storage'):
            self.storage = file_.storage
        elif url_pat.match(self.name):
            self.storage = UrlStorage()
        else:
            self.storage = default_storage

        if hasattr(self.storage, 'location'):
            location = self.storage.location
            if not self.storage.location.endswith("/"):
                location += "/"
            if self.name.startswith(location):
                self.name = self.name[len(location):]

    def __unicode__(self):
        return self.name

    def exists(self):
        return self.storage.exists(self.name)

    def set_size(self, size=None):
        # set the size if given
        if size is not None:
            pass
        # Don't try to set the size the expensive way if it already has a
        # value.
        elif self._size is not None:
            return
        elif hasattr(self.storage, 'image_size'):
            # Storage backends can implement ``image_size`` method that
            # optimizes this.
            size = self.storage.image_size(self.name)
        else:
            # This is the worst case scenario
            image = default.engine.get_image(self)
            size = default.engine.get_image_size(image)
        self._size = list(size)

    @property
    def size(self):
        return self._size

    @property
    def url(self):
        return self.storage.url(self.name)

    def read(self):
        return self.storage.open(self.name).read()

    def write(self, content):
        if not isinstance(content, File):
            content = ContentFile(content)

        self._size = None
        self.name = self.storage.save(self.name, content)

        return self.name

    def delete(self):
        return self.storage.delete(self.name)

    def serialize_storage(self):
        if isinstance(self.storage, LazyObject):
            # if storage is wrapped in a lazy object we need to get the real
            # thing.
            if self.storage._wrapped is empty:
                self.storage._setup()
            cls = self.storage._wrapped.__class__
        else:
            cls = self.storage.__class__
        return '%s.%s' % (cls.__module__, cls.__name__)

    @property
    def key(self):
        return tokey(self.name, self.serialize_storage())

    def serialize(self):
        return serialize_image_file(self)

class DummyImageFile(BaseImageFile):
    def __init__(self, geometry_string):
        self.size = parse_geometry(
            geometry_string,
            settings.THUMBNAIL_DUMMY_RATIO,
        )

    def exists(self):
        return True

    @property
    def url(self):
        return settings.THUMBNAIL_DUMMY_SOURCE % (
            {'width': self.x, 'height': self.y}
        )

class UrlStorage(Storage):
    def normalize_url(self, url, charset='utf-8'):
        url = encode(url, charset, 'ignore')
        scheme, netloc, path, qs, anchor = urlsplit(url)

        # Encode to utf8 to prevent urllib KeyError
        path = encode(path, charset, 'ignore')

        path = quote(path, '/%')
        qs = quote_plus(qs, ':&%=')

        return urlparse.urlunsplit((scheme, netloc, path, qs, anchor))

    def open(self, name, mode='rb'):
        return urlopen(self.normalize_url(name))

    def exists(self, name):
        try:
            self.open(name)
        except URLError:
            return False
        return True

    def url(self, name):
        return name

    def delete(self, name):
        pass

def delete_all_thumbnails():
    storage = default.storage
    path = os.path.join(storage.location, settings.THUMBNAIL_PREFIX)

    def walk(path):
        dirs, files = storage.listdir(path)
        for f in files:
            storage.delete(os.path.join(path, f))
        for d in dirs:
            directory = os.path.join(path, d)
            walk(directory)
            try:
                full_path = storage.path(directory)
            except Exception:
                continue
            os.rmdir(full_path)

    walk(path)
<|endoftext|>


<commit_before>import logging

from etcdocker import util

LOG = logging.getLogger("etcdocker")

class Container(object):
    def __init__(self, name, params):
        self.name = name
        self.params = params
        self.docker_params = {}

    def set_or_create_param(self, key, value):
        self.params[key] = value
        LOG.info("Set param '%s' on '%s'" % (key, self.name))

    def update_params(self, params):
        """
        Checks if container's param keys have changed and
        makes changes to container if required.

        TODO: Only handles adds right now (swat30)

        args:
            container (obj) - Container
            params (dict) - New params to check

        Returns: (bool)
            Let us know if they have changed
        """
        has_changed = False

        for param, val in params.iteritems():
            # Check for new or changed params
            if (param not in self.params.keys() or
                    val != self.params.get(param)):
                self.set_or_create_param(param, val)
                has_changed = True

        return has_changed

    def ensure_running(self, force_restart=False):
        """
        Ensure an up to date version of the container is running

        args:
            force_restart (bool) - restart even if already up
        """
        # Ensure container is running with specified params
        containers = util.get_containers()
        found = False

        for pc in containers:
            if "/%s" % self.name in pc['Names']:
                found = True
                full_image = "%s:%s" % (
                    self.params.get('image'), self.params.get('tag'))
                if (pc['Status'].startswith('Up') and
                        pc['Image'] == full_image and
                        not force_restart):
                    return
                break

        if found:
            # Shut down old container first
            util.stop_and_rm_docker_container(self.name)

        self.docker_params = util.convert_params(self.params)
        self.create()
        self.start()

    def create(self):
        # Create container with specified args
        util.create_docker_container(self.name, self.docker_params)

    def start(self):
        # Start 'er up
        util.start_docker_container(self.name, self.docker_params)
<commit_msg>Some additional logging<commit_after>import logging

from etcdocker import util

LOG = logging.getLogger("etcdocker")

class Container(object):
    def __init__(self, name, params):
        self.name = name
        self.params = params
        self.docker_params = {}

    def set_or_create_param(self, key, value):
        self.params[key] = value
        LOG.info("Set param '%s' on '%s'" % (key, self.name))

    def update_params(self, params):
        """
        Checks if container's param keys have changed and
        makes changes to container if required.

        TODO: Only handles adds right now (swat30)

        args:
            container (obj) - Container
            params (dict) - New params to check

        Returns: (bool)
            Let us know if they have changed
        """
        has_changed = False

        for param, val in params.iteritems():
            # Check for new or changed params
            if (param not in self.params.keys() or
                    val != self.params.get(param)):
                self.set_or_create_param(param, val)
                has_changed = True

        return has_changed

    def ensure_running(self, force_restart=False):
        """
        Ensure an up to date version of the container is running

        args:
            force_restart (bool) - restart even if already up
        """
        # Ensure container is running with specified params
        containers = util.get_containers()
        found = False

        for pc in containers:
            if "/%s" % self.name in pc['Names']:
                found = True
                full_image = "%s:%s" % (
                    self.params.get('image'), self.params.get('tag'))
                if (pc['Status'].startswith('Up') and
                        pc['Image'] == full_image and
                        not force_restart):
                    return
                break

        if found:
            # Shut down old container first
            LOG.warning("Stopping %s..." % self.name)
            util.stop_and_rm_docker_container(self.name)

        self.docker_params = util.convert_params(self.params)
        LOG.warning("Starting %s..." % self.name)
        self.create()
        self.start()

    def create(self):
        # Create container with specified args
        util.create_docker_container(self.name, self.docker_params)

    def start(self):
        # Start 'er up
        util.start_docker_container(self.name, self.docker_params)
<|endoftext|>


<commit_before>#!/usr/bin/python -tt
# Copyright 2010 Google Inc.
# Licensed under the Apache License, Version 2.0
# http://www.apache.org/licenses/LICENSE-2.0

# Google's Python Class
# http://code.google.com/edu/languages/google-python-class/

"""Mimic pyquick exercise -- optional extra exercise.
Google's Python Class

Read in the file specified on the command line.
Do a simple split() on whitespace to obtain all the words in the file.
Rather than read the file line by line, it's easier to read
it into one giant string and split it once.

Build a "mimic" dict that maps each word that appears in the file
to a list of all the words that immediately follow that word in the file.
The list of words can be be in any order and should include
duplicates. So for example the key "and" might have the list
["then", "best", "then", "after", ...] listing
all the words which came after "and" in the text.
We'll say that the empty string is what comes before
the first word in the file.

With the mimic dict, it's fairly easy to emit random
text that mimics the original. Print a word, then look
up what words might come next and pick one at random as
the next work.
Use the empty string as the first word to prime things.
If we ever get stuck with a word that is not in the dict,
go back to the empty string to keep things moving.

Note: the standard python module 'random' includes a
random.choice(list) method which picks a random element
from a non-empty list.

For fun, feed your program to itself as input.
Could work on getting it to put in linebreaks around 70
columns, so the output looks better.

"""

import random
import sys
import string

def mimic_dict(filename):
  """Returns mimic dict mapping each word to list of words which follow it."""

  # Open file, read text, split into word list
  f = open(filename, 'rU')
  text = f.read()
  words = text.split()

  # Build dictionary of words following other words
  dictFollowingWords = {'': words[0]}
  for i in range(0, len(words[:100])):
    word = words[i]
    nextWord = words[i+1]

    #####################################
    #####################################
    ### HERE HERE HERE HERE
    #####################################
    #####################################
    if word in dictFollowingWords:
      dictFollowingWords['word'] = dictFollowingWords['word'].append('word')
    else:
      dictFollowingWords['word'] = [nextWord]

    print dictFollowingWords
  return

def print_mimic(mimic_dict, word):
  """Given mimic dict and start word, prints 200 random words."""
  # +++your code here+++
  return

# Provided main(), calls mimic_dict() and mimic()
def main():
  if len(sys.argv) != 2:
    print 'usage: ./mimic.py file-to-read'
    sys.exit(1)

  dict = mimic_dict(sys.argv[1])
  print_mimic(dict, '')

if __name__ == '__main__':
  main()
<commit_msg>Finished exercise<commit_after>#!/usr/bin/python -tt
# Copyright 2010 Google Inc.
# Licensed under the Apache License, Version 2.0
# http://www.apache.org/licenses/LICENSE-2.0

# Google's Python Class
# http://code.google.com/edu/languages/google-python-class/

"""Mimic pyquick exercise -- optional extra exercise.
Google's Python Class

Read in the file specified on the command line.
Do a simple split() on whitespace to obtain all the words in the file.
Rather than read the file line by line, it's easier to read
it into one giant string and split it once.

Build a "mimic" dict that maps each word that appears in the file
to a list of all the words that immediately follow that word in the file.
The list of words can be be in any order and should include
duplicates. So for example the key "and" might have the list
["then", "best", "then", "after", ...] listing
all the words which came after "and" in the text.
We'll say that the empty string is what comes before
the first word in the file.

With the mimic dict, it's fairly easy to emit random
text that mimics the original. Print a word, then look
up what words might come next and pick one at random as
the next work.
Use the empty string as the first word to prime things.
If we ever get stuck with a word that is not in the dict,
go back to the empty string to keep things moving.

Note: the standard python module 'random' includes a
random.choice(list) method which picks a random element
from a non-empty list.

For fun, feed your program to itself as input.
Could work on getting it to put in linebreaks around 70
columns, so the output looks better.

"""

import random
import sys
import string
from random import randint

def mimic_dict(filename):
  """Returns mimic dict mapping each word to list of words which follow it."""

  # Open file, read text, split into word list
  f = open(filename, 'rU')
  text = f.read()
  words = text.split()

  # Build dictionary of words following other words
  mimic_dict = {'': [words[0]]}
  for i in range(0, len(words)-1):
    word = words[i]
    nextWord = words[i+1]

    if word not in mimic_dict.keys():
      mimic_dict[word] = [nextWord]
    else:
      mimic_dict[word].append(nextWord)

  return mimic_dict

def print_mimic(mimic_dict, word):

  mimic_list = [word]
  mimic_string = ''
  for i in range(0,199):
    lastWord = mimic_list[-1]
    if lastWord not in mimic_dict.keys():
      nextWord = ''
    else:
      nextWords = mimic_dict[lastWord]
      nextWord = nextWords[randint(1, len(nextWords))-1]
    mimic_list.append(nextWord)
    mimic_string = mimic_string + ' ' + mimic_list[-1]

  print mimic_string
  return

# Provided main(), calls mimic_dict() and mimic()
def main():
  if len(sys.argv) != 2:
    print 'usage: ./mimic.py file-to-read'
    sys.exit(1)

  dict = mimic_dict(sys.argv[1])
  print_mimic(dict, '')

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