<commit_before>import json
from dateutil.parser import parse as parse_timestamp
import requests
from requests import RequestException
from microcosm.api.exceptions import APIException
from microweb.helpers import DateTimeEncoder
from microweb.helpers import build_url

# Item types that can have comments
COMMENTABLE_ITEM_TYPES = [
    'event',
    'conversation',
    'poll'
]

class APIResource(object):
    """
    Base API resource that performs HTTP operations. Each API class should subclass this
    to deal with custom validation and JSON processing.
    """

    @classmethod
    def retrieve(cls, host, id=None, offset=None, access_token=None, url_override=None):
        """
        GET an API resource. If resource ID is omitted, returns a list. Appends access_token
        and offset (for paging) if provided.
        """

        headers = {'Host': host}

        if url_override:
            resource_url = url_override
        else:
            path_fragments = [cls.resource_fragment]
            if id: path_fragments.append(id)
            resource_url = build_url(host, path_fragments)

        params = {}
        if access_token: params['access_token'] = access_token
        if offset: params['offset'] = offset

        response = requests.get(resource_url, params=params, headers=headers)

        try:
            resource = response.json()
        except ValueError:
            raise APIException('Response not valid json: %s' % response.content, 500)

        if resource['error']:
            raise APIException(resource['error'], response.status_code)

        if not resource['data']:
            raise APIException('No data returned at: %s' % resource_url)

        return resource['data']

    @classmethod
    def create(cls, host, data, access_token, headers=None):
        """
        Create an API resource with POST.
        """

        resource_url = build_url(host, [cls.resource_fragment])
        params = {'access_token': access_token}

        if headers:
            headers['Content-Type'] = 'application/json'
            headers['Host'] = host
        else:
            headers = {
                'Content-Type': 'application/json',
                'Host': host
            }

        response = requests.post(
            resource_url,
            data=json.dumps(data, cls=DateTimeEncoder),
            headers=headers,
            params=params
        )

        try:
            resource = response.json()
        except ValueError:
            raise APIException('Response not valid json: %s' % response.content, 500)

        if resource['error']:
            raise APIException(resource['error'], response.status_code)

        if not resource['data']:
            raise APIException('No data returned at: %s' % resource_url)

        return resource['data']

    @classmethod
    def update(cls, host, data, id, access_token):
        """
        Update an API resource with PUT.
        """

        resource_url = build_url(host, [cls.resource_fragment, id])

        headers = {
            'Content-Type': 'application/json',
            'Host': host,
        }
        params = {
            'method': 'PUT',
            'access_token': access_token,
        }

        response = requests.post(
            resource_url,
            data=json.dumps(data, cls=DateTimeEncoder),
            headers=headers,
            params=params
        )

        try:
            resource = response.json()
        except ValueError:
            raise APIException('The API has returned invalid json: %s' % response.content, 500)

        if resource['error']:
            raise APIException(resource['error'], response.status_code)

        if not resource['data']:
            raise APIException('No data returned at: %s' % resource_url)

        return resource['data']

    @classmethod
    def delete(cls, host, id, access_token):
        """
        DELETE an API resource. ID must be supplied.

        A 'data' object is never returned by a DELETE, so this
        method will raise an exception on failure. In normal
        operation the method simply returns.
        """

        path_fragments = [cls.resource_fragment]

        if id:
            path_fragments.append(id)
        elif access_token:
            path_fragments.append(access_token)
        else:
            raise AssertionError, 'You must supply either an id or '\
                                  'an access_token to delete'

        resource_url = build_url(host, path_fragments)
        params = {
            'method': 'DELETE',
            'access_token': access_token,
        }
        headers = {'Host': host}
        response = requests.post(resource_url, params=params, headers=headers)

        try:
            resource = response.json()
        except ValueError:
            raise APIException('The API has returned invalid json: %s' % response.content, 500)

        if resource['error']:
            raise APIException(resource['error'], response.status_code)

class Site(APIResource):
    item_type = 'site'
    resource_fragment = 'site'

    @classmethod
    def retrieve(cls, host):
        resource = super(Site, cls).retrieve(host)
        return Site(resource)

    def __init__(self, data):
        self.site_id = data['siteId']
        self.title = data['title']
        self.description = data['description']
        self.subdomain_key = data['subdomainKey']
        self.domain = data['domain']
        self.owned_by = Profile(data['ownedBy'])
        self.logo_url = data['logo_url']

class User(APIResource):
    item_type = 'user'
    resource_fragment = 'users'

    @classmethod
    def retrieve(cls, host, id, access_token):
        resource = super(User, cls).retrieve(host, id=id, access_token=access_token)
        return User(resource)

    # Currently only 'email is used on User objects
    def __init__(self, data):
        self.email_address = data['email']

class Authentication(APIResource):
    resource_fragment = 'auth'

class WhoAmI(APIResource):
    item_type = 'whoami'
    resource_fragment = 'whoami'

    @classmethod
    def retrieve(cls, host, access_token):
        resource = super(WhoAmI, cls).retrieve(host, access_token=access_token)
        return Profile(resource)

class Profile(APIResource):
    item_type = 'profile'
    resource_fragment = 'profiles'

    @classmethod
    def retrieve(cls, host, id, access_token=None):
        resource = super(Profile, cls).retrieve(host, id, access_token=access_token)
        return Profile(resource)

    def __init__(self, data):
        self.id = data['id']
        self.site_id = data['siteId']
        self.user_id = data['userId']
        self.profile_name = data['profileName']
        self.visible = data['visible']
        self.style_id = data['styleId']
        self.item_count = data['itemCount']
        self.comment_count = data['commentCount']
        self.created = parse_timestamp(data['created'])
        self.last_active = parse_timestamp(data['lastActive'])
        self.gravatar = data['gravatar']
        self.banned = data['banned']
        self.admin = data['admin']
        # Profile meta contains links and permissions
        self.meta = Meta(data['meta'])

class Microcosm(APIResource):
    item_type = 'microcosm'
    resource_fragment = 'microcosms'

    @classmethod
    def retrieve(cls, host, id=None, offset=None, access_token=None):
        resource = super(Microcosm, cls).retrieve(host, id, offset, access_token)
        resource = cls.create_linkmap(resource)
        return APIResource.process_timestamp(resource)

class Conversation(APIResource):
    resource_fragment = 'conversations'

    @classmethod
    def retrieve(cls, host, id=None, offset=None, access_token=None):
        resource = super(Conversation, cls).retrieve(host, id, offset, access_token)
        resource = cls.create_linkmap(resource)
        return APIResource.process_timestamp(resource)

class Event(APIResource):
    resource_fragment = 'events'

    @classmethod
    def retrieve(cls, host, id=None, offset=None, access_token=None):
        resource = super(Event, cls).retrieve(host, id, offset, access_token)
        resource = cls.create_linkmap(resource)
        return APIResource.process_timestamp(resource)

    @classmethod
    def retrieve_attendees(cls, host, id, access_token=None):
        """
        Retrieve a list of attendees for an event.
        TODO: pagination support
        """

        resource_url = build_url(host, [cls.resource_fragment, id, 'attendees'])
        resource = APIResource.retrieve(host, id=id, access_token=access_token, url_override=resource_url)
        resource = cls.create_linkmap(resource)
        return APIResource.process_timestamp(resource)

    @classmethod
    def rsvp(cls, host, event_id, profile_id, attendance_data, access_token):
        """
        Create or update attendance to an event.
        TODO: This is obviously pretty nasty but it'll be changed soon.
        """

        collection_url = build_url(host, [cls.resource_fragment, event_id, 'attendees'])
        item_url = collection_url + '/' + str(profile_id)

        # See if there is an attendance entry for this profile
        try:
            response = requests.get(item_url, params={'access_token': access_token})
        except RequestException:
            raise

        # If it is not found, POST an attendance
        if response.status_code == 404:
            try:
                print 'Not found, posting to ' + collection_url
                post_response = requests.post(collection_url, attendance_data, params={'access_token': access_token})
            except RequestException:
                raise

            try:
                post_response.json()
            except ValueError:
                raise APIException('Invalid JSON returned')

            return

        # Attendance record exists, so update it with PUT
        elif response.status_code >= 200 and response.status_code < 400:

            try:
                print 'Found, putting to ' + item_url
                put_response = requests.post(
                    item_url,
                    data=attendance_data,
                    params={'method': 'PUT', 'access_token': access_token}
                )
            except RequestException:
                raise

            try:
                put_response.json()
            except ValueError:
                raise APIException('Invalid JSON returned')

            return

        else:
            raise APIException(response.content)

class Poll(APIResource):
    resource_fragment = 'polls'

    @classmethod
    def retrieve(cls, host, id=None, offset=None, access_token=None):
        resource = super(Poll, cls).retrieve(host, id, offset, access_token)
        resource = cls.create_linkmap(resource)
        return APIResource.process_timestamp(resource)

class Comment(APIResource):
    resource_fragment = 'comments'

    @classmethod
    def retrieve(cls, host, id=None, offset=None, access_token=None):
        resource = super(Comment, cls).retrieve(host, id, offset, access_token)
        resource = cls.create_linkmap(resource)
        return APIResource.process_timestamp(resource)

    @classmethod
    def create(cls, host, data, access_token):
        resource = super(Comment, cls).create(host, data, access_token)
        resource = cls.create_linkmap(resource)
        return resource

    @classmethod
    def update(cls, host, data, id, access_token):
        resource = super(Comment, cls).update(host, data, id, access_token)
        resource = cls.create_linkmap(resource)
        return resource

class GeoCode():
    """
    This is simply request proxying, so don't attempt formatting
    or error recovery.
    """

    @classmethod
    def retrieve(cls, host, q, access_token):
        """
        Forward a geocode request (q) to the API.
        """
        params = {'q': q}
        headers = {'Authorization': 'Bearer %s' % access_token}
        response = requests.get(build_url(host, ['geocode']), params=params, headers=headers)
        return response.content
<commit_msg>Implement constructors for Microcosms, Items, and meta types<commit_after>import json
from dateutil.parser import parse as parse_timestamp
import requests
from requests import RequestException
from microcosm.api.exceptions import APIException
from microweb.helpers import DateTimeEncoder
from microweb.helpers import build_url

# Item types that can have comments
COMMENTABLE_ITEM_TYPES = [
    'event',
    'conversation',
    'poll'
]

class APIResource(object):
    """
    Base API resource that performs HTTP operations. Each API class should subclass this
    to deal with custom validation and JSON processing.
    """

    @classmethod
    def retrieve(cls, host, id=None, offset=None, access_token=None, url_override=None):
        """
        GET an API resource. If resource ID is omitted, returns a list. Appends access_token
        and offset (for paging) if provided.
        """

        headers = {'Host': host}

        if url_override:
            resource_url = url_override
        else:
            path_fragments = [cls.resource_fragment]
            if id: path_fragments.append(id)
            resource_url = build_url(host, path_fragments)

        params = {}
        if access_token: params['access_token'] = access_token
        if offset: params['offset'] = offset

        response = requests.get(resource_url, params=params, headers=headers)

        try:
            resource = response.json()
        except ValueError:
            raise APIException('Response not valid json: %s' % response.content, 500)

        if resource['error']:
            raise APIException(resource['error'], response.status_code)

        if not resource['data']:
            raise APIException('No data returned at: %s' % resource_url)

        return resource['data']

    @classmethod
    def create(cls, host, data, access_token, headers=None):
        """
        Create an API resource with POST.
        """

        resource_url = build_url(host, [cls.resource_fragment])
        params = {'access_token': access_token}

        if headers:
            headers['Content-Type'] = 'application/json'
            headers['Host'] = host
        else:
            headers = {
                'Content-Type': 'application/json',
                'Host': host
            }

        response = requests.post(
            resource_url,
            data=json.dumps(data, cls=DateTimeEncoder),
            headers=headers,
            params=params
        )

        try:
            resource = response.json()
        except ValueError:
            raise APIException('Response not valid json: %s' % response.content, 500)

        if resource['error']:
            raise APIException(resource['error'], response.status_code)

        if not resource['data']:
            raise APIException('No data returned at: %s' % resource_url)

        return resource['data']

    @classmethod
    def update(cls, host, data, id, access_token):
        """
        Update an API resource with PUT.
        """

        resource_url = build_url(host, [cls.resource_fragment, id])

        headers = {
            'Content-Type': 'application/json',
            'Host': host,
        }
        params = {
            'method': 'PUT',
            'access_token': access_token,
        }

        response = requests.post(
            resource_url,
            data=json.dumps(data, cls=DateTimeEncoder),
            headers=headers,
            params=params
        )

        try:
            resource = response.json()
        except ValueError:
            raise APIException('The API has returned invalid json: %s' % response.content, 500)

        if resource['error']:
            raise APIException(resource['error'], response.status_code)

        if not resource['data']:
            raise APIException('No data returned at: %s' % resource_url)

        return resource['data']

    @classmethod
    def delete(cls, host, id, access_token):
        """
        DELETE an API resource. ID must be supplied.

        A 'data' object is never returned by a DELETE, so this
        method will raise an exception on failure. In normal
        operation the method simply returns.
        """

        path_fragments = [cls.resource_fragment]

        if id:
            path_fragments.append(id)
        elif access_token:
            path_fragments.append(access_token)
        else:
            raise AssertionError, 'You must supply either an id or '\
                                  'an access_token to delete'

        resource_url = build_url(host, path_fragments)
        params = {
            'method': 'DELETE',
            'access_token': access_token,
        }
        headers = {'Host': host}
        response = requests.post(resource_url, params=params, headers=headers)

        try:
            resource = response.json()
        except ValueError:
            raise APIException('The API has returned invalid json: %s' % response.content, 500)

        if resource['error']:
            raise APIException(resource['error'], response.status_code)

class Site(APIResource):
    item_type = 'site'
    resource_fragment = 'site'

    @classmethod
    def retrieve(cls, host):
        resource = super(Site, cls).retrieve(host)
        return Site(resource)

    def __init__(self, data):
        self.site_id = data['siteId']
        self.title = data['title']
        self.description = data['description']
        self.subdomain_key = data['subdomainKey']
        self.domain = data['domain']
        self.owned_by = Profile(data['ownedBy'])
        self.logo_url = data['logo_url']

class User(APIResource):
    item_type = 'user'
    resource_fragment = 'users'

    @classmethod
    def retrieve(cls, host, id, access_token):
        resource = super(User, cls).retrieve(host, id=id, access_token=access_token)
        return User(resource)

    # Currently only 'email is used on User objects
    def __init__(self, data):
        self.email_address = data['email']

class Authentication(APIResource):
    resource_fragment = 'auth'

class WhoAmI(APIResource):
    item_type = 'whoami'
    resource_fragment = 'whoami'

    @classmethod
    def retrieve(cls, host, access_token):
        resource = super(WhoAmI, cls).retrieve(host, access_token=access_token)
        return Profile(resource)

class Profile(APIResource):
    item_type = 'profile'
    resource_fragment = 'profiles'

    @classmethod
    def retrieve(cls, host, id, access_token=None):
        resource = super(Profile, cls).retrieve(host, id, access_token=access_token)
        return Profile(resource)

    def __init__(self, data, summary=True):
        self.id = data['id']
        self.site_id = data['siteId']
        self.user_id = data['userId']
        self.profile_name = data['profileName']
        self.visible = data['visible']
        self.gravatar = data['gravatar']
        self.meta = Meta(data['meta'])

        if not summary:
            self.style_id = data['styleId']
            self.item_count = data['itemCount']
            self.comment_count = data['commentCount']
            self.created = parse_timestamp(data['created'])
            self.last_active = parse_timestamp(data['lastActive'])
            self.banned = data['banned']
            self.admin = data['admin']

class Microcosm(APIResource):
    """
    Represents a single microcosm, containing items (conversations, events, ...)
    """

    resource_fragment = 'microcosms'

    @classmethod
    def retrieve(cls, host, id, offset=None, access_token=None):
        resource = super(Microcosm, cls).retrieve(host, id, offset, access_token)
        return Microcosm(resource, summary=False)

    def __init__(self, data, summary=True):
        self.id = data['id']
        self.site_id = data['siteId']
        self.visibility = data['visibility']
        self.title = data['title']
        self.description = data['description']
        self.moderators = data['moderators']
        self.meta = Meta(data['meta'])

        if summary:
            if data.has_key('mostRecentUpdate') \
            and data['mostRecentUpdate'] is not None:
                self.most_recent_update = Item(data['mostRecentUpdate'])
            self.total_items = data['totalItems']
            self.total_comments = data['totalComments']
        else:
            self.items = PaginatedList(data['items'], Item)

class MicrocosmList(APIResource):
    """
    Represents a list of microcosms for a given site.
    """

    resource_fragment = 'microcosms'

    @classmethod
    def retrieve(cls, host, offset=None, access_token=None):
        resource = super(MicrocosmList, cls).retrieve(host, offset=offset, access_token=access_token)
        return MicrocosmList(resource)

    def __init__(self, data):
        self.microcosms = PaginatedList(data['microcosms'], Microcosm)
        self.meta = Meta(data['meta'])

class Item():

    """
    Represents an item contained within a microcosm. Only used when
    fetching a single microcosm to represent the list of items
    contained within.
    """

    def __init__(self, data):
        self.id = data['id']
        self.item_type = data['itemType']
        self.microcosm_id = data['microcosmId']
        self.title = data['title']
        self.total_comments = data['totalComments']
        self.total_views = data['totalViews']
        self.last_comment_id = data['lastCommentId']
        self.last_comment_created_by = Profile(data['lastCommentCreatedBy'])
        self.last_comment_created = parse_timestamp(data['lastCommentCreated'])
        self.meta = Meta(data['meta'])

class PaginatedList():

    """
    Generic list of items and pagination metadata (total, number of pages, etc.).
    """

    def __init__(self, list, list_item_cls):
        self.total = list['total']
        self.limit = list['limit']
        self.offset = list['offset']
        self.max_offset = list['maxOffset']
        self.total_pages = list['totalPages']
        self.page = list['page']
        self.type = list['type']
        self.items = [list_item_cls(item) for item in list['items']]

class Meta():

    """
    Represents a resource 'meta' type, including creation time/user,
    flags, links, and permissions.
    """

    def __init__(self, data):
        if data.has_key('created'): self.created = (data['created'])
        if data.has_key('createdBy'): self.created_by = Profile(data['createdBy'])
        if data.has_key('edited'): self.created = (data['edited'])
        if data.has_key('editedBy'): self.created_by = Profile(data['editedBy'])
        if data.has_key('flags'): self.flags = data['flags']
        if data.has_key('links'): self.links = data['links']
        if data.has_key('permissions'): self.permissions = PermissionSet(data['permissions'])

class PermissionSet():

    """
    Represents user permissions on a resource.
    """

    def __init__(self, data):
        self.create = data['create']
        self.read = data['read']
        self.update = data['update']
        self.delete = data['delete']
        self.guest = data['guest']
        self.super_user = data['superUser']

class Conversation(APIResource):
    """
    Represents a conversation (title and list of comments).
    """

    resource_fragment = 'conversations'

    @classmethod
    def retrieve(cls, host, id=None, offset=None, access_token=None):
        resource = super(Conversation, cls).retrieve(host, id, offset, access_token)
        return APIResource.process_timestamp(resource)

    def __init__(self, data):
        self.id = data['id']
        self.microcosm_id = data['microcosmId']
        self.title = data['title']
        self.meta = Meta(data['meta'])
        self.comments = PaginatedList(data['comments'], None)

class Event(APIResource):
    """
    Represents an event (event details and list of comments).
    """

    resource_fragment = 'events'

    @classmethod
    def retrieve(cls, host, id=None, offset=None, access_token=None):
        resource = super(Event, cls).retrieve(host, id, offset, access_token)
        return APIResource.process_timestamp(resource)

    @classmethod
    def retrieve_attendees(cls, host, id, access_token=None):
        """
        Retrieve a list of attendees for an event.
        TODO: pagination support
        """

        resource_url = build_url(host, [cls.resource_fragment, id, 'attendees'])
        resource = APIResource.retrieve(host, id=id, access_token=access_token, url_override=resource_url)
        resource = cls.create_linkmap(resource)
        return APIResource.process_timestamp(resource)

    @classmethod
    def rsvp(cls, host, event_id, profile_id, attendance_data, access_token):
        """
        Create or update attendance to an event.
        TODO: This is obviously pretty nasty but it'll be changed soon.
        """

        collection_url = build_url(host, [cls.resource_fragment, event_id, 'attendees'])
        item_url = collection_url + '/' + str(profile_id)

        # See if there is an attendance entry for this profile
        try:
            response = requests.get(item_url, params={'access_token': access_token})
        except RequestException:
            raise

        # If it is not found, POST an attendance
        if response.status_code == 404:
            try:
                print 'Not found, posting to ' + collection_url
                post_response = requests.post(collection_url, attendance_data, params={'access_token': access_token})
            except RequestException:
                raise

            try:
                post_response.json()
            except ValueError:
                raise APIException('Invalid JSON returned')

            return

        # Attendance record exists, so update it with PUT
        elif response.status_code >= 200 and response.status_code < 400:

            try:
                print 'Found, putting to ' + item_url
                put_response = requests.post(
                    item_url,
                    data=attendance_data,
                    params={'method': 'PUT', 'access_token': access_token}
                )
            except RequestException:
                raise

            try:
                put_response.json()
            except ValueError:
                raise APIException('Invalid JSON returned')

            return

        else:
            raise APIException(response.content)

class Poll(APIResource):
    resource_fragment = 'polls'

    @classmethod
    def retrieve(cls, host, id=None, offset=None, access_token=None):
        resource = super(Poll, cls).retrieve(host, id, offset, access_token)
        resource = cls.create_linkmap(resource)
        return APIResource.process_timestamp(resource)

class Comment(APIResource):
    resource_fragment = 'comments'

    @classmethod
    def retrieve(cls, host, id=None, offset=None, access_token=None):
        resource = super(Comment, cls).retrieve(host, id, offset, access_token)
        resource = cls.create_linkmap(resource)
        return APIResource.process_timestamp(resource)

    @classmethod
    def create(cls, host, data, access_token):
        resource = super(Comment, cls).create(host, data, access_token)
        resource = cls.create_linkmap(resource)
        return resource

    @classmethod
    def update(cls, host, data, id, access_token):
        resource = super(Comment, cls).update(host, data, id, access_token)
        resource = cls.create_linkmap(resource)
        return resource

class GeoCode():
    """
    This is simply request proxying, so don't attempt formatting
    or error recovery.
    """

    @classmethod
    def retrieve(cls, host, q, access_token):
        """
        Forward a geocode request (q) to the API.
        """
        params = {'q': q}
        headers = {'Authorization': 'Bearer %s' % access_token}
        response = requests.get(build_url(host, ['geocode']), params=params, headers=headers)
        return response.content
<|endoftext|>


<commit_before># GUI Application automation and testing library
# Copyright (C) 2006-2017 Mark Mc Mahon and Contributors
# https://github.com/pywinauto/pywinauto/graphs/contributors
# http://pywinauto.readthedocs.io/en/latest/credits.html
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# * Neither the name of pywinauto nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""Implementation of the class to deal with an UI element (based on UI Automation API)"""

from comtypes import COMError
from six import integer_types

from .uia_defines import IUIA
from .uia_defines import get_elem_interface

from .handleprops import dumpwindow, controlid
from .element_info import ElementInfo
from .win32structures import RECT

def elements_from_uia_array(ptrs, cache_enable = False):
    """Build a list of UIAElementInfo elements from IUIAutomationElementArray"""
    return [UIAElementInfo(ptrs.GetElement(n), cache_enable) for n in range(ptrs.Length)]

class UIAElementInfo(ElementInfo):
    """UI element wrapper for IUIAutomation API"""

    def __init__(self, handle_or_elem = None, cache_enable = False):
        """
        Create an instance of UIAElementInfo from a handle (int or long)
        or from an IUIAutomationElement.

        If handle_or_elem is None create an instance for UI root element.
        """
        if handle_or_elem is not None:
            if isinstance(handle_or_elem, integer_types):
                # Create instane of UIAElementInfo from a handle
                self._element = IUIA().iuia.ElementFromHandle(handle_or_elem)
            elif isinstance(handle_or_elem, IUIA().ui_automation_client.IUIAutomationElement):
                self._element = handle_or_elem
            else:
                raise TypeError("UIAElementInfo object can be initialized " + \
                    "with integer or IUIAutomationElement instance only!")
        else:
            self._element = IUIA().root

        self.set_cache_strategy(cached = cache_enable)

    def _get_current_class_name(self):
        """Return an actual class name of the element"""
        try:
            return self._element.CurrentClassName
        except COMError:
            return None # probably element already doesn't exist

    def _get_cached_class_name(self):
        """Return a cached class name of the element"""
        if self._cached_class_name is None:
            self._cached_class_name = self._get_current_class_name()
        return self._cached_class_name

    def _get_current_handle(self):
        """Return an actual handle of the element"""
        try:
            return self._element.CurrentNativeWindowHandle
        except COMError:
            return None # probably element already doesn't exist

    def _get_cached_handle(self):
        """Return a cached handle of the element"""
        if self._cached_handle is None:
            self._cached_handle = self._get_current_handle()
        return self._cached_handle

    def _get_current_control_type(self):
        """Return an actual control type of the element"""
        try:
            return IUIA().known_control_type_ids[self._element.CurrentControlType]
        except COMError:
            return None # probably element already doesn't exist

    def _get_cached_control_type(self):
        """Return a cached control type of the element"""
        if self._cached_control_type is None:
            self._cached_control_type = self._get_current_control_type()
        return self._cached_control_type

    def _get_current_name(self):
        """Return an actual name of the element"""
        try:
            return self._element.CurrentName
        except COMError:
            return None # probably element already doesn't exist

    def _get_cached_name(self):
        """Return a cached name of the element"""
        if self._cached_name is None:
            self._cached_name = self._get_current_name()
        return self._cached_name

    def _get_current_visible(self):
        """Return an actual visible property of the element"""
        try:
            return bool(not self._element.CurrentIsOffscreen)
        except COMError:
            return False # probably element already doesn't exist

    def _get_cached_visible(self):
        """Return a cached visible property of the element"""
        if self._cached_visible is None:
            self._cached_visible = self._get_current_visible()
        return self._cached_visible

    def _get_current_rich_text(self):
        """Return the actual rich_text of the element"""
        if not self.class_name:
            return self.name
        try:
            pattern = get_elem_interface(self._element, "Text")
            return pattern.DocumentRange.GetText(-1)
        except Exception:
            return self.name # TODO: probably we should raise an exception here

    def _get_cached_rich_text(self):
        """Return the cached rich_text of the element"""
        if self._cached_rich_text is None:
            self._cached_rich_text = self._get_current_rich_text()
        return self._cached_rich_text

    def set_cache_strategy(self, cached = None):
        """Setup a cache strategy for frequently used attributes"""
        if cached is True:
            # Refresh cached attributes
            self._cached_class_name = None
            self._cached_handle = None
            self._cached_control_type = None
            self._cached_name = None
            self._cached_visible = None
            self._cached_rich_text = None

            # Switch to cached attributes
            self._get_class_name = self._get_cached_class_name
            self._get_handle = self._get_cached_handle
            self._get_control_type = self._get_cached_control_type
            self._get_name = self._get_cached_name
            self._get_visible = self._get_cached_visible
            self._get_rich_text = self._get_cached_rich_text
        else:
            # Switch to actual (non-cached) attributes
            self._get_class_name = self._get_current_class_name
            self._get_handle = self._get_current_handle
            self._get_control_type = self._get_current_control_type
            self._get_name = self._get_current_name
            self._get_visible = self._get_current_visible
            self._get_rich_text = self._get_current_rich_text

    @property
    def element(self):
        """Return AutomationElement's instance"""
        return self._element

    @property
    def automation_id(self):
        """Return AutomationId of the element"""
        try:
            return self._element.CurrentAutomationId
        except COMError:
            return None # probably element already doesn't exist

    @property
    def control_id(self):
        """Return ControlId of the element if it has a handle"""
        if (self.handle):
            return controlid(self.handle)
        else:
            return None

    @property
    def process_id(self):
        """Return ProcessId of the element"""
        try:
            return self._element.CurrentProcessId
        except COMError:
            return None # probably element already doesn't exist

    @property
    def framework_id(self):
        """Return FrameworkId of the element"""
        try:
            return self._element.CurrentFrameworkId
        except COMError:
            return None # probably element already doesn't exist

    @property
    def runtime_id(self):
        """Return Runtime ID (hashable value but may be different from run to run)"""
        return self._element.GetRuntimeId()

    @property
    def name(self):
        """Return name of the element"""
        return self._get_name()

    @property
    def class_name(self):
        """Return class name of the element"""
        return self._get_class_name()

    @property
    def control_type(self):
        """Return control type of element"""
        return self._get_control_type()

    @property
    def handle(self):
        """Return handle of the element"""
        return self._get_handle()

    @property
    def parent(self):
        """Return parent of the element"""
        parent_elem = IUIA().iuia.ControlViewWalker.GetParentElement(self._element)
        if parent_elem:
            return UIAElementInfo(parent_elem)
        else:
            return None

    def _get_elements(self, tree_scope, cond = IUIA().true_condition, cache_enable = False):
        """Find all elements according to the given tree scope and conditions"""
        ptrs_array = self._element.FindAll(tree_scope, cond)
        return elements_from_uia_array(ptrs_array, cache_enable)

    def children(self, **kwargs):
        """Return a list of only immediate children of the element

         * **kwargs** is a criteria to reduce a list by process,
           class_name, control_type, content_only and/or title.
        """
        cache_enable = kwargs.pop('cache_enable', False)
        cond = IUIA().build_condition(**kwargs)
        return self._get_elements(IUIA().tree_scope["children"], cond, cache_enable)

    def descendants(self, **kwargs):
        """Return a list of all descendant children of the element

         * **kwargs** is a criteria to reduce a list by process,
           class_name, control_type, content_only and/or title.
        """
        cache_enable = kwargs.pop('cache_enable', False)
        depth = kwargs.pop('depth', None)
        cond = IUIA().build_condition(**kwargs)
        elements = self._get_elements(IUIA().tree_scope["descendants"], cond, cache_enable)

        elements = ElementInfo.filter_with_depth(elements, self, depth)

        return elements

    @property
    def visible(self):
        """Check if the element is visible"""
        return self._get_visible()

    @property
    def enabled(self):
        """Check if the element is enabled"""
        return bool(self._element.CurrentIsEnabled)

    @property
    def rectangle(self):
        """Return rectangle of the element"""
        bound_rect = self._element.CurrentBoundingRectangle
        rect = RECT()
        rect.left = bound_rect.left
        rect.top = bound_rect.top
        rect.right = bound_rect.right
        rect.bottom = bound_rect.bottom
        return rect

    def dump_window(self):
        """Dump window to a set of properties"""
        return dumpwindow(self.handle)

    @property
    def rich_text(self):
        """Return rich_text of the element"""
        return self._get_rich_text()

    def __eq__(self, other):
        """Check if 2 UIAElementInfo objects describe 1 actual element"""
        if not isinstance(other, UIAElementInfo):
            return False;
        # We put the most frequent attibutes at the top of comparison as
        # quite often the element doesn't have all these attributes.
        # For example 'handle' exists only for top-level windows.
        # TODO: remove some of this properties
        return self.control_type == other.control_type and \
               self.class_name == other.class_name and \
               self.process_id == other.process_id and \
               self.handle == other.handle and \
               self.name == other.name and \
               self.automation_id == other.automation_id and \
               self.framework_id == other.framework_id and \
               self.rectangle == other.rectangle
<commit_msg>use iuia function to compare elements<commit_after># GUI Application automation and testing library
# Copyright (C) 2006-2017 Mark Mc Mahon and Contributors
# https://github.com/pywinauto/pywinauto/graphs/contributors
# http://pywinauto.readthedocs.io/en/latest/credits.html
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# * Neither the name of pywinauto nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""Implementation of the class to deal with an UI element (based on UI Automation API)"""

from comtypes import COMError
from six import integer_types

from .uia_defines import IUIA
from .uia_defines import get_elem_interface

from .handleprops import dumpwindow, controlid
from .element_info import ElementInfo
from .win32structures import RECT

def elements_from_uia_array(ptrs, cache_enable = False):
    """Build a list of UIAElementInfo elements from IUIAutomationElementArray"""
    return [UIAElementInfo(ptrs.GetElement(n), cache_enable) for n in range(ptrs.Length)]

class UIAElementInfo(ElementInfo):
    """UI element wrapper for IUIAutomation API"""

    def __init__(self, handle_or_elem = None, cache_enable = False):
        """
        Create an instance of UIAElementInfo from a handle (int or long)
        or from an IUIAutomationElement.

        If handle_or_elem is None create an instance for UI root element.
        """
        if handle_or_elem is not None:
            if isinstance(handle_or_elem, integer_types):
                # Create instane of UIAElementInfo from a handle
                self._element = IUIA().iuia.ElementFromHandle(handle_or_elem)
            elif isinstance(handle_or_elem, IUIA().ui_automation_client.IUIAutomationElement):
                self._element = handle_or_elem
            else:
                raise TypeError("UIAElementInfo object can be initialized " + \
                    "with integer or IUIAutomationElement instance only!")
        else:
            self._element = IUIA().root

        self.set_cache_strategy(cached = cache_enable)

    def _get_current_class_name(self):
        """Return an actual class name of the element"""
        try:
            return self._element.CurrentClassName
        except COMError:
            return None # probably element already doesn't exist

    def _get_cached_class_name(self):
        """Return a cached class name of the element"""
        if self._cached_class_name is None:
            self._cached_class_name = self._get_current_class_name()
        return self._cached_class_name

    def _get_current_handle(self):
        """Return an actual handle of the element"""
        try:
            return self._element.CurrentNativeWindowHandle
        except COMError:
            return None # probably element already doesn't exist

    def _get_cached_handle(self):
        """Return a cached handle of the element"""
        if self._cached_handle is None:
            self._cached_handle = self._get_current_handle()
        return self._cached_handle

    def _get_current_control_type(self):
        """Return an actual control type of the element"""
        try:
            return IUIA().known_control_type_ids[self._element.CurrentControlType]
        except COMError:
            return None # probably element already doesn't exist

    def _get_cached_control_type(self):
        """Return a cached control type of the element"""
        if self._cached_control_type is None:
            self._cached_control_type = self._get_current_control_type()
        return self._cached_control_type

    def _get_current_name(self):
        """Return an actual name of the element"""
        try:
            return self._element.CurrentName
        except COMError:
            return None # probably element already doesn't exist

    def _get_cached_name(self):
        """Return a cached name of the element"""
        if self._cached_name is None:
            self._cached_name = self._get_current_name()
        return self._cached_name

    def _get_current_visible(self):
        """Return an actual visible property of the element"""
        try:
            return bool(not self._element.CurrentIsOffscreen)
        except COMError:
            return False # probably element already doesn't exist

    def _get_cached_visible(self):
        """Return a cached visible property of the element"""
        if self._cached_visible is None:
            self._cached_visible = self._get_current_visible()
        return self._cached_visible

    def _get_current_rich_text(self):
        """Return the actual rich_text of the element"""
        if not self.class_name:
            return self.name
        try:
            pattern = get_elem_interface(self._element, "Text")
            return pattern.DocumentRange.GetText(-1)
        except Exception:
            return self.name # TODO: probably we should raise an exception here

    def _get_cached_rich_text(self):
        """Return the cached rich_text of the element"""
        if self._cached_rich_text is None:
            self._cached_rich_text = self._get_current_rich_text()
        return self._cached_rich_text

    def set_cache_strategy(self, cached = None):
        """Setup a cache strategy for frequently used attributes"""
        if cached is True:
            # Refresh cached attributes
            self._cached_class_name = None
            self._cached_handle = None
            self._cached_control_type = None
            self._cached_name = None
            self._cached_visible = None
            self._cached_rich_text = None

            # Switch to cached attributes
            self._get_class_name = self._get_cached_class_name
            self._get_handle = self._get_cached_handle
            self._get_control_type = self._get_cached_control_type
            self._get_name = self._get_cached_name
            self._get_visible = self._get_cached_visible
            self._get_rich_text = self._get_cached_rich_text
        else:
            # Switch to actual (non-cached) attributes
            self._get_class_name = self._get_current_class_name
            self._get_handle = self._get_current_handle
            self._get_control_type = self._get_current_control_type
            self._get_name = self._get_current_name
            self._get_visible = self._get_current_visible
            self._get_rich_text = self._get_current_rich_text

    @property
    def element(self):
        """Return AutomationElement's instance"""
        return self._element

    @property
    def automation_id(self):
        """Return AutomationId of the element"""
        try:
            return self._element.CurrentAutomationId
        except COMError:
            return None # probably element already doesn't exist

    @property
    def control_id(self):
        """Return ControlId of the element if it has a handle"""
        if (self.handle):
            return controlid(self.handle)
        else:
            return None

    @property
    def process_id(self):
        """Return ProcessId of the element"""
        try:
            return self._element.CurrentProcessId
        except COMError:
            return None # probably element already doesn't exist

    @property
    def framework_id(self):
        """Return FrameworkId of the element"""
        try:
            return self._element.CurrentFrameworkId
        except COMError:
            return None # probably element already doesn't exist

    @property
    def runtime_id(self):
        """Return Runtime ID (hashable value but may be different from run to run)"""
        return self._element.GetRuntimeId()

    @property
    def name(self):
        """Return name of the element"""
        return self._get_name()

    @property
    def class_name(self):
        """Return class name of the element"""
        return self._get_class_name()

    @property
    def control_type(self):
        """Return control type of element"""
        return self._get_control_type()

    @property
    def handle(self):
        """Return handle of the element"""
        return self._get_handle()

    @property
    def parent(self):
        """Return parent of the element"""
        parent_elem = IUIA().iuia.ControlViewWalker.GetParentElement(self._element)
        if parent_elem:
            return UIAElementInfo(parent_elem)
        else:
            return None

    def _get_elements(self, tree_scope, cond = IUIA().true_condition, cache_enable = False):
        """Find all elements according to the given tree scope and conditions"""
        ptrs_array = self._element.FindAll(tree_scope, cond)
        return elements_from_uia_array(ptrs_array, cache_enable)

    def children(self, **kwargs):
        """Return a list of only immediate children of the element

         * **kwargs** is a criteria to reduce a list by process,
           class_name, control_type, content_only and/or title.
        """
        cache_enable = kwargs.pop('cache_enable', False)
        cond = IUIA().build_condition(**kwargs)
        return self._get_elements(IUIA().tree_scope["children"], cond, cache_enable)

    def descendants(self, **kwargs):
        """Return a list of all descendant children of the element

         * **kwargs** is a criteria to reduce a list by process,
           class_name, control_type, content_only and/or title.
        """
        cache_enable = kwargs.pop('cache_enable', False)
        depth = kwargs.pop('depth', None)
        cond = IUIA().build_condition(**kwargs)
        elements = self._get_elements(IUIA().tree_scope["descendants"], cond, cache_enable)

        elements = ElementInfo.filter_with_depth(elements, self, depth)

        return elements

    @property
    def visible(self):
        """Check if the element is visible"""
        return self._get_visible()

    @property
    def enabled(self):
        """Check if the element is enabled"""
        return bool(self._element.CurrentIsEnabled)

    @property
    def rectangle(self):
        """Return rectangle of the element"""
        bound_rect = self._element.CurrentBoundingRectangle
        rect = RECT()
        rect.left = bound_rect.left
        rect.top = bound_rect.top
        rect.right = bound_rect.right
        rect.bottom = bound_rect.bottom
        return rect

    def dump_window(self):
        """Dump window to a set of properties"""
        return dumpwindow(self.handle)

    @property
    def rich_text(self):
        """Return rich_text of the element"""
        return self._get_rich_text()

    def __eq__(self, other):
        """Check if 2 UIAElementInfo objects describe 1 actual element"""
        if not isinstance(other, UIAElementInfo):
            return False
        return bool(IUIA().iuia.CompareElements(self.element, other.element))
<|endoftext|>


<commit_before>import torch
import torch.nn as nn
import torchvision.datasets as dsets
import torchvision.transforms as transforms

import qelos as q, numpy as np
from qelos.rnn import GRUCell, RecStack
from qelos.util import ticktock

tt = ticktock("script")

class RNNStack(nn.Module):
    def __init__(self, *layers):
        super(RNNStack, self).__init__()
        self.layers = nn.ModuleList(modules=list(layers))

    def forward(self, x, h0):
        y = x
        for i, layer in enumerate(self.layers):
            y, s = layer(y, h0[i].unsqueeze(0))
        return y, s

# RNN Model (Many-to-One)
class Encoder(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, mode="nn"):
        super(Encoder, self).__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.mode = mode
        if self.mode == "qrnn":
            tt.msg("using q.RNN")
            self.rnn = RecStack(*[GRUCell(input_size, hidden_size)] +
                                 [GRUCell(hidden_size, hidden_size) for i in range(num_layers - 1)]) \
                .to_layer().return_all()
        elif self.mode == "nn":
            tt.msg("using nn.RNN")
            self.rnn = nn.GRU(input_size, hidden_size, num_layers, batch_first=True)
        elif self.mode == "stack":
            self.rnn = RNNStack(
                *([nn.GRU(input_size, hidden_size, 1, batch_first=True)] +
                  [nn.GRU(hidden_size, hidden_size, 1, batch_first=True) for i in range(num_layers - 1)]
                  )
            )

    def forward(self, x):
        # Set initial states
        h0 = q.var(torch.zeros(self.num_layers, x.size(0), self.hidden_size)).cuda(crit=x).v
        # c0 = Variable(torch.zeros(self.num_layers, x.size(0), self.hidden_size))

        # Forward propagate RNN
        if self.mode == "qrnn":
            out = self.rnn(x)
        else:
            out, _ = self.rnn(x, h0)

        # Returns final state
        out = out[:, -1, :]
        return out

class ImgToSeq(nn.Module):
    def __init__(self, encoder, decoder):
        super(ImgToSeq, self).__init__()
        self.encoder = encoder
        self.decoder = decoder

    def forward(self, img, outseq):
        enc = self.encoder(img)
        dec = self.decoder(outseq, enc)
        return dec

class DecoderLoss(nn.Module):
    def __init__(self):
        super(DecoderLoss, self).__init__()
        self.elem_loss = nn.NLLLoss(ignore_index=0)

    def forward(self, logprobs, gold):
        """
        :param logprobs:    (batsize, seqlen, vocsize)
        :param gold:        (batsize, seqlen)
        :return:
        """
        acc = 0
        for i in range(logprobs.size(0)):
            acc += self.elem_loss(logprobs[i], gold[i])
        acc /= i
        return acc

def test_decoder_loss():
    l = DecoderLoss()
    logprobs = -np.random.random((3, 5, 4))
    gold = np.asarray([[1,2,3,0,0],[1,1,0,0,0],[3,3,3,3,3]])
    logprobs = q.var(torch.FloatTensor(logprobs)).v
    gold = q.var(torch.LongTensor(gold)).v
    loss = l(logprobs, gold)
    print loss

def number2charseq(x):
    dic = {0: "_zero  ",
           1: "_one   ",
           2: "_two   ",
           3: "_three ",
           4: "_four  ",
           5: "_five  ",
           6: "_six   ",
           7: "_seven ",
           8: "_eight ",
           9: "_nine  "}
    acc = []
    tocuda = False
    if x.is_cuda:
        x = x.cpu()
        tocuda = True
    for i in range(x.size(0)):
        word = x[i].data.numpy()[0]
        word = dic[word]
        word = map(lambda x: ord(x) if x is not " " else 0, word)
        acc.append(word)
    acc = np.asarray(acc)
    acc = q.var(torch.LongTensor(acc)).cuda(crit=tocuda).v
    return acc

def main(
    # Hyper Parameters
        sequence_length = 28,
        input_size = 28,
        hidden_size = 128,
        num_layers = 2,
        batch_size = 100,
        num_epochs = 2,
        learning_rate = 0.01,

        gpu = False,
        mode = "stack"     # "nn" or "qrnn" or "stack"
    ):
    tt.msg("using q: {}".format(mode))
    # MNIST Dataset
    train_dataset = dsets.MNIST(root='../../../data/mnist/',
                                train=True,
                                transform=transforms.ToTensor(),
                                download=True)

    test_dataset = dsets.MNIST(root='../../../data/mnist/',
                               train=False,
                               transform=transforms.ToTensor())

    # Data Loader (Input Pipeline)
    train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
                                               batch_size=batch_size,
                                               shuffle=True)

    test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
                                              batch_size=batch_size,
                                              shuffle=False)

    if gpu:
        q.var.all_cuda = True
    encoder = Encoder(input_size, hidden_size, num_layers, mode=mode)
    decoder = q.ContextDecoderCell(*[
        nn.Embedding(256, 20),
        q.GRUCell(20+hidden_size, 256),
        q.Forward(256, 256),
        q.LogSoftmax()
    ]).to_decoder()

    encdec = ImgToSeq(encoder, decoder)
    if gpu:
        encdec.cuda()

    # Loss and Optimizer
    criterion = nn.CrossEntropyLoss()
    criterion = DecoderLoss()
    if gpu:
        criterion.cuda()
    optimizer = torch.optim.Adadelta(encdec.parameters(), lr=learning_rate)

    tt.msg("training")
    # Train the Model
    for epoch in range(num_epochs):
        tt.tick()
        btt = ticktock("batch")
        btt.tick()
        for i, (images, labels) in enumerate(train_loader):
            #btt.tick("doing batch")
            images = q.var(images.view(-1, sequence_length, input_size)).cuda(crit=gpu).v
            labels = q.var(labels).cuda(crit=gpu).v
            tgt = number2charseq(labels)

            # Forward + Backward + Optimize
            optimizer.zero_grad()
            outputs = encdec(images, tgt[:, :-1])
            loss = criterion(outputs, tgt[:, 1:])
            loss.backward()
            optimizer.step()

            if (i+1) % 100 == 0:
                btt.tock("100 batches done")
                print ('Epoch [%d/%d], Step [%d/%d], Loss: %.4f'
                       %(epoch+1, num_epochs, i+1, len(train_dataset)//batch_size, loss.data[0]))
                btt.tick()
            #tt.tock("batch done")
        tt.tock("epoch {} done {}".format(epoch, loss.data[0]))
    # Test the Model
    correct = 0
    total = 0
    for images, labels in test_loader:
        images = q.var(images.view(-1, sequence_length, input_size)).cuda(crit=gpu).v
        labels = q.var(labels).cuda(crit=gpu).v
        tgt = number2charseq(labels)
        outputs = encdec(images, tgt[:, :-1])
        _, predicted = torch.max(outputs.data, 2)
        if tgt.is_cuda:
            tgt = tgt.cpu()
        if predicted.is_cuda:
            predicted = predicted.cpu()
        tgt = tgt[:, 1:].data.numpy()
        predicted = predicted.data.numpy()
        tgtmask = tgt != 0
        eq = predicted == tgtmask
        eq = eq | (tgtmask == False)
        eq = np.all(eq, axis=1)
        correct = eq.sum()
        total += labels.size(0)

    print('Test Accuracy of the model on the 10000 test images: %d %%' % (100 * correct / total))

    # Save the Model
    torch.save(encdec.state_dict(), 'rnn.pkl')

if __name__ == "__main__":
    #test_decoder_loss()
    q.argprun(main)<commit_msg>* mnist decoder training test<commit_after>import torch
import torch.nn as nn
import torchvision.datasets as dsets
import torchvision.transforms as transforms

import qelos as q, numpy as np
from qelos.rnn import GRUCell, RecStack
from qelos.util import ticktock

tt = ticktock("script")

class RNNStack(nn.Module):
    def __init__(self, *layers):
        super(RNNStack, self).__init__()
        self.layers = nn.ModuleList(modules=list(layers))

    def forward(self, x, h0):
        y = x
        for i, layer in enumerate(self.layers):
            y, s = layer(y, h0[i].unsqueeze(0))
        return y, s

# RNN Model (Many-to-One)
class Encoder(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, mode="nn"):
        super(Encoder, self).__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.mode = mode
        if self.mode == "qrnn":
            tt.msg("using q.RNN")
            self.rnn = RecStack(*[GRUCell(input_size, hidden_size)] +
                                 [GRUCell(hidden_size, hidden_size) for i in range(num_layers - 1)]) \
                .to_layer().return_all()
        elif self.mode == "nn":
            tt.msg("using nn.RNN")
            self.rnn = nn.GRU(input_size, hidden_size, num_layers, batch_first=True)
        elif self.mode == "stack":
            self.rnn = RNNStack(
                *([nn.GRU(input_size, hidden_size, 1, batch_first=True)] +
                  [nn.GRU(hidden_size, hidden_size, 1, batch_first=True) for i in range(num_layers - 1)]
                  )
            )

    def forward(self, x):
        # Set initial states
        h0 = q.var(torch.zeros(self.num_layers, x.size(0), self.hidden_size)).cuda(crit=x).v
        # c0 = Variable(torch.zeros(self.num_layers, x.size(0), self.hidden_size))

        # Forward propagate RNN
        if self.mode == "qrnn":
            out = self.rnn(x)
        else:
            out, _ = self.rnn(x, h0)

        # Returns final state
        out = out[:, -1, :]
        return out

class ImgToSeq(nn.Module):
    def __init__(self, encoder, decoder):
        super(ImgToSeq, self).__init__()
        self.encoder = encoder
        self.decoder = decoder

    def forward(self, img, outseq):
        enc = self.encoder(img)
        dec = self.decoder(outseq, enc)
        return dec

class DecoderLoss(nn.Module):
    def __init__(self):
        super(DecoderLoss, self).__init__()
        self.elem_loss = nn.NLLLoss(ignore_index=0)

    def forward(self, logprobs, gold):
        """
        :param logprobs:    (batsize, seqlen, vocsize)
        :param gold:        (batsize, seqlen)
        :return:
        """
        acc = 0
        for i in range(logprobs.size(0)):
            acc += self.elem_loss(logprobs[i], gold[i])
        acc /= i
        return acc

def test_decoder_loss():
    l = DecoderLoss()
    logprobs = -np.random.random((3, 5, 4))
    gold = np.asarray([[1,2,3,0,0],[1,1,0,0,0],[3,3,3,3,3]])
    logprobs = q.var(torch.FloatTensor(logprobs)).v
    gold = q.var(torch.LongTensor(gold)).v
    loss = l(logprobs, gold)
    print loss

def number2charseq(x):
    dic = {0: "_zero  ",
           1: "_one   ",
           2: "_two   ",
           3: "_three ",
           4: "_four  ",
           5: "_five  ",
           6: "_six   ",
           7: "_seven ",
           8: "_eight ",
           9: "_nine  "}
    acc = []
    tocuda = False
    if x.is_cuda:
        x = x.cpu()
        tocuda = True
    for i in range(x.size(0)):
        word = x[i].data.numpy()[0]
        word = dic[word]
        word = map(lambda x: ord(x) if x is not " " else 0, word)
        acc.append(word)
    acc = np.asarray(acc)
    acc = q.var(torch.LongTensor(acc)).cuda(crit=tocuda).v
    return acc

def main(
    # Hyper Parameters
        sequence_length = 28,
        input_size = 28,
        hidden_size = 128,
        num_layers = 2,
        batch_size = 100,
        num_epochs = 2,
        learning_rate = 0.01,

        gpu = False,
        mode = "stack"     # "nn" or "qrnn" or "stack"
    ):
    tt.msg("using q: {}".format(mode))
    # MNIST Dataset
    train_dataset = dsets.MNIST(root='../../../data/mnist/',
                                train=True,
                                transform=transforms.ToTensor(),
                                download=True)

    test_dataset = dsets.MNIST(root='../../../data/mnist/',
                               train=False,
                               transform=transforms.ToTensor())

    # Data Loader (Input Pipeline)
    train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
                                               batch_size=batch_size,
                                               shuffle=True)

    test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
                                              batch_size=batch_size,
                                              shuffle=False)

    if gpu:
        q.var.all_cuda = True
    encoder = Encoder(input_size, hidden_size, num_layers, mode=mode)
    decoder = q.ContextDecoderCell(*[
        nn.Embedding(256, 20),
        q.GRUCell(20+hidden_size, 256),
        q.Forward(256, 256),
        q.LogSoftmax()
    ]).to_decoder()

    encdec = ImgToSeq(encoder, decoder)
    if gpu:
        encdec.cuda()

    # Loss and Optimizer
    criterion = nn.CrossEntropyLoss()
    criterion = DecoderLoss()
    if gpu:
        criterion.cuda()
    optimizer = torch.optim.Adadelta(encdec.parameters(), lr=learning_rate)

    tt.msg("training")
    # Train the Model
    for epoch in range(num_epochs):
        tt.tick()
        btt = ticktock("batch")
        btt.tick()
        for i, (images, labels) in enumerate(train_loader):
            #btt.tick("doing batch")
            images = q.var(images.view(-1, sequence_length, input_size)).cuda(crit=gpu).v
            labels = q.var(labels).cuda(crit=gpu).v
            tgt = number2charseq(labels)

            # Forward + Backward + Optimize
            optimizer.zero_grad()
            outputs = encdec(images, tgt[:, :-1])
            loss = criterion(outputs, tgt[:, 1:])
            loss.backward()
            optimizer.step()

            if (i+1) % 100 == 0:
                btt.tock("100 batches done")
                print ('Epoch [%d/%d], Step [%d/%d], Loss: %.4f'
                       %(epoch+1, num_epochs, i+1, len(train_dataset)//batch_size, loss.data[0]))
                btt.tick()
            #tt.tock("batch done")
        tt.tock("epoch {} done {}".format(epoch, loss.data[0]))
    # Test the Model
    correct = 0
    total = 0
    for images, labels in test_loader:
        images = q.var(images.view(-1, sequence_length, input_size)).cuda(crit=gpu).v
        labels = q.var(labels).cuda(crit=gpu).v
        tgt = number2charseq(labels)
        outputs = encdec(images, tgt[:, :-1])
        _, predicted = torch.max(outputs.data, 2)
        if tgt.is_cuda:
            tgt = tgt.cpu()
        if predicted.is_cuda:
            predicted = predicted.cpu()
        tgt = tgt[:, 1:].data.numpy()
        predicted = predicted.numpy()
        tgtmask = tgt != 0
        eq = predicted == tgtmask
        eq = eq | (tgtmask == False)
        eq = np.all(eq, axis=1)
        correct = eq.sum()
        total += labels.size(0)

    print('Test Accuracy of the model on the 10000 test images: %d %%' % (100 * correct / total))

    # Save the Model
    torch.save(encdec.state_dict(), 'rnn.pkl')

if __name__ == "__main__":
    #test_decoder_loss()
    q.argprun(main)<|endoftext|>


<commit_before># -*- coding: UTF-8 -*-
import datetime
import os.path
from django.conf import settings
from django.db import models

import tagging
from tagging.fields import TagField

class DeadlineManager(models.Manager):
    def valid_news(self):
        today = datetime.date.today()
        return self.all().filter(date__gte = today)

class Deadline(models.Model):
    """
    deadline per il pycon
    """
    date = models.DateField()

    objects = DeadlineManager()

    def __unicode__(self):
        return "deadline: %s" % (self.date, )

    class Meta:
        ordering = ['date']

    def isExpired(self):
       today = datetime.date.today()
       return today > self.date

class DeadlineContent(models.Model):
    """
    Testo, multilingua, di una deadline
    """
    deadline = models.ForeignKey(Deadline)
    language = models.CharField(max_length = 3)
    body = models.TextField()

from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

class MultilingualContent(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')
    language = models.CharField(max_length = 3)
    content = models.CharField(max_length = 20)
    body = models.TextField()

import urlparse
from django.core.files.storage import FileSystemStorage

# definisco uno storage custom perché non uso MEDIA_DIR per memorizzare la
# roba sotto stuff
fs_speaker = FileSystemStorage(
    location = os.path.join(settings.STUFF_DIR, 'speaker'),
    base_url = urlparse.urljoin(settings.MEDIA_URL, 'stuff/speaker/')
)

def _speaker_image_path(instance, filename):
    return instance.slug + os.path.splitext(filename)[1].lower()

class Speaker(models.Model):
    name = models.CharField('nome e cognome speaker', max_length = 100)
    slug = models.SlugField()
    homepage = models.URLField(verify_exists = False, blank = True)
    activity = models.CharField(max_length = 50, blank = True)
    industry = models.CharField(max_length = 50, blank = True)
    location = models.CharField(max_length = 100, blank = True)
    image = models.ImageField(upload_to = _speaker_image_path, blank = True, storage = fs_speaker)
    bios = generic.GenericRelation(MultilingualContent)

    class Meta:
        ordering = ['name']

    def __unicode__(self):
        return self.name

    @models.permalink
    def get_absolute_url(self):
        return ('conference-speaker', (), { 'slug': self.slug })

TALK_DURATION = (
    (30, '30 minuti'),
    (45, '45 minuti'),
    (60, '60 minuti'),
    (90, '90 minuti'),
)
TALK_LANGUAGES = (
    ('it', 'Italiano'),
    ('en', 'Inglese'),
)

fs_slides = FileSystemStorage(
    location = os.path.join(settings.STUFF_DIR, 'slides'),
    base_url = urlparse.urljoin(settings.MEDIA_URL, 'stuff/slides/')
)

def _talk_slides_path(instance, filename):
    return instance.slug + os.path.splitext(filename)[1].lower()

class Talk(models.Model):
    title = models.CharField('titolo del talk', max_length = 100)
    slug = models.SlugField()
    speaker = models.ForeignKey(Speaker)
    duration = models.IntegerField(choices = TALK_DURATION)
    language = models.CharField('lingua del talk', max_length = 3, choices = TALK_LANGUAGES)
    abstracts = generic.GenericRelation(MultilingualContent)
    slides = models.FileField(upload_to = _talk_slides_path, blank = True, storage = fs_slides)
    video = models.URLField(verify_exists = False, blank = True)

    def __unicode__(self):
        return self.title

    @models.permalink
    def get_absolute_url(self):
        return ('conference-talk', (), { 'slug': self.slug })

fs_logo = FileSystemStorage(
    location = os.path.join(settings.STUFF_DIR, 'sponsor'),
    base_url = urlparse.urljoin(settings.MEDIA_URL, 'stuff/sponsor/')
)

def _sponsor_logo_path(instance, filename):
    return instance.slug + os.path.splitext(filename)[1].lower()

class Sponsor(models.Model):
    """

    """
    sponsor = models.CharField(max_length = 100, help_text = 'nome dello sponsor')
    slug = models.SlugField()
    url = models.URLField(verify_exists = False, blank = True)
    logo = models.ImageField(
        upload_to = _sponsor_logo_path, blank = True, storage = fs_logo,
        help_text = 'Inserire un immagine raster sufficientemente grande da poter essere scalata al bisogno'
    )

    def __unicode__(self):
        return self.sponsor

class SponsorIncome(models.Model):
    sponsor = models.ForeignKey(Sponsor)
    conference = models.CharField(max_length = 20)
    income = models.PositiveIntegerField()
    tags = TagField()

class Schedule(models.Model):
    conference = models.CharField(help_text = 'nome della conferenza', max_length = 50)
    date = models.DateField()

class Track(models.Model):
    schedule = models.ForeignKey(Schedule)
    track = models.CharField('nome track', max_length = 20)
    title = models.TextField('titolo della track', help_text = 'HTML supportato')

    def __unicode__(self):
        return self.track

class Event(models.Model):
    """
    """
    schedule = models.ForeignKey(Schedule)
    talk = models.ForeignKey(Talk, blank = True)
    custom = models.TextField(blank = True)
    start_time = models.TimeField()
    track = TagField(help_text = 'Inserire uno o più nomi di track, oppure "keynote"')
    sponsor = models.ForeignKey(Sponsor, blank = True)

    def __unicode__(self):
        if self.talk:
            return self.talk
        else:
            return self.custom

<commit_msg>refactoring creazione FileSystemStorage e sovrascrittura dei file presenti in stuff<commit_after># -*- coding: UTF-8 -*-
import datetime
import os.path
from django.conf import settings
from django.db import models

import tagging
from tagging.fields import TagField

class DeadlineManager(models.Manager):
    def valid_news(self):
        today = datetime.date.today()
        return self.all().filter(date__gte = today)

class Deadline(models.Model):
    """
    deadline per il pycon
    """
    date = models.DateField()

    objects = DeadlineManager()

    def __unicode__(self):
        return "deadline: %s" % (self.date, )

    class Meta:
        ordering = ['date']

    def isExpired(self):
       today = datetime.date.today()
       return today > self.date

class DeadlineContent(models.Model):
    """
    Testo, multilingua, di una deadline
    """
    deadline = models.ForeignKey(Deadline)
    language = models.CharField(max_length = 3)
    body = models.TextField()

from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

class MultilingualContent(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')
    language = models.CharField(max_length = 3)
    content = models.CharField(max_length = 20)
    body = models.TextField()

import urlparse
from django.core.files.storage import FileSystemStorage

# definisco uno storage custom perché non uso MEDIA_DIR per memorizzare la
# roba sotto stuff
fs_speaker = FileSystemStorage(
    location = os.path.join(settings.STUFF_DIR, 'speaker'),
    base_url = urlparse.urljoin(settings.MEDIA_URL, 'stuff/speaker/')
)

def _speaker_image_path(instance, filename):
    return instance.slug + os.path.splitext(filename)[1].lower()

class Speaker(models.Model):
    name = models.CharField('nome e cognome speaker', max_length = 100)
    slug = models.SlugField()
    homepage = models.URLField(verify_exists = False, blank = True)
    activity = models.CharField(max_length = 50, blank = True)
    industry = models.CharField(max_length = 50, blank = True)
    location = models.CharField(max_length = 100, blank = True)
    image = models.ImageField(upload_to = _speaker_image_path, blank = True, storage = fs_speaker)
    bios = generic.GenericRelation(MultilingualContent)

    class Meta:
        ordering = ['name']

    def __unicode__(self):
        return self.name

    @models.permalink
    def get_absolute_url(self):
        return ('conference-speaker', (), { 'slug': self.slug })

TALK_DURATION = (
    (30, '30 minuti'),
    (45, '45 minuti'),
    (60, '60 minuti'),
    (90, '90 minuti'),
)
TALK_LANGUAGES = (
    ('it', 'Italiano'),
    ('en', 'Inglese'),
)

fs_slides = FileSystemStorage(
    location = os.path.join(settings.STUFF_DIR, 'slides'),
    base_url = urlparse.urljoin(settings.MEDIA_URL, 'stuff/slides/')
)

def _talk_slides_path(instance, filename):
    return instance.slug + os.path.splitext(filename)[1].lower()

class Talk(models.Model):
    title = models.CharField('titolo del talk', max_length = 100)
    slug = models.SlugField()
    speaker = models.ForeignKey(Speaker)
    duration = models.IntegerField(choices = TALK_DURATION)
    language = models.CharField('lingua del talk', max_length = 3, choices = TALK_LANGUAGES)
    abstracts = generic.GenericRelation(MultilingualContent)
    slides = models.FileField(upload_to = _talk_slides_path, blank = True, storage = fs_slides)
    video = models.URLField(verify_exists = False, blank = True)

    def __unicode__(self):
        return self.title

    @models.permalink
    def get_absolute_url(self):
        return ('conference-talk', (), { 'slug': self.slug })

def _build_fs_stuff(subdir):
    fs = FileSystemStorage(
        location = os.path.join(settings.STUFF_DIR, 'sponsor'),
        base_url = urlparse.urljoin(settings.MEDIA_URL, 'stuff/sponsor/')
    )

    def build_path(instance, filename):
        fname = instance.slug + os.path.splitext(filename)[1].lower()
        fs.delete(fname)
        return fname

    return fs, build_path

fs_sponsor_logo, _sponsor_logo_path = _build_fs_stuff('sponsor')

class Sponsor(models.Model):
    """

    """
    sponsor = models.CharField(max_length = 100, help_text = 'nome dello sponsor')
    slug = models.SlugField()
    url = models.URLField(verify_exists = False, blank = True)
    logo = models.ImageField(
        upload_to = _sponsor_logo_path, blank = True, storage = fs_sponsor_logo,
        help_text = 'Inserire un immagine raster sufficientemente grande da poter essere scalata al bisogno'
    )

    def __unicode__(self):
        return self.sponsor

class SponsorIncome(models.Model):
    sponsor = models.ForeignKey(Sponsor)
    conference = models.CharField(max_length = 20)
    income = models.PositiveIntegerField()
    tags = TagField()

class Schedule(models.Model):
    conference = models.CharField(help_text = 'nome della conferenza', max_length = 50)
    date = models.DateField()

class Track(models.Model):
    schedule = models.ForeignKey(Schedule)
    track = models.CharField('nome track', max_length = 20)
    title = models.TextField('titolo della track', help_text = 'HTML supportato')

    def __unicode__(self):
        return self.track

class Event(models.Model):
    """
    """
    schedule = models.ForeignKey(Schedule)
    talk = models.ForeignKey(Talk, blank = True)
    custom = models.TextField(blank = True)
    start_time = models.TimeField()
    track = TagField(help_text = 'Inserire uno o più nomi di track, oppure "keynote"')
    sponsor = models.ForeignKey(Sponsor, blank = True)

    def __unicode__(self):
        if self.talk:
            return self.talk
        else:
            return self.custom

<|endoftext|>


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

from openerp import models, fields, api
from pprint import pprint
import json
import sys
from datetime import datetime, date
from magento import MagentoAPI
import config

# http://stackoverflow.com/questions/1305532/convert-python-dict-to-object (last one)
class dict2obj(dict):
    def __init__(self, dict_):
        super(dict2obj, self).__init__(dict_)
        for key in self:
            item = self[key]
            if isinstance(item, list):
                for idx, it in enumerate(item):
                    if isinstance(it, dict):
                        item[idx] = dict2obj(it)
            elif isinstance(item, dict):
                self[key] = dict2obj(item)

    def __getattr__(self, key):
        return self[key]

    def __getstate__(self):
        return self.__dict__.copy()

    def __setstate__(self, state):
        self.__dict__.update(state)

# task to schedule
class magento_task(models.Model):
    _name = 'magento.task'

    @api.model
    def create_syncid_data(self, odoo_id, magento_id):
        syncid_data = {}
        syncid_data['model'] = 80 #res.partner model
        syncid_data['source'] = 1 #syncid magento source
        syncid_data['odoo_id'] = odoo_id
        syncid_data['source_id'] = magento_id
        res = self.env['syncid.reference'].create(syncid_data)

    @api.model
    def create_partner_address(self, data, partner_id):
        #method to create a delivery or invoice address given magento address data

        address_data = {}
        address_data['name'] = data['name'] + ' ' + data['lastname']
        address_data['street'] = data['street']
        address_data['city'] = data['city']
        address_data['zip'] = data['postcode']
        address_data['phone'] = data['telephone']
        address_data['email'] = data['email']
        address_data['active'] = True
        address_data['customer'] = False
        address_data['parent_id'] = partner_id
        if data['address_type'] == 'billing':
            address_data['type'] = 'invoice'
        elif data['address_type'] == 'shipping':
            address_data['type'] = 'delivery'

        res = self.env['res.partner'].create(address_data)

        #create syncid reference
        res_syncid = create_syncid_data(res, address_data['customer_address_id'])

        return res

    @api.model
    def create_partner(self, data):
        #method to create basic partner data
        #TODO: maybe add more accurate data in address
        address_data = {}
        address_data['name'] = data['customer_name'] + ' ' + data['customer_lastname']
        # address_data['street'] = data['street']
        # address_data['city'] = data['city']
        # address_data['zip'] = data['postcode']
        # address_data['phone'] = data['telephone']
        address_data['email'] = data['customer_email']
        address_data['active'] = True
        address_data['customer'] = True

        res = self.env['res.partner'].create(address_data)

        res_syncid = create_syncid_data(res, data['customer_id'])

        return res

    @api.model
    def sync_orders_from_magento(self):
        reload(sys)
        sys.setdefaultencoding("utf-8")

        # check config and do nothing if it's missing some parameter
        if not config.domain or \
           not config.port or \
           not config.user or \
           not config.key or \
           not config.protocol:
           return

        #testing
        print 'Fetching magento orders...'
        m = MagentoAPI(config.domain, config.port, config.user, config.key, proto=config.protocol)
        orders = m.sales_order.list({'created_at': {'from': date.today().strftime('%Y-%m-%d')}})

        for order in orders:
            print order
        #END testing

        S_IVA21S = self.env['account.tax'].search([('description', '=', 'S_IVA21S')])
        #first get de date range to check orders
        #TODO: today minus 10 days for safe check
        order_filter = {'created_at':{'from': date.today().strftime('%Y-%m-%d')}}

        #fetch a list of magent orders from date
        orders = m.sales_order.list(order_filter)

        #filter orders to process state in ['new', 'processing']
        m_orders_list = []
        for i in orders:
            if i['state'] in ['new', 'processing']:
                m_orders_list.append('MAG-'+i['increment_id'])

        #check which sale orders are allready imported in odoo
        orders_to_process = []
        for i in m_orders_list:
            o_saleorder = self.env['sale.order'].search([('name', '=', i)])
            if not o_saleorder:
                orders_to_process.append(i)

        #processing sale orders:
        for i in orders_to_process:
            #fetching order info
            order = m.sales_order.info({'increment_id': i[4:]})

            #checking partner, invoice address and shipping address
            #if not exist on odoo, create it!

            #TODO:partner
            m_customer_id = order['customer_id']
            syncid_customer = self.env['syncid.reference'].search(['source','=',1],['model','=',80],['source_id','=',m_customer_id])
            if syncid_customer:
                o_customer_id = syncid_customer[0].odoo_id
            else:
                o_customer_id = create_partner(order)

            #TODO:billing
            m_billing_address_id = order['billing_address_id']
            syncid_billing = self.env['syncid.reference'].search(['source','=',1],['model','=',80],['source_id','=',m_billing_address_id])
            if syncid_billing:
                o_billing_id = syncid_customer[0].odoo_id
            else:
                o_billing_id = create_partner_address(order['billing_address'], o_customer_id)

            #TODO:shipping
            m_shipping_addess_id = order['shipping_address_id']
            syncid_shipping = self.env['sync_d.reference'].search(['source','=',1],['model','=',80],['source_id','=',m_shipping_addess_id])
            if syncid_shipping:
                o_shipping_id = syncid_customer[0].odoo_id
            else:
                o_shipping_id = create_partner_address(order['shipping_address'], o_customer_id)

            #Create sale order:
            saleorder_data = {}
            saleorder_data['name'] = i
            saleorder_data['partner_id'] = o_customer_id
            saleorder_data['partner_invoice_id'] = o_billing_id
            saleorder_data['partner_shipping_id'] = o_shipping_id
            saleorder_data['date_order'] = datetime.strptime(order['created_at'], '%Y-%m-%d %H:%M:%S')
            #TODO: add payment_mode info to saleorder
            o_saleorder = self.env['sale.order'].create(saleorder_data)

            #Create sale order lines data:
            for line in order['items']:
                saleorder_line_data = {}
                saleorder_line_data['order_id'] = o_saleorder

                syncid_product = self.env['syncid.reference'].search(['source','=',1],['model','=',191],['source_id','=',line['product_id']])
                if syncid_product:
                    product = self.env['product.product'].search(['id', '=', syncid_product[0].id])
                    saleorder_line_data['product_id'] = product.id

                saleorder_line_data['name'] = line['name']
                saleorder_line_data['product_uom_qty'] = int(float(line['qty_ordered']))
                saleorder_line_data['price_unit'] =float(line['base_original_price'])
                saleorder_line_data['tax_id'] = [(6, 0, [S_IVA_21S.id])]
                o_saleorder_line = self.env['sale.order.line'].create(saleorder_line_data)

            #check cod_fee & shipment fee and add it as products
            if order['cod_fee']:
                saleorder_line_data = {}
                saleorder_line_data['order_id'] = o_saleorder
                saleorder_line_data['name'] = 'Contrarembolso'
                saleorder_line_data['product_id'] = 15413 #product 'gastos de envio'
                saleorder_line_data['product_uom_qty'] = 1
                saleorder_line_data['price_unit'] = float(order['cod_fee'])
                saleorder_line_data['tax_id'] = [(6, 0, [S_IVA_21S.id])]
                o_saleorder_line = self.env['sale.order.line'].create(saleorder_line_data)

            if order['shipping_ammount']:
                saleorder_line_data = {}
                saleorder_line_data['order_id'] = o_saleorder
                saleorder_line_data['name'] = 'Gastos de envio'
                saleorder_line_data['product_id'] = 15413 #product 'gastos de envio'
                saleorder_line_data['product_uom_qty'] = 1
                saleorder_line_data['price_unit'] = float(order['shipping_ammount'])
                saleorder_line_data['tax_id'] = [(6, 0, [S_IVA_21S.id])]
                o_saleorder_line = self.env['sale.order.line'].create(saleorder_line_data)
<commit_msg>+ fix logic and syntax errors and add a runable code<commit_after># -*- coding: utf-8 -*-

from openerp import models, fields, api
from pprint import pprint
import json
import sys
from datetime import datetime, date
from magento import MagentoAPI
import config

# http://stackoverflow.com/questions/1305532/convert-python-dict-to-object (last one)
class dict2obj(dict):
    def __init__(self, dict_):
        super(dict2obj, self).__init__(dict_)
        for key in self:
            item = self[key]
            if isinstance(item, list):
                for idx, it in enumerate(item):
                    if isinstance(it, dict):
                        item[idx] = dict2obj(it)
            elif isinstance(item, dict):
                self[key] = dict2obj(item)

    def __getattr__(self, key):
        return self[key]

    def __getstate__(self):
        return self.__dict__.copy()

    def __setstate__(self, state):
        self.__dict__.update(state)

# task to schedule
class magento_task(models.Model):
    _name = 'magento.task'

    @api.model
    def create_syncid_data(self, odoo_id, magento_id):
        syncid_data = {}
        syncid_data['model'] = 80 #res.partner model
        syncid_data['source'] = 1 #syncid magento source
        syncid_data['odoo_id'] = odoo_id
        syncid_data['source_id'] = magento_id
        res = self.env['syncid.reference'].create(syncid_data)

    @api.model
    def create_partner_address(self, data, partner_id):
        #method to create a delivery or invoice address given magento address data

        address_data = {}
        address_data['name'] = data['firstname'] + ' ' + data['lastname']
        address_data['street'] = data['street']
        address_data['city'] = data['city']
        address_data['zip'] = data['postcode']
        address_data['phone'] = data['telephone']
        address_data['email'] = data['email']
        address_data['active'] = True
        address_data['customer'] = False
        address_data['parent_id'] = partner_id
        if data['address_type'] == 'billing':
            address_data['type'] = 'invoice'
        elif data['address_type'] == 'shipping':
            address_data['type'] = 'delivery'

        res = self.env['res.partner'].create(address_data)

        #create syncid reference
        res_syncid = self.create_syncid_data(res, data['address_id'])

        return res

    @api.model
    def create_partner(self, data):
        #method to create basic partner data
        #TODO: maybe add more accurate data in address
        address_data = {}
        address_data['name'] = data['customer_firstname'] + ' ' + data['customer_lastname']
        # address_data['street'] = data['street']
        # address_data['city'] = data['city']
        # address_data['zip'] = data['postcode']
        # address_data['phone'] = data['telephone']
        address_data['email'] = data['customer_email']
        address_data['active'] = True
        address_data['customer'] = True

        res = self.env['res.partner'].create(address_data)

        res_syncid = self.create_syncid_data(res, data['customer_id'])

        return res

    @api.model
    def sync_orders_from_magento(self):
        reload(sys)
        sys.setdefaultencoding("utf-8")

        # check config and do nothing if it's missing some parameter
        if not config.domain or \
           not config.port or \
           not config.user or \
           not config.key or \
           not config.protocol:
           return

        #testing
        print 'Fetching magento orders...'
        m = MagentoAPI(config.domain, config.port, config.user, config.key, proto=config.protocol)
        # orders = m.sales_order.list({'created_at': {'from': date.today().strftime('%Y-%m-%d')}})

        # for order in orders:
        #     print order
        #END testing

        S_IVA_21S = self.env['account.tax'].search([('description', '=', 'S_IVA21S')])
        PRODUCT_UOM = self.env['product.uom'].search([('id','=',1)]).id

        #first get de date range to check orders
        #TODO: today minus 10 days for safe check
        order_filter = {'created_at':{'from': date.today().strftime('%Y-%m-%d')}}

        #fetch a list of magent orders from date
        orders = m.sales_order.list(order_filter)

        #filter orders to process state in ['new', 'processing']
        m_orders_list = []
        for i in orders:
            if i['state'] in ['new', 'processing']:
                m_orders_list.append('MAG-'+i['increment_id'])

        #check which sale orders are allready imported in odoo
        orders_to_process = []
        for i in m_orders_list:
            o_saleorder = self.env['sale.order'].search([('name', '=', i)])
            if not o_saleorder:
                orders_to_process.append(i)

        #processing sale orders:
        print 'Total orders to process', len(orders_to_process)

        for i in orders_to_process:
            print 'Processing...', i
            #fetching order info
            order = m.sales_order.info({'increment_id': i[4:]})

            #checking partner, invoice address and shipping address
            #if not exist on odoo, create it!

            #TODO:partner
            m_customer_id = order['customer_id']
            syncid_customer = self.env['syncid.reference'].search([('source','=',1),('model','=',80),('source_id','=',m_customer_id)])
            if syncid_customer:
                o_customer_id = syncid_customer[0].odoo_id
            else:
                o_customer_id = self.create_partner(order).id

            #TODO:billing
            m_billing_address_id = order['billing_address_id']
            syncid_billing = self.env['syncid.reference'].search([('source','=',1),('model','=',80),('source_id','=',m_billing_address_id)])
            if syncid_billing:
                o_billing_id = syncid_customer[0].odoo_id
            else:
                o_billing_id = self.create_partner_address(order['billing_address'], o_customer_id).id

            #TODO:shipping
            m_shipping_addess_id = order['shipping_address_id']
            syncid_shipping = self.env['syncid.reference'].search([('source','=',1),('model','=',80),('source_id','=',m_shipping_addess_id)])
            if syncid_shipping:
                o_shipping_id = syncid_customer[0].odoo_id
            else:
                o_shipping_id = self.create_partner_address(order['shipping_address'], o_customer_id).id

            #Create sale order:
            saleorder_data = {}
            saleorder_data['name'] = i
            saleorder_data['partner_id'] = o_customer_id
            saleorder_data['partner_invoice_id'] = o_billing_id
            saleorder_data['partner_shipping_id'] = o_shipping_id
            saleorder_data['date_order'] = datetime.strptime(order['created_at'], '%Y-%m-%d %H:%M:%S')
            #TODO: add payment_mode info to saleorder
            o_saleorder = self.env['sale.order'].create(saleorder_data)

            #Create sale order lines data:
            for line in order['items']:
                saleorder_line_data = {}
                saleorder_line_data['order_id'] = o_saleorder.id

                product = self.env['product.product'].search([('default_code', '=', line['sku'])])
                if product:
                    saleorder_line_data['product_id'] = product.id
                else:
                    saleorder_line_data['product_id'] = 15414 #sync-error product

                saleorder_line_data['name'] = line['name']
                saleorder_line_data['product_uom'] = PRODUCT_UOM
                saleorder_line_data['product_uom_qty'] = int(float(line['qty_ordered']))
                if line['base_original_price']:
                    saleorder_line_data['price_unit'] = float(line['base_original_price'])
                else:
                    saleorder_line_data['price_unit'] = 0
                saleorder_line_data['tax_id'] = [(6, 0, [S_IVA_21S.id])]
                o_saleorder_line = self.env['sale.order.line'].create(saleorder_line_data)

            #check cod_fee & shipment fee and add it as products
            if order['cod_fee']:
                saleorder_line_data = {}
                saleorder_line_data['order_id'] = o_saleorder.id
                saleorder_line_data['name'] = 'Contrarembolso'
                saleorder_line_data['product_uom'] = PRODUCT_UOM
                saleorder_line_data['product_id'] = 15413 #product 'gastos de envio'
                saleorder_line_data['product_uom_qty'] = 1
                saleorder_line_data['price_unit'] = float(order['cod_fee'])
                saleorder_line_data['tax_id'] = [(6, 0, [S_IVA_21S.id])]
                o_saleorder_line = self.env['sale.order.line'].create(saleorder_line_data)

            if order['shipping_amount']:
                saleorder_line_data = {}
                saleorder_line_data['order_id'] = o_saleorder.id
                saleorder_line_data['product_uom'] = PRODUCT_UOM
                saleorder_line_data['name'] = 'Gastos de envio'
                saleorder_line_data['product_id'] = 15413 #product 'gastos de envio'
                saleorder_line_data['product_uom_qty'] = 1
                saleorder_line_data['price_unit'] = float(order['shipping_amount'])
                saleorder_line_data['tax_id'] = [(6, 0, [S_IVA_21S.id])]
                o_saleorder_line = self.env['sale.order.line'].create(saleorder_line_data)
<|endoftext|>