<commit_before>import logging
from datetime import datetime
from bson import ObjectId, DBRef
import mongoengine as mongo
from mongoengine.base import TopLevelDocumentMetaclass as TLDMetaclass
import pymongo

import prf.exc
from prf.utils import dictset, split_strip, pager,\
                      to_dunders, process_fields, qs2dict
from prf.utils.qs import prep_params
from prf.renderers import _JSONEncoder

log = logging.getLogger(__name__)

class TopLevelDocumentMetaclass(TLDMetaclass):

    def __new__(cls, name, bases, attrs):
        super_new = super(TopLevelDocumentMetaclass, cls)
        attrs_meta = dictset(attrs.get('meta', {}))

        new_klass = super_new.__new__(cls, name, bases, attrs)

        if attrs_meta.pop('enable_signals', False):
            for signal in mongo.signals.__all__:
                if hasattr(new_klass, signal):
                    method = getattr(new_klass, signal)
                    if callable(method):
                        getattr(mongo.signals, signal).connect(method, sender=new_klass)

        return new_klass

def get_document_cls(name, _raise=True):
    try:
        return mongo.document.get_document(name)
    except Exception as e:
        if _raise:
            raise dictset.DValueError('`%s` document does not exist' % name)

def drop_collections(name_prefix):
    db = mongo.connection.get_db()
    for name in db.collection_names():
        if name.startswith(name_prefix):
            log.warning('dropping `%s` collection' % name)
            db.drop_collection(name)

def includeme(config):
    mongo_connect(config.registry.settings)

    import pyramid
    config.add_tween('prf.mongodb.mongodb_exc_tween',
                      under='pyramid.tweens.excview_tween_factory')

Field2Default = {
    mongo.StringField : '',
    mongo.ListField : [],
    mongo.SortedListField : [],
    mongo.DictField : {},
    mongo.MapField : {},
}

def mongo_connect(settings):
    settings = dictset(settings)
    db = settings['mongodb.db']
    host = settings.get('mongodb.host', 'localhost')
    port = settings.asint('mongodb.port', default=27017)

    log.info('MongoDB enabled with db:%s, host:%s, port:%s', db, host, port)

    mongo.connect(db=db, host=host, port=port)

def mongodb_exc_tween(handler, registry):
    log.info('mongodb_exc_tween enabled')

    def tween(request):
        try:
            return handler(request)

        except mongo.NotUniqueError as e:
            if 'E11000' in e.message:
                raise prf.exc.HTTPConflict(detail='Resource already exists.',
                            request=request, exception=e)
            else:
                raise prf.exc.HTTPBadRequest('Not Unique', request=request)

        except (mongo.OperationError,
                mongo.ValidationError,
                mongo.InvalidQueryError,
                pymongo.errors.OperationFailure) as e:
            raise prf.exc.HTTPBadRequest(e, request=request, exception=e)

        except mongo.MultipleObjectsReturned:
            raise prf.exc.HTTPBadRequest('Bad or Insufficient Params',
                            request=request)
        except mongo.DoesNotExist as e:
            raise prf.exc.HTTPNotFound(request=request, exception=e)

    return tween

class MongoJSONEncoder(_JSONEncoder):

    def default(self, obj):
        if isinstance(obj, (ObjectId, DBRef)):
            return str(obj)

        return super(MongoJSONEncoder, self).default(obj)

class BaseMixin(object):

    Q = mongo.Q

    @classmethod
    def process_empty_op(cls, name, value):
        try:
            _field = getattr(cls, name)
            _default = Field2Default[type(_field)]
        except (KeyError, AttributeError) as e:
            raise prf.exc.HTTPBadRequest(
                'Can not use `empty` for field `%s`: dynamic field or unknown type' % (name, ))

        if int(value) == 0:
            return {'%s__ne' % name: _default}
        else:
            return {name: _default}

    @classmethod
    def get_frequencies(cls, queryset, specials):
        specials.asstr('_frequencies',  allow_missing=True)
        specials.asbool('_fq_normalize',  default=False)

        reverse = not bool(specials._sort and specials._sort[0].startswith('-'))
        for each in  sorted(
            queryset.item_frequencies(specials._frequencies,
            normalize=specials.asbool('_fq_normalize', default=False)
        ).items(),
        key=lambda x:x[1],
        reverse=reverse)[specials._start:specials._limit]:
            yield({each[0]:each[1]})

    @classmethod
    def get_distinct(cls, queryset, specials):
        reverse = False

        if specials.asbool('_count', False):
            return len(queryset.distinct(specials._distinct))

        if specials._sort:
            if len(specials._sort) > 1:
                raise prf.exc.HTTPBadRequest('Must sort only on distinct')

            _sort = specials._sort[0]
            if _sort.startswith('-'):
                reverse = True
                _sort = _sort[1:]

            if _sort != specials._distinct:
                raise prf.exc.HTTPBadRequest('Must sort only on distinct')

        dset = sorted(queryset.distinct(specials._distinct), reverse=reverse)

        if specials._end is None:
            return dset[specials._start:]
        else:
            return dset[specials._start: specials._end]

    @classmethod
    def get_group(cls, queryset, specials):
        aggr = []
        specials.aslist('_group', allow_missing=True)
        match_query = queryset._query

        accumulators = dictset([[e[7:],specials[e]] \
            for e in specials if e.startswith('_group_')])

        def undot(name):
            return name.replace('.', '__')

        def match(aggr):
            if match_query:
                aggr.append({'$match':match_query})
            return aggr

        def unwind(aggr):
            _prj = {"_id": "$_id"}
            unwinds = []

            for op, name in accumulators.copy().items():
                if op != 'unwind':
                    continue

                accumulators.pop(op)
                num_dots = name.count('.')
                if num_dots:
                    new_name = undot(name)
                    # accumulators[op] = new_name
                    _prj[new_name]='$%s' % name
                    for x in range(num_dots):
                        unwinds.append({'$unwind': '$%s' % new_name})
                else:
                    _prj[name]='$%s' % name
                    unwinds.append({'$unwind': '$%s' % name})

            if unwinds:
                aggr.append({'$project':_prj})
                aggr.extend(unwinds)

            return aggr

        def group(aggr):
            group_dict = {}

            for each in specials._group:
                group_dict[undot(each)] = '$%s' % each

            if group_dict:
                _d = {'_id': group_dict,
                      'count': {'$sum':1}}

                for op, val in accumulators.items():
                    _op = op.lower()
                    if _op in ['addtoset', 'set']:
                        sfx = 'set'
                        op = '$addToSet'
                    elif _op in ['push', 'list']:
                        sfx = 'list'
                        op = '$push'
                    else:
                        sfx = op
                        op = '$%s'%sfx

                    if val == '$ROOT':
                        _d[sfx] = {op:'$$ROOT'}
                        continue

                    _dd = {}

                    if sfx in ['set', 'list']:
                        for _v in split_strip(val):
                            _dd[undot(_v)] = '$%s' % _v
                    else:
                        _dd = '$%s' % val

                    _d[sfx] = {op:_dd}

                aggr.append({'$group':_d})

            return aggr

        def project(aggr):
            _prj = {'_id':0, 'count':1}
            for each in specials._group:
                _prj[each] = '$_id.%s' % undot(each)

            _gkeys = {}
            for each in aggr:
                if '$group' in each:
                    _gkeys = each['$group'].keys()

            for each in _gkeys:
                if each == '_id':
                    continue
                for _v in split_strip(each):
                    _prj[_v] = '$%s' % undot(_v)

            aggr.append(
                {'$project': _prj}
            )
            return aggr

        def sort(aggr):
            sort_dict = {}

            for each in specials._sort:
                if each[0] == '-':
                    sort_dict[each[1:]] = -1
                else:
                    sort_dict[each] = 1

            sort_dict = sort_dict or {'count': -1}
            aggr.append({'$sort':sort_dict})

            return aggr

        def limit(aggr):
            aggr.append({'$skip':specials._start})
            if specials._end is not None:
                aggr.append({'$limit':specials._end})

            return aggr

        def aggregate(aggr):
            log.debug(aggr)
            return cls._collection.aggregate(aggr, cursor={},
                                             allowDiskUse=True)

        if specials.asbool('_count', False):
            aggr = group(match(aggr))
            return len(list(aggregate(aggr)))

        aggr = limit(sort(project(group(unwind(match(aggr))))))

        if specials.asbool('_asdict', False):
            return dict([
                         [e[specials._group[0]],
                          e.get('list', e.get('set', [{}]))[0]]
                        for e in aggregate(aggr)])
        else:
            return [e for e in aggregate(aggr)]

    @classmethod
    def _ix(cls, specials, total):
        if specials._ix < 0:
            _ix = max(total + specials._ix, 0)
        else:
            _ix = min(specials._ix, total-1)

        specials._start = _ix
        specials._end = _ix + 1
        specials._limit = 1

    @classmethod
    def get_collection(cls, _q=None, **params):
        params = dictset(params)
        log.debug('cls: %s, params: %s', cls.__name__, params)

        params, specials = prep_params(params)

        query_set = cls.objects(_q)
        query_set = query_set(**params)
        _total = query_set.count()

        if specials._frequencies:
            return cls.get_frequencies(query_set, specials)

        elif specials._group:
            return cls.get_group(query_set, specials)

        elif specials._distinct:
            return cls.get_distinct(query_set, specials)

        if specials._count:
            return _total

        if specials._sort:
            query_set = query_set.order_by(*specials._sort)

        if specials._ix is not None:
            cls._ix(specials, _total)

        if specials._end is None:
            query_set = query_set[specials._start:]
        else:
            query_set = query_set[specials._start:specials._end]

        if specials._scalar:
            return query_set.scalar(*specials.aslist('_scalar'))

        if specials._fields:
            only, exclude = process_fields(specials._fields).mget(['only', 'exclude'])

            if only:
                query_set = query_set.only(*only)
            elif exclude:
                query_set = query_set.exclude(*exclude)

        query_set._total = _total
        log.debug('_query: %s', query_set._query)

        if specials._explain and isinstance(query_set, mongo.QuerySet):
            return query_set.explain()

        return query_set

    @classmethod
    def get_resource(cls, **params):
        obj = cls.get_collection(**params).first()
        if not obj:
            raise prf.exc.HTTPNotFound("'%s(%s)' resource not found" % (cls.__name__, params))
        return obj

    @classmethod
    def get(cls, **params):
        return cls.get_collection(**params).first()

    def unique_fields(self):
        return [e['fields'][0][0] for e in self._unique_with_indexes()] \
            + [self._meta['id_field']]

    @classmethod
    def get_or_create(cls, **params):
        defaults = params.pop('defaults', {})
        try:
            return (cls.objects.get(**params), False)
        except mongo.queryset.DoesNotExist:
            defaults.update(params)
            return (cls(**defaults).save(), True)

    def repr_parts(self):
        return []

    def __repr__(self):
        parts = ['%s:' % self.__class__.__name__]

        if hasattr(self, 'id'):
            parts.append('id=%s' % self.id)

        parts.extend(self.repr_parts())
        return '<%s>' % ', '.join(parts)

    @classmethod
    def get_by_ids(cls, ids, **params):
        return cls.get_collection(id__in=ids, _limit=len(ids), **params)

    @property
    def id_str(self):
        return str(self.id)

    def update_with(self, _dict, overwrite=True, flatten_first=False, reverse=False):
        self_dict = self.to_dict().update_with(_dict, overwrite=overwrite,
                                    flatten_first=flatten_first, reverse=reverse)

        for key, val in self_dict.unflat().items():
            setattr(self, key, val)

        return self

    def to_dict(self, fields=None):
        _d = dictset(self.to_mongo().to_dict())

        if '_id' in _d:
            _d['id']=_d.pop('_id')

        if fields:
            _d = dictset(_d).extract(fields)

        return _d

    @classmethod
    def delete_if_exists(cls, **params):
        obj = cls.get(**params)
        if obj:
            obj.delete()

    @classmethod
    def _(cls, ix=0):
        return cls.objects[ix].to_dict()

    @classmethod
    def _count(cls):
        return cls.objects.count()

    @classmethod
    def to_dicts(cls, keyname, **params):

        def to_dict(_d, fields):
            if isinstance(_d, dict):
                return dictset(_d).subset(fields)
            else:
                return _d.to_dict(fields=fields)

        params = dictset(params)
        _fields = params.aslist('_fields', default=[])

        if len(_fields) == 1: #if one field, assign the value directly
            _d = dictset()
            for e in cls.get_collection(**params):
                _d[e[keyname]] = getattr(e, _fields[0])
            return _d
        else:
            return dictset([[e[keyname], to_dict(e, _fields)]
                        for e in cls.get_collection(**params)])

    @classmethod
    def to_distincts(cls, fields, reverse=False):
        _d = dictset()
        fields = split_strip(fields)
        for fld in fields:
            _d[fld] = sorted(cls.objects.distinct(fld), reverse=reverse)

        return _d

    @classmethod
    def get_collection_qs(cls, qs):
        return cls.get_collection(**qs2dict(qs))

    def contains(self, other, exclude=None):
        if not isinstance(other, dict):
            other = other.to_dict(exclude)
        return not other or self.to_dict(other.keys()) == other

    def save_safe(self):
        try:
            return self.save()
        except Exception as e:
            log.error('%s: %s' % (e, self.to_dict()))

    @classmethod
    def get_collection_paginated(cls, page_size, params=None):
        params = dictset(params or {})
        _start = int(params.pop('_start', 0))
        _limit = int(params.pop('_limit', -1))

        if _limit == -1:
            _limit = cls.get_collection(_limit=_limit, **params).count()

        pgr = pager(_start, page_size, _limit)

        for start, count in pgr():
            _params = params.copy().update({'_start':start, '_limit': count})
            yield cls.get_collection(**_params)

class Base(BaseMixin, mongo.Document):
    __metaclass__ = TopLevelDocumentMetaclass

    meta = {'abstract': True}

    def update(self, *arg, **kw):
        result = super(Base, self).update(*arg, **to_dunders(kw))
        return result

class DynamicBase(BaseMixin, mongo.DynamicDocument):
    __metaclass__ = TopLevelDocumentMetaclass

    meta = {'abstract': True}

    def update(self, *arg, **kw):
        result = super(DynamicBase, self).update(*arg, **to_dunders(kw))
        return result
<commit_msg>* fixed the passing of query object<commit_after>import logging
from datetime import datetime
from bson import ObjectId, DBRef
import mongoengine as mongo
from mongoengine.base import TopLevelDocumentMetaclass as TLDMetaclass
import pymongo

import prf.exc
from prf.utils import dictset, split_strip, pager,\
                      to_dunders, process_fields, qs2dict
from prf.utils.qs import prep_params
from prf.renderers import _JSONEncoder

log = logging.getLogger(__name__)

class TopLevelDocumentMetaclass(TLDMetaclass):

    def __new__(cls, name, bases, attrs):
        super_new = super(TopLevelDocumentMetaclass, cls)
        attrs_meta = dictset(attrs.get('meta', {}))

        new_klass = super_new.__new__(cls, name, bases, attrs)

        if attrs_meta.pop('enable_signals', False):
            for signal in mongo.signals.__all__:
                if hasattr(new_klass, signal):
                    method = getattr(new_klass, signal)
                    if callable(method):
                        getattr(mongo.signals, signal).connect(method, sender=new_klass)

        return new_klass

def get_document_cls(name, _raise=True):
    try:
        return mongo.document.get_document(name)
    except Exception as e:
        if _raise:
            raise dictset.DValueError('`%s` document does not exist' % name)

def drop_collections(name_prefix):
    db = mongo.connection.get_db()
    for name in db.collection_names():
        if name.startswith(name_prefix):
            log.warning('dropping `%s` collection' % name)
            db.drop_collection(name)

def includeme(config):
    mongo_connect(config.registry.settings)

    import pyramid
    config.add_tween('prf.mongodb.mongodb_exc_tween',
                      under='pyramid.tweens.excview_tween_factory')

Field2Default = {
    mongo.StringField : '',
    mongo.ListField : [],
    mongo.SortedListField : [],
    mongo.DictField : {},
    mongo.MapField : {},
}

def mongo_connect(settings):
    settings = dictset(settings)
    db = settings['mongodb.db']
    host = settings.get('mongodb.host', 'localhost')
    port = settings.asint('mongodb.port', default=27017)

    log.info('MongoDB enabled with db:%s, host:%s, port:%s', db, host, port)

    mongo.connect(db=db, host=host, port=port)

def mongodb_exc_tween(handler, registry):
    log.info('mongodb_exc_tween enabled')

    def tween(request):
        try:
            return handler(request)

        except mongo.NotUniqueError as e:
            if 'E11000' in e.message:
                raise prf.exc.HTTPConflict(detail='Resource already exists.',
                            request=request, exception=e)
            else:
                raise prf.exc.HTTPBadRequest('Not Unique', request=request)

        except (mongo.OperationError,
                mongo.ValidationError,
                mongo.InvalidQueryError,
                pymongo.errors.OperationFailure) as e:
            raise prf.exc.HTTPBadRequest(e, request=request, exception=e)

        except mongo.MultipleObjectsReturned:
            raise prf.exc.HTTPBadRequest('Bad or Insufficient Params',
                            request=request)
        except mongo.DoesNotExist as e:
            raise prf.exc.HTTPNotFound(request=request, exception=e)

    return tween

class MongoJSONEncoder(_JSONEncoder):

    def default(self, obj):
        if isinstance(obj, (ObjectId, DBRef)):
            return str(obj)

        return super(MongoJSONEncoder, self).default(obj)

class BaseMixin(object):

    Q = mongo.Q

    @classmethod
    def process_empty_op(cls, name, value):
        try:
            _field = getattr(cls, name)
            _default = Field2Default[type(_field)]
        except (KeyError, AttributeError) as e:
            raise prf.exc.HTTPBadRequest(
                'Can not use `empty` for field `%s`: dynamic field or unknown type' % (name, ))

        if int(value) == 0:
            return {'%s__ne' % name: _default}
        else:
            return {name: _default}

    @classmethod
    def get_frequencies(cls, queryset, specials):
        specials.asstr('_frequencies',  allow_missing=True)
        specials.asbool('_fq_normalize',  default=False)

        reverse = not bool(specials._sort and specials._sort[0].startswith('-'))
        for each in  sorted(
            queryset.item_frequencies(specials._frequencies,
            normalize=specials.asbool('_fq_normalize', default=False)
        ).items(),
        key=lambda x:x[1],
        reverse=reverse)[specials._start:specials._limit]:
            yield({each[0]:each[1]})

    @classmethod
    def get_distinct(cls, queryset, specials):
        reverse = False

        if specials.asbool('_count', False):
            return len(queryset.distinct(specials._distinct))

        if specials._sort:
            if len(specials._sort) > 1:
                raise prf.exc.HTTPBadRequest('Must sort only on distinct')

            _sort = specials._sort[0]
            if _sort.startswith('-'):
                reverse = True
                _sort = _sort[1:]

            if _sort != specials._distinct:
                raise prf.exc.HTTPBadRequest('Must sort only on distinct')

        dset = sorted(queryset.distinct(specials._distinct), reverse=reverse)

        if specials._end is None:
            return dset[specials._start:]
        else:
            return dset[specials._start: specials._end]

    @classmethod
    def get_group(cls, queryset, specials):
        aggr = []
        specials.aslist('_group', allow_missing=True)
        match_query = queryset._query

        accumulators = dictset([[e[7:],specials[e]] \
            for e in specials if e.startswith('_group_')])

        def undot(name):
            return name.replace('.', '__')

        def match(aggr):
            if match_query:
                aggr.append({'$match':match_query})
            return aggr

        def unwind(aggr):
            _prj = {"_id": "$_id"}
            unwinds = []

            for op, name in accumulators.copy().items():
                if op != 'unwind':
                    continue

                accumulators.pop(op)
                num_dots = name.count('.')
                if num_dots:
                    new_name = undot(name)
                    # accumulators[op] = new_name
                    _prj[new_name]='$%s' % name
                    for x in range(num_dots):
                        unwinds.append({'$unwind': '$%s' % new_name})
                else:
                    _prj[name]='$%s' % name
                    unwinds.append({'$unwind': '$%s' % name})

            if unwinds:
                aggr.append({'$project':_prj})
                aggr.extend(unwinds)

            return aggr

        def group(aggr):
            group_dict = {}

            for each in specials._group:
                group_dict[undot(each)] = '$%s' % each

            if group_dict:
                _d = {'_id': group_dict,
                      'count': {'$sum':1}}

                for op, val in accumulators.items():
                    _op = op.lower()
                    if _op in ['addtoset', 'set']:
                        sfx = 'set'
                        op = '$addToSet'
                    elif _op in ['push', 'list']:
                        sfx = 'list'
                        op = '$push'
                    else:
                        sfx = op
                        op = '$%s'%sfx

                    if val == '$ROOT':
                        _d[sfx] = {op:'$$ROOT'}
                        continue

                    _dd = {}

                    if sfx in ['set', 'list']:
                        for _v in split_strip(val):
                            _dd[undot(_v)] = '$%s' % _v
                    else:
                        _dd = '$%s' % val

                    _d[sfx] = {op:_dd}

                aggr.append({'$group':_d})

            return aggr

        def project(aggr):
            _prj = {'_id':0, 'count':1}
            for each in specials._group:
                _prj[each] = '$_id.%s' % undot(each)

            _gkeys = {}
            for each in aggr:
                if '$group' in each:
                    _gkeys = each['$group'].keys()

            for each in _gkeys:
                if each == '_id':
                    continue
                for _v in split_strip(each):
                    _prj[_v] = '$%s' % undot(_v)

            aggr.append(
                {'$project': _prj}
            )
            return aggr

        def sort(aggr):
            sort_dict = {}

            for each in specials._sort:
                if each[0] == '-':
                    sort_dict[each[1:]] = -1
                else:
                    sort_dict[each] = 1

            sort_dict = sort_dict or {'count': -1}
            aggr.append({'$sort':sort_dict})

            return aggr

        def limit(aggr):
            aggr.append({'$skip':specials._start})
            if specials._end is not None:
                aggr.append({'$limit':specials._end})

            return aggr

        def aggregate(aggr):
            log.debug(aggr)
            return cls._collection.aggregate(aggr, cursor={},
                                             allowDiskUse=True)

        if specials.asbool('_count', False):
            aggr = group(match(aggr))
            return len(list(aggregate(aggr)))

        aggr = limit(sort(project(group(unwind(match(aggr))))))

        if specials.asbool('_asdict', False):
            return dict([
                         [e[specials._group[0]],
                          e.get('list', e.get('set', [{}]))[0]]
                        for e in aggregate(aggr)])
        else:
            return [e for e in aggregate(aggr)]

    @classmethod
    def _ix(cls, specials, total):
        if specials._ix < 0:
            _ix = max(total + specials._ix, 0)
        else:
            _ix = min(specials._ix, total-1)

        specials._start = _ix
        specials._end = _ix + 1
        specials._limit = 1

    @classmethod
    def get_collection(cls, _q=None, **params):
        params = dictset(params)
        log.debug('cls: %s, params: %s', cls.__name__, params)

        params, specials = prep_params(params)

        if isinstance(_q, basestring):
            query_set = cls.objects
        elif _q: # needs better way to check if its a proper query object
            query_set = cls.objects(_q)

        query_set = query_set(**params)
        _total = query_set.count()

        if specials._frequencies:
            return cls.get_frequencies(query_set, specials)

        elif specials._group:
            return cls.get_group(query_set, specials)

        elif specials._distinct:
            return cls.get_distinct(query_set, specials)

        if specials._count:
            return _total

        if specials._sort:
            query_set = query_set.order_by(*specials._sort)

        if specials._ix is not None:
            cls._ix(specials, _total)

        if specials._end is None:
            query_set = query_set[specials._start:]
        else:
            query_set = query_set[specials._start:specials._end]

        if specials._scalar:
            return query_set.scalar(*specials.aslist('_scalar'))

        if specials._fields:
            only, exclude = process_fields(specials._fields).mget(['only', 'exclude'])

            if only:
                query_set = query_set.only(*only)
            elif exclude:
                query_set = query_set.exclude(*exclude)

        query_set._total = _total
        log.debug('_query: %s', query_set._query)

        if specials._explain and isinstance(query_set, mongo.QuerySet):
            return query_set.explain()

        return query_set

    @classmethod
    def get_resource(cls, **params):
        obj = cls.get_collection(**params).first()
        if not obj:
            raise prf.exc.HTTPNotFound("'%s(%s)' resource not found" % (cls.__name__, params))
        return obj

    @classmethod
    def get(cls, **params):
        return cls.get_collection(**params).first()

    def unique_fields(self):
        return [e['fields'][0][0] for e in self._unique_with_indexes()] \
            + [self._meta['id_field']]

    @classmethod
    def get_or_create(cls, **params):
        defaults = params.pop('defaults', {})
        try:
            return (cls.objects.get(**params), False)
        except mongo.queryset.DoesNotExist:
            defaults.update(params)
            return (cls(**defaults).save(), True)

    def repr_parts(self):
        return []

    def __repr__(self):
        parts = ['%s:' % self.__class__.__name__]

        if hasattr(self, 'id'):
            parts.append('id=%s' % self.id)

        parts.extend(self.repr_parts())
        return '<%s>' % ', '.join(parts)

    @classmethod
    def get_by_ids(cls, ids, **params):
        return cls.get_collection(id__in=ids, _limit=len(ids), **params)

    @property
    def id_str(self):
        return str(self.id)

    def update_with(self, _dict, overwrite=True, flatten_first=False, reverse=False):
        self_dict = self.to_dict().update_with(_dict, overwrite=overwrite,
                                    flatten_first=flatten_first, reverse=reverse)

        for key, val in self_dict.unflat().items():
            setattr(self, key, val)

        return self

    def to_dict(self, fields=None):
        _d = dictset(self.to_mongo().to_dict())

        if '_id' in _d:
            _d['id']=_d.pop('_id')

        if fields:
            _d = dictset(_d).extract(fields)

        return _d

    @classmethod
    def delete_if_exists(cls, **params):
        obj = cls.get(**params)
        if obj:
            obj.delete()

    @classmethod
    def _(cls, ix=0):
        return cls.objects[ix].to_dict()

    @classmethod
    def _count(cls):
        return cls.objects.count()

    @classmethod
    def to_dicts(cls, keyname, **params):

        def to_dict(_d, fields):
            if isinstance(_d, dict):
                return dictset(_d).subset(fields)
            else:
                return _d.to_dict(fields=fields)

        params = dictset(params)
        _fields = params.aslist('_fields', default=[])

        if len(_fields) == 1: #if one field, assign the value directly
            _d = dictset()
            for e in cls.get_collection(**params):
                _d[e[keyname]] = getattr(e, _fields[0])
            return _d
        else:
            return dictset([[e[keyname], to_dict(e, _fields)]
                        for e in cls.get_collection(**params)])

    @classmethod
    def to_distincts(cls, fields, reverse=False):
        _d = dictset()
        fields = split_strip(fields)
        for fld in fields:
            _d[fld] = sorted(cls.objects.distinct(fld), reverse=reverse)

        return _d

    @classmethod
    def get_collection_qs(cls, qs):
        return cls.get_collection(**qs2dict(qs))

    def contains(self, other, exclude=None):
        if not isinstance(other, dict):
            other = other.to_dict(exclude)
        return not other or self.to_dict(other.keys()) == other

    def save_safe(self):
        try:
            return self.save()
        except Exception as e:
            log.error('%s: %s' % (e, self.to_dict()))

    @classmethod
    def get_collection_paginated(cls, page_size, params=None):
        params = dictset(params or {})
        _start = int(params.pop('_start', 0))
        _limit = int(params.pop('_limit', -1))

        if _limit == -1:
            _limit = cls.get_collection(_limit=_limit, **params).count()

        pgr = pager(_start, page_size, _limit)

        for start, count in pgr():
            _params = params.copy().update({'_start':start, '_limit': count})
            yield cls.get_collection(**_params)

class Base(BaseMixin, mongo.Document):
    __metaclass__ = TopLevelDocumentMetaclass

    meta = {'abstract': True}

    def update(self, *arg, **kw):
        result = super(Base, self).update(*arg, **to_dunders(kw))
        return result

class DynamicBase(BaseMixin, mongo.DynamicDocument):
    __metaclass__ = TopLevelDocumentMetaclass

    meta = {'abstract': True}

    def update(self, *arg, **kw):
        result = super(DynamicBase, self).update(*arg, **to_dunders(kw))
        return result
<|endoftext|>


<commit_before>
#
# spyne - Copyright (C) Spyne contributors.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
#

from __future__ import unicode_literals

import decimal
import uuid

from spyne.model.primitive import NATIVE_MAP
from spyne.util import six
from spyne.model._base import SimpleModel
from spyne.model.primitive._base import re_match_with_span

UUID_PATTERN = "%(x)s{8}-%(x)s{4}-%(x)s{4}-%(x)s{4}-%(x)s{12}" % \
                                                            {'x': '[a-fA-F0-9]'}

LTREE_PATTERN = r"\w+(\\.\w+)*"

# Actual ltree max size is 65536 but it's advised to keep it under 2048.
LTREE_OPTIMAL_SIZE = 2048

class Unicode(SimpleModel):
    """The type to represent human-readable data. Its native format is `unicode`
    or `str` with given encoding.
    """

    __type_name__ = 'string'
    Value = six.text_type

    class Attributes(SimpleModel.Attributes):
        """Customizable attributes of the :class:`spyne.model.primitive.Unicode`
        type."""

        min_len = 0
        """Minimum length of string. Can be set to any positive integer"""

        max_len = decimal.Decimal('inf')
        """Maximum length of string. Can be set to ``decimal.Decimal('inf')`` to
        accept strings of arbitrary length. You may also need to adjust
        :const:`spyne.server.wsgi.MAX_CONTENT_LENGTH`."""

        pattern = None
        """A regular expression that matches the whole string. See here for more
        info: http://www.regular-expressions.info/xml.html"""

        unicode_pattern = None
        """Same as ``pattern``, but, will be compiled with ``re.UNICODE``.
        See: https://docs.python.org/2/library/re.html#re.UNICODE"""

        encoding = None
        """The encoding of binary data this class may have to deal with."""

        unicode_errors = 'strict'
        """The argument to the ``unicode`` builtin; one of 'strict', 'replace'
        or 'ignore'."""

        format = None
        """A regular python string formatting string. See here:
        http://docs.python.org/library/stdtypes.html#string-formatting"""

        cast = None
        """Type override callable for casting non-unicode input to unicode."""

    def __new__(cls, *args, **kwargs):
        assert len(args) <= 1

        if len(args) == 1:
            kwargs['max_len'] = args[0]

        retval = SimpleModel.__new__(cls,  ** kwargs)

        return retval

    @staticmethod
    def is_default(cls):
        return (    SimpleModel.is_default(cls)
                and cls.Attributes.min_len == Unicode.Attributes.min_len
                and cls.Attributes.max_len == Unicode.Attributes.max_len
                and cls.Attributes.pattern == Unicode.Attributes.pattern
            )

    @staticmethod
    def validate_string(cls, value):
        return (     SimpleModel.validate_string(cls, value)
            and (value is None or (
                cls.Attributes.min_len <= len(value) <= cls.Attributes.max_len
            )))

    @staticmethod
    def validate_native(cls, value):
        return (SimpleModel.validate_native(cls, value)
            and (value is None or (
                re_match_with_span(cls.Attributes, value)
            )))

class String(Unicode):
    pass

if not six.PY2:
    String = Unicode

class AnyUri(Unicode):
    """A special kind of String type designed to hold an uri."""

    __type_name__ = 'anyURI'

    class Attributes(String.Attributes):
        text = None
        """The text shown in link."""

        anchor_class = None
        """The class of the generated <a> tag."""

    class Value(object):
        """A special object that is just a better way of carrying the
        information carried with a link.

        :param href: The uri string.
        :param text: The text data that goes with the link. This is a
            ``str`` or a ``unicode`` instance.
        :param content: The structured data that goes with the link. This is an
            `lxml.etree.Element` instance.
        """

        def __init__(self, href, text=None, content=None):
            self.href = href
            self.text = text
            self.content = content

        def __repr__(self):
            return "Uri(href={0!r}, text={1!r}, content={2!r})" \
                                     .format(self.href, self.text, self.content)

class ImageUri(AnyUri):
    """A special kind of String that holds the uri of an image."""

def _uuid_validate_string(cls, value):
    return (     SimpleModel.validate_string(cls, value)
        and (value is None or (
            cls.Attributes.min_len <= len(value) <= cls.Attributes.max_len
            and re_match_with_span(cls.Attributes, value)
        )))

def _Tuuid_validate(key):
    from uuid import UUID

    def _uvalid(cls, v):
        try:
            UUID(**{key:v})
        except ValueError:
            return False
        return True
    return _uvalid

_uuid_validate = {
    None: _uuid_validate_string,
    'hex': _Tuuid_validate('hex'),
    'urn': _Tuuid_validate('urn'),
    six.binary_type: _Tuuid_validate('bytes'),
    'bytes': _Tuuid_validate('bytes'),
    'bytes_le': _Tuuid_validate('bytes_le'),
    'fields': _Tuuid_validate('fields'),
    int: _Tuuid_validate('int'),
    'int': _Tuuid_validate('int'),
}

class Uuid(Unicode(pattern=UUID_PATTERN)):
    """Unicode subclass for Universially-Unique Identifiers."""

    __namespace__ = 'http://spyne.io/schema'
    __type_name__ = 'uuid'
    Value = uuid.UUID

    class Attributes(Unicode(pattern=UUID_PATTERN).Attributes):
        serialize_as = None

    @staticmethod
    def validate_string(cls, value):
        return _uuid_validate[cls.Attributes.serialize_as](cls, value)

    @staticmethod
    def validate_native(cls, value):
        return SimpleModel.validate_native(cls, value)

class Ltree(Unicode(LTREE_OPTIMAL_SIZE, unicode_pattern=LTREE_PATTERN)):
    """A special kind of String type designed to hold the Ltree type from
    Postgresql."""

    __namespace__ = 'http://spyne.io/schema'
    __type_name__ = 'ltreeString'

if not six.PY2:
    NATIVE_MAP.update({
        str: Unicode,
    })

else:
    NATIVE_MAP.update({
        str: String,
        unicode: Unicode,
    })
<commit_msg>fix typo<commit_after>
#
# spyne - Copyright (C) Spyne contributors.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
#

from __future__ import unicode_literals

import decimal
import uuid

from spyne.model.primitive import NATIVE_MAP
from spyne.util import six
from spyne.model._base import SimpleModel
from spyne.model.primitive._base import re_match_with_span

UUID_PATTERN = "%(x)s{8}-%(x)s{4}-%(x)s{4}-%(x)s{4}-%(x)s{12}" % \
                                                            {'x': '[a-fA-F0-9]'}

LTREE_PATTERN = r"\w+(\.\w+)*"

# Actual ltree max size is 65536 but it's advised to keep it under 2048.
LTREE_OPTIMAL_SIZE = 2048

class Unicode(SimpleModel):
    """The type to represent human-readable data. Its native format is `unicode`
    or `str` with given encoding.
    """

    __type_name__ = 'string'
    Value = six.text_type

    class Attributes(SimpleModel.Attributes):
        """Customizable attributes of the :class:`spyne.model.primitive.Unicode`
        type."""

        min_len = 0
        """Minimum length of string. Can be set to any positive integer"""

        max_len = decimal.Decimal('inf')
        """Maximum length of string. Can be set to ``decimal.Decimal('inf')`` to
        accept strings of arbitrary length. You may also need to adjust
        :const:`spyne.server.wsgi.MAX_CONTENT_LENGTH`."""

        pattern = None
        """A regular expression that matches the whole string. See here for more
        info: http://www.regular-expressions.info/xml.html"""

        unicode_pattern = None
        """Same as ``pattern``, but, will be compiled with ``re.UNICODE``.
        See: https://docs.python.org/2/library/re.html#re.UNICODE"""

        encoding = None
        """The encoding of binary data this class may have to deal with."""

        unicode_errors = 'strict'
        """The argument to the ``unicode`` builtin; one of 'strict', 'replace'
        or 'ignore'."""

        format = None
        """A regular python string formatting string. See here:
        http://docs.python.org/library/stdtypes.html#string-formatting"""

        cast = None
        """Type override callable for casting non-unicode input to unicode."""

    def __new__(cls, *args, **kwargs):
        assert len(args) <= 1

        if len(args) == 1:
            kwargs['max_len'] = args[0]

        retval = SimpleModel.__new__(cls,  ** kwargs)

        return retval

    @staticmethod
    def is_default(cls):
        return (    SimpleModel.is_default(cls)
                and cls.Attributes.min_len == Unicode.Attributes.min_len
                and cls.Attributes.max_len == Unicode.Attributes.max_len
                and cls.Attributes.pattern == Unicode.Attributes.pattern
            )

    @staticmethod
    def validate_string(cls, value):
        return (     SimpleModel.validate_string(cls, value)
            and (value is None or (
                cls.Attributes.min_len <= len(value) <= cls.Attributes.max_len
            )))

    @staticmethod
    def validate_native(cls, value):
        return (SimpleModel.validate_native(cls, value)
            and (value is None or (
                re_match_with_span(cls.Attributes, value)
            )))

class String(Unicode):
    pass

if not six.PY2:
    String = Unicode

class AnyUri(Unicode):
    """A special kind of String type designed to hold an uri."""

    __type_name__ = 'anyURI'

    class Attributes(String.Attributes):
        text = None
        """The text shown in link."""

        anchor_class = None
        """The class of the generated <a> tag."""

    class Value(object):
        """A special object that is just a better way of carrying the
        information carried with a link.

        :param href: The uri string.
        :param text: The text data that goes with the link. This is a
            ``str`` or a ``unicode`` instance.
        :param content: The structured data that goes with the link. This is an
            `lxml.etree.Element` instance.
        """

        def __init__(self, href, text=None, content=None):
            self.href = href
            self.text = text
            self.content = content

        def __repr__(self):
            return "Uri(href={0!r}, text={1!r}, content={2!r})" \
                                     .format(self.href, self.text, self.content)

class ImageUri(AnyUri):
    """A special kind of String that holds the uri of an image."""

def _uuid_validate_string(cls, value):
    return (     SimpleModel.validate_string(cls, value)
        and (value is None or (
            cls.Attributes.min_len <= len(value) <= cls.Attributes.max_len
            and re_match_with_span(cls.Attributes, value)
        )))

def _Tuuid_validate(key):
    from uuid import UUID

    def _uvalid(cls, v):
        try:
            UUID(**{key:v})
        except ValueError:
            return False
        return True
    return _uvalid

_uuid_validate = {
    None: _uuid_validate_string,
    'hex': _Tuuid_validate('hex'),
    'urn': _Tuuid_validate('urn'),
    six.binary_type: _Tuuid_validate('bytes'),
    'bytes': _Tuuid_validate('bytes'),
    'bytes_le': _Tuuid_validate('bytes_le'),
    'fields': _Tuuid_validate('fields'),
    int: _Tuuid_validate('int'),
    'int': _Tuuid_validate('int'),
}

class Uuid(Unicode(pattern=UUID_PATTERN)):
    """Unicode subclass for Universially-Unique Identifiers."""

    __namespace__ = 'http://spyne.io/schema'
    __type_name__ = 'uuid'
    Value = uuid.UUID

    class Attributes(Unicode(pattern=UUID_PATTERN).Attributes):
        serialize_as = None

    @staticmethod
    def validate_string(cls, value):
        return _uuid_validate[cls.Attributes.serialize_as](cls, value)

    @staticmethod
    def validate_native(cls, value):
        return SimpleModel.validate_native(cls, value)

class Ltree(Unicode(LTREE_OPTIMAL_SIZE, unicode_pattern=LTREE_PATTERN)):
    """A special kind of String type designed to hold the Ltree type from
    Postgresql."""

    __namespace__ = 'http://spyne.io/schema'
    __type_name__ = 'ltreeString'

if not six.PY2:
    NATIVE_MAP.update({
        str: Unicode,
    })

else:
    NATIVE_MAP.update({
        str: String,
        unicode: Unicode,
    })
<|endoftext|>


<commit_before>#!/usr/bin/env python
#
# spyne - Copyright (C) Spyne contributors.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
#

import unittest

from suds.client import Client
from suds import WebFault
from datetime import datetime

from spyne.test.interop._test_soap_client_base import SpyneClientTestBase

import logging
suds_logger = logging.getLogger('suds')
suds_logger.setLevel(logging.INFO)

class TestSuds(SpyneClientTestBase, unittest.TestCase):
    def setUp(self):
        SpyneClientTestBase.setUp(self, 'http')

        self.client = Client("http://localhost:9754/?wsdl", cache=None)
        self.ns = "spyne.test.interop.server"

    def test_echo_datetime(self):
        val = datetime.now()
        ret = self.client.service.echo_datetime(val)

        assert val == ret

    def test_echo_datetime_with_invalid_format(self):
        val = datetime.now()
        ret = self.client.service.echo_datetime_with_invalid_format(val)

        assert val == ret

    def test_echo_date(self):
        val = datetime.now().date()
        ret = self.client.service.echo_date(val)

        assert val == ret

    def test_echo_date_with_invalid_format(self):
        val = datetime.now().date()
        ret = self.client.service.echo_date_with_invalid_format(val)

        assert val == ret

    def test_echo_time(self):
        val = datetime.now().time()
        ret = self.client.service.echo_time(val)

        assert val == ret

    def test_echo_time_with_invalid_format(self):
        val = datetime.now().time()
        ret = self.client.service.echo_time_with_invalid_format(val)

        assert val == ret

    def test_echo_simple_boolean_array(self):
        val = [False, False, False, True]
        ret = self.client.service.echo_simple_boolean_array(val)

        assert val == ret

    def test_echo_boolean(self):
        val = True
        ret = self.client.service.echo_boolean(val)
        self.assertEquals(val, ret)

        val = False
        ret = self.client.service.echo_boolean(val)
        self.assertEquals(val, ret)

    def test_enum(self):
        DaysOfWeekEnum = self.client.factory.create("DaysOfWeekEnum")

        val = DaysOfWeekEnum.Monday
        ret = self.client.service.echo_enum(val)

        assert val == ret

    def test_validation(self):
        non_nillable_class = self.client.factory.create(
                                                "{hunk.sunk}NonNillableClass")
        non_nillable_class.i = 6
        non_nillable_class.s = None

        try:
            self.client.service.non_nillable(non_nillable_class)
        except WebFault, e:
            pass
        else:
            raise Exception("must fail")

    def test_echo_integer_array(self):
        ia = self.client.factory.create('integerArray')
        ia.integer.extend([1, 2, 3, 4, 5])
        self.client.service.echo_integer_array(ia)

    def test_echo_in_header(self):
        in_header = self.client.factory.create('InHeader')
        in_header.s = 'a'
        in_header.i = 3

        self.client.set_options(soapheaders=in_header)
        ret = self.client.service.echo_in_header()
        self.client.set_options(soapheaders=None)

        print(ret)

        self.assertEquals(in_header.s, ret.s)
        self.assertEquals(in_header.i, ret.i)

    def test_echo_in_complex_header(self):
        in_header = self.client.factory.create('InHeader')
        in_header.s = 'a'
        in_header.i = 3
        in_trace_header = self.client.factory.create('InTraceHeader')
        in_trace_header.client = 'suds'
        in_trace_header.callDate = datetime(year=2000, month=1, day=1, hour=0,
                                              minute=0, second=0, microsecond=0)

        self.client.set_options(soapheaders=(in_header, in_trace_header))
        ret = self.client.service.echo_in_complex_header()
        self.client.set_options(soapheaders=None)

        print(ret)

        self.assertEquals(in_header.s, ret[0].s)
        self.assertEquals(in_header.i, ret[0].i)
        self.assertEquals(in_trace_header.client, ret[1].client)
        self.assertEquals(in_trace_header.callDate, ret[1].callDate)

    def test_send_out_header(self):
        out_header = self.client.factory.create('OutHeader')
        out_header.dt = datetime(year=2000, month=1, day=1)
        out_header.f = 3.141592653

        ret = self.client.service.send_out_header()

        self.assertTrue(isinstance(ret, type(out_header)))
        self.assertEquals(ret.dt, out_header.dt)
        self.assertEquals(ret.f, out_header.f)

    def test_send_out_complex_header(self):
        out_header = self.client.factory.create('OutHeader')
        out_header.dt = datetime(year=2000, month=1, day=1)
        out_header.f = 3.141592653
        out_trace_header = self.client.factory.create('OutTraceHeader')
        out_trace_header.receiptDate = datetime(year=2000, month=1, day=1,
                                  hour=1, minute=1, second=1, microsecond=1)
        out_trace_header.returnDate = datetime(year=2000, month=1, day=1,
                                 hour=1, minute=1, second=1, microsecond=100)

        ret = self.client.service.send_out_complex_header()

        self.assertTrue(isinstance(ret[0], type(out_header)))
        self.assertEquals(ret[0].dt, out_header.dt)
        self.assertEquals(ret[0].f, out_header.f)
        self.assertTrue(isinstance(ret[1], type(out_trace_header)))
        self.assertEquals(ret[1].receiptDate, out_trace_header.receiptDate)
        self.assertEquals(ret[1].returnDate, out_trace_header.returnDate)
        # Control the reply soap header (in an unelegant way but this is the
        # only way with suds)
        soapheaders = self.client.last_received().getChild("Envelope").getChild("Header")
        soap_out_header = soapheaders.getChild('OutHeader')
        self.assertEquals('T'.join((out_header.dt.date().isoformat(),
                                    out_header.dt.time().isoformat())),
                          soap_out_header.getChild('dt').getText())
        self.assertEquals(unicode(out_header.f), soap_out_header.getChild('f').getText())
        soap_out_trace_header = soapheaders.getChild('OutTraceHeader')
        self.assertEquals('T'.join((out_trace_header.receiptDate.date().isoformat(),
                                    out_trace_header.receiptDate.time().isoformat())),
                          soap_out_trace_header.getChild('receiptDate').getText())
        self.assertEquals('T'.join((out_trace_header.returnDate.date().isoformat(),
                                    out_trace_header.returnDate.time().isoformat())),
                          soap_out_trace_header.getChild('returnDate').getText())

    def test_echo_string(self):
        test_string = "OK"
        ret = self.client.service.echo_string(test_string)

        self.assertEquals(ret, test_string)

    def __get_xml_test_val(self):
        return {
            "test_sub": {
                "test_subsub1": {
                    "test_subsubsub1" : ["subsubsub1 value"]
                },
                "test_subsub2": ["subsub2 value 1", "subsub2 value 2"],
                "test_subsub3": [
                    {
                        "test_subsub3sub1": ["subsub3sub1 value"]
                    },
                    {
                        "test_subsub3sub2": ["subsub3sub2 value"]
                    },
                ],
                "test_subsub4": [],
                "test_subsub5": ["x"],
            }
        }

    def test_echo_simple_class(self):
        val = self.client.factory.create("{spyne.test.interop.server}SimpleClass")

        val.i = 45
        val.s = "asd"

        ret = self.client.service.echo_simple_class(val)

        assert ret.i == val.i
        assert ret.s == val.s

    def test_echo_class_with_self_reference(self):
        val = self.client.factory.create("{spyne.test.interop.server}ClassWithSelfReference")

        val.i = 45
        val.sr = self.client.factory.create("{spyne.test.interop.server}ClassWithSelfReference")
        val.sr.i = 50
        val.sr.sr = None

        ret = self.client.service.echo_class_with_self_reference(val)

        assert ret.i == val.i
        assert ret.sr.i == val.sr.i

    def test_echo_nested_class(self):
        val = self.client.factory.create("{punk.tunk}NestedClass");

        val.i = 45
        val.s = "asd"
        val.f = 12.34
        val.ai = self.client.factory.create("integerArray")
        val.ai.integer.extend([1, 2, 3, 45, 5, 3, 2, 1, 4])

        val.simple = self.client.factory.create("{spyne.test.interop.server}SimpleClassArray")

        val.simple.SimpleClass.append(self.client.factory.create("{spyne.test.interop.server}SimpleClass"))
        val.simple.SimpleClass.append(self.client.factory.create("{spyne.test.interop.server}SimpleClass"))

        val.simple.SimpleClass[0].i = 45
        val.simple.SimpleClass[0].s = "asd"
        val.simple.SimpleClass[1].i = 12
        val.simple.SimpleClass[1].s = "qwe"

        val.other = self.client.factory.create("{spyne.test.interop.server}OtherClass");
        val.other.dt = datetime.now()
        val.other.d = 123.456
        val.other.b = True

        ret = self.client.service.echo_nested_class(val)

        self.assertEquals(ret.i, val.i)
        self.assertEqual(ret.ai[0], val.ai[0])
        self.assertEquals(ret.simple.SimpleClass[0].s, val.simple.SimpleClass[0].s)
        self.assertEqual(ret.other.dt, val.other.dt)

    def test_huge_number(self):
        self.assertEquals(self.client.service.huge_number(), 2**int(1e5))

    def test_long_string(self):
        self.assertEquals(self.client.service.long_string(), ('0123456789abcdef' * 16384))

    def test_long_string(self):
        self.client.service.test_empty()

    def test_echo_extension_class(self):
        val = self.client.factory.create("{bar}ExtensionClass")

        val.i = 45
        val.s = "asd"
        val.f = 12.34

        val.simple = self.client.factory.create("{spyne.test.interop.server}SimpleClassArray")

        val.simple.SimpleClass.append(self.client.factory.create("{spyne.test.interop.server}SimpleClass"))
        val.simple.SimpleClass.append(self.client.factory.create("{spyne.test.interop.server}SimpleClass"))

        val.simple.SimpleClass[0].i = 45
        val.simple.SimpleClass[0].s = "asd"
        val.simple.SimpleClass[1].i = 12
        val.simple.SimpleClass[1].s = "qwe"

        val.other = self.client.factory.create("{spyne.test.interop.server}OtherClass");
        val.other.dt = datetime.now()
        val.other.d = 123.456
        val.other.b = True

        val.p = self.client.factory.create("{hunk.sunk}NonNillableClass");
        val.p.dt = datetime(2010, 6, 2)
        val.p.i = 123
        val.p.s = "punk"

        val.l = datetime(2010, 7, 2)
        val.q = 5

        ret = self.client.service.echo_extension_class(val)
        print(ret)

        self.assertEquals(ret.i, val.i)
        self.assertEquals(ret.s, val.s)
        self.assertEquals(ret.f, val.f)
        self.assertEquals(ret.simple.SimpleClass[0].i, val.simple.SimpleClass[0].i)
        self.assertEquals(ret.other.dt, val.other.dt)
        self.assertEquals(ret.p.s, val.p.s)

    def test_python_exception(self):
        try:
            self.client.service.python_exception()
            raise Exception("must fail")
        except WebFault, e:
            pass

    def test_soap_exception(self):
        try:
            self.client.service.soap_exception()
            raise Exception("must fail")
        except WebFault, e:
            pass

    def test_complex_return(self):
        ret = self.client.service.complex_return()

        self.assertEquals(ret.resultCode, 1)
        self.assertEquals(ret.resultDescription, "Test")
        self.assertEquals(ret.transactionId, 123)
        self.assertEquals(ret.roles.RoleEnum[0], "MEMBER")

    def test_return_invalid_data(self):
        try:
            self.client.service.return_invalid_data()
            raise Exception("must fail")
        except:
            pass

    def test_custom_messages(self):
        ret = self.client.service.custom_messages("test")

        assert ret == 'test'

    def test_echo_simple_bare(self):
        ret = self.client.service.echo_simple_bare("test")

        assert ret == 'test'

    def test_echo_complex_bare(self):
        val = ['abc','def']
        ia = self.client.factory.create('stringArray')
        ia.string.extend(val)
        ret = self.client.service.echo_complex_bare(ia)

        assert ret == val

if __name__ == '__main__':
    unittest.main()
<commit_msg>disable test_echo_complex_bare in suds interop tests because suds creates an invalid request here.<commit_after>#!/usr/bin/env python
#
# spyne - Copyright (C) Spyne contributors.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
#

import unittest

from suds.client import Client
from suds import WebFault
from datetime import datetime

from spyne.test.interop._test_soap_client_base import SpyneClientTestBase

import logging
suds_logger = logging.getLogger('suds')
suds_logger.setLevel(logging.INFO)

class TestSuds(SpyneClientTestBase, unittest.TestCase):
    def setUp(self):
        SpyneClientTestBase.setUp(self, 'http')

        self.client = Client("http://localhost:9754/?wsdl", cache=None)
        self.ns = "spyne.test.interop.server"

    def test_echo_datetime(self):
        val = datetime.now()
        ret = self.client.service.echo_datetime(val)

        assert val == ret

    def test_echo_datetime_with_invalid_format(self):
        val = datetime.now()
        ret = self.client.service.echo_datetime_with_invalid_format(val)

        assert val == ret

    def test_echo_date(self):
        val = datetime.now().date()
        ret = self.client.service.echo_date(val)

        assert val == ret

    def test_echo_date_with_invalid_format(self):
        val = datetime.now().date()
        ret = self.client.service.echo_date_with_invalid_format(val)

        assert val == ret

    def test_echo_time(self):
        val = datetime.now().time()
        ret = self.client.service.echo_time(val)

        assert val == ret

    def test_echo_time_with_invalid_format(self):
        val = datetime.now().time()
        ret = self.client.service.echo_time_with_invalid_format(val)

        assert val == ret

    def test_echo_simple_boolean_array(self):
        val = [False, False, False, True]
        ret = self.client.service.echo_simple_boolean_array(val)

        assert val == ret

    def test_echo_boolean(self):
        val = True
        ret = self.client.service.echo_boolean(val)
        self.assertEquals(val, ret)

        val = False
        ret = self.client.service.echo_boolean(val)
        self.assertEquals(val, ret)

    def test_enum(self):
        DaysOfWeekEnum = self.client.factory.create("DaysOfWeekEnum")

        val = DaysOfWeekEnum.Monday
        ret = self.client.service.echo_enum(val)

        assert val == ret

    def test_validation(self):
        non_nillable_class = self.client.factory.create(
                                                "{hunk.sunk}NonNillableClass")
        non_nillable_class.i = 6
        non_nillable_class.s = None

        try:
            self.client.service.non_nillable(non_nillable_class)
        except WebFault, e:
            pass
        else:
            raise Exception("must fail")

    def test_echo_integer_array(self):
        ia = self.client.factory.create('integerArray')
        ia.integer.extend([1, 2, 3, 4, 5])
        self.client.service.echo_integer_array(ia)

    def test_echo_in_header(self):
        in_header = self.client.factory.create('InHeader')
        in_header.s = 'a'
        in_header.i = 3

        self.client.set_options(soapheaders=in_header)
        ret = self.client.service.echo_in_header()
        self.client.set_options(soapheaders=None)

        print(ret)

        self.assertEquals(in_header.s, ret.s)
        self.assertEquals(in_header.i, ret.i)

    def test_echo_in_complex_header(self):
        in_header = self.client.factory.create('InHeader')
        in_header.s = 'a'
        in_header.i = 3
        in_trace_header = self.client.factory.create('InTraceHeader')
        in_trace_header.client = 'suds'
        in_trace_header.callDate = datetime(year=2000, month=1, day=1, hour=0,
                                              minute=0, second=0, microsecond=0)

        self.client.set_options(soapheaders=(in_header, in_trace_header))
        ret = self.client.service.echo_in_complex_header()
        self.client.set_options(soapheaders=None)

        print(ret)

        self.assertEquals(in_header.s, ret[0].s)
        self.assertEquals(in_header.i, ret[0].i)
        self.assertEquals(in_trace_header.client, ret[1].client)
        self.assertEquals(in_trace_header.callDate, ret[1].callDate)

    def test_send_out_header(self):
        out_header = self.client.factory.create('OutHeader')
        out_header.dt = datetime(year=2000, month=1, day=1)
        out_header.f = 3.141592653

        ret = self.client.service.send_out_header()

        self.assertTrue(isinstance(ret, type(out_header)))
        self.assertEquals(ret.dt, out_header.dt)
        self.assertEquals(ret.f, out_header.f)

    def test_send_out_complex_header(self):
        out_header = self.client.factory.create('OutHeader')
        out_header.dt = datetime(year=2000, month=1, day=1)
        out_header.f = 3.141592653
        out_trace_header = self.client.factory.create('OutTraceHeader')
        out_trace_header.receiptDate = datetime(year=2000, month=1, day=1,
                                  hour=1, minute=1, second=1, microsecond=1)
        out_trace_header.returnDate = datetime(year=2000, month=1, day=1,
                                 hour=1, minute=1, second=1, microsecond=100)

        ret = self.client.service.send_out_complex_header()

        self.assertTrue(isinstance(ret[0], type(out_header)))
        self.assertEquals(ret[0].dt, out_header.dt)
        self.assertEquals(ret[0].f, out_header.f)
        self.assertTrue(isinstance(ret[1], type(out_trace_header)))
        self.assertEquals(ret[1].receiptDate, out_trace_header.receiptDate)
        self.assertEquals(ret[1].returnDate, out_trace_header.returnDate)
        # Control the reply soap header (in an unelegant way but this is the
        # only way with suds)
        soapheaders = self.client.last_received().getChild("Envelope").getChild("Header")
        soap_out_header = soapheaders.getChild('OutHeader')
        self.assertEquals('T'.join((out_header.dt.date().isoformat(),
                                    out_header.dt.time().isoformat())),
                          soap_out_header.getChild('dt').getText())
        self.assertEquals(unicode(out_header.f), soap_out_header.getChild('f').getText())
        soap_out_trace_header = soapheaders.getChild('OutTraceHeader')
        self.assertEquals('T'.join((out_trace_header.receiptDate.date().isoformat(),
                                    out_trace_header.receiptDate.time().isoformat())),
                          soap_out_trace_header.getChild('receiptDate').getText())
        self.assertEquals('T'.join((out_trace_header.returnDate.date().isoformat(),
                                    out_trace_header.returnDate.time().isoformat())),
                          soap_out_trace_header.getChild('returnDate').getText())

    def test_echo_string(self):
        test_string = "OK"
        ret = self.client.service.echo_string(test_string)

        self.assertEquals(ret, test_string)

    def __get_xml_test_val(self):
        return {
            "test_sub": {
                "test_subsub1": {
                    "test_subsubsub1" : ["subsubsub1 value"]
                },
                "test_subsub2": ["subsub2 value 1", "subsub2 value 2"],
                "test_subsub3": [
                    {
                        "test_subsub3sub1": ["subsub3sub1 value"]
                    },
                    {
                        "test_subsub3sub2": ["subsub3sub2 value"]
                    },
                ],
                "test_subsub4": [],
                "test_subsub5": ["x"],
            }
        }

    def test_echo_simple_class(self):
        val = self.client.factory.create("{spyne.test.interop.server}SimpleClass")

        val.i = 45
        val.s = "asd"

        ret = self.client.service.echo_simple_class(val)

        assert ret.i == val.i
        assert ret.s == val.s

    def test_echo_class_with_self_reference(self):
        val = self.client.factory.create("{spyne.test.interop.server}ClassWithSelfReference")

        val.i = 45
        val.sr = self.client.factory.create("{spyne.test.interop.server}ClassWithSelfReference")
        val.sr.i = 50
        val.sr.sr = None

        ret = self.client.service.echo_class_with_self_reference(val)

        assert ret.i == val.i
        assert ret.sr.i == val.sr.i

    def test_echo_nested_class(self):
        val = self.client.factory.create("{punk.tunk}NestedClass");

        val.i = 45
        val.s = "asd"
        val.f = 12.34
        val.ai = self.client.factory.create("integerArray")
        val.ai.integer.extend([1, 2, 3, 45, 5, 3, 2, 1, 4])

        val.simple = self.client.factory.create("{spyne.test.interop.server}SimpleClassArray")

        val.simple.SimpleClass.append(self.client.factory.create("{spyne.test.interop.server}SimpleClass"))
        val.simple.SimpleClass.append(self.client.factory.create("{spyne.test.interop.server}SimpleClass"))

        val.simple.SimpleClass[0].i = 45
        val.simple.SimpleClass[0].s = "asd"
        val.simple.SimpleClass[1].i = 12
        val.simple.SimpleClass[1].s = "qwe"

        val.other = self.client.factory.create("{spyne.test.interop.server}OtherClass");
        val.other.dt = datetime.now()
        val.other.d = 123.456
        val.other.b = True

        ret = self.client.service.echo_nested_class(val)

        self.assertEquals(ret.i, val.i)
        self.assertEqual(ret.ai[0], val.ai[0])
        self.assertEquals(ret.simple.SimpleClass[0].s, val.simple.SimpleClass[0].s)
        self.assertEqual(ret.other.dt, val.other.dt)

    def test_huge_number(self):
        self.assertEquals(self.client.service.huge_number(), 2**int(1e5))

    def test_long_string(self):
        self.assertEquals(self.client.service.long_string(), ('0123456789abcdef' * 16384))

    def test_long_string(self):
        self.client.service.test_empty()

    def test_echo_extension_class(self):
        val = self.client.factory.create("{bar}ExtensionClass")

        val.i = 45
        val.s = "asd"
        val.f = 12.34

        val.simple = self.client.factory.create("{spyne.test.interop.server}SimpleClassArray")

        val.simple.SimpleClass.append(self.client.factory.create("{spyne.test.interop.server}SimpleClass"))
        val.simple.SimpleClass.append(self.client.factory.create("{spyne.test.interop.server}SimpleClass"))

        val.simple.SimpleClass[0].i = 45
        val.simple.SimpleClass[0].s = "asd"
        val.simple.SimpleClass[1].i = 12
        val.simple.SimpleClass[1].s = "qwe"

        val.other = self.client.factory.create("{spyne.test.interop.server}OtherClass");
        val.other.dt = datetime.now()
        val.other.d = 123.456
        val.other.b = True

        val.p = self.client.factory.create("{hunk.sunk}NonNillableClass");
        val.p.dt = datetime(2010, 6, 2)
        val.p.i = 123
        val.p.s = "punk"

        val.l = datetime(2010, 7, 2)
        val.q = 5

        ret = self.client.service.echo_extension_class(val)
        print(ret)

        self.assertEquals(ret.i, val.i)
        self.assertEquals(ret.s, val.s)
        self.assertEquals(ret.f, val.f)
        self.assertEquals(ret.simple.SimpleClass[0].i, val.simple.SimpleClass[0].i)
        self.assertEquals(ret.other.dt, val.other.dt)
        self.assertEquals(ret.p.s, val.p.s)

    def test_python_exception(self):
        try:
            self.client.service.python_exception()
            raise Exception("must fail")
        except WebFault, e:
            pass

    def test_soap_exception(self):
        try:
            self.client.service.soap_exception()
            raise Exception("must fail")
        except WebFault, e:
            pass

    def test_complex_return(self):
        ret = self.client.service.complex_return()

        self.assertEquals(ret.resultCode, 1)
        self.assertEquals(ret.resultDescription, "Test")
        self.assertEquals(ret.transactionId, 123)
        self.assertEquals(ret.roles.RoleEnum[0], "MEMBER")

    def test_return_invalid_data(self):
        try:
            self.client.service.return_invalid_data()
            raise Exception("must fail")
        except:
            pass

    def test_custom_messages(self):
        ret = self.client.service.custom_messages("test")

        assert ret == 'test'

    def test_echo_simple_bare(self):
        ret = self.client.service.echo_simple_bare("test")

        assert ret == 'test'

    #
    # This test is disabled because suds does not create the right request
    # object. The first <ns0:string> tag below is wrong.
    #
    #<SOAP-ENV:Envelope xmlns:ns0="spyne.test.interop.server"
    #                   xmlns:xs="http://www.w3.org/2001/XMLSchema"
    #                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    #                   xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/"
    #                   xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    #  <SOAP-ENV:Header/>
    #   <ns1:Body>
    #      <ns0:echo_complex_bare>
    #         <ns0:string>
    #            <ns0:string>abc</ns0:string>
    #            <ns0:string>def</ns0:string>
    #         </ns0:string>
    #      </ns0:echo_complex_bare>
    #   </ns1:Body>
    #</SOAP-ENV:Envelope>
    #
    # The right request looks like this:
    #
    #      <ns0:echo_complex_bare>
    #         <ns0:string>abc</ns0:string>
    #         <ns0:string>def</ns0:string>
    #      </ns0:echo_complex_bare>
    #
    def _test_echo_complex_bare(self):
        val = ['abc','def']
        ia = self.client.factory.create('stringArray')
        ia.string.extend(val)
        ret = self.client.service.echo_complex_bare(ia)

        assert ret == val

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


<commit_before>from StringIO import StringIO
import os
from tempfile import mkstemp
from numpy.testing import *
import numpy as N

set_package_path()
from io.npfile import npfile, sys_endian_code
restore_path()

class test_npfile(NumpyTestCase):

    def test_init(self):
        fd, fname = mkstemp()
        npf = npfile(fname)
        arr = N.reshape(N.arange(10), (5,2))
        self.assertRaises(IOError, npf.write, arr)
        npf.close()
        npf = npfile(fname, 'w')
        npf.write(arr)
        npf.rewind()
        self.assertRaises(IOError, npf.read,
                          arr.shape,
                          arr.dtype)
        npf.close()
        os.remove(fname)

        npf = npfile(StringIO(), endian='>', order='F')
        assert npf.endian == '>', 'Endian not set correctly'
        assert npf.order == 'F', 'Order not set correctly'
        npf.endian = '<'
        assert npf.endian == '<', 'Endian not set correctly'

    def test_parse_endian(self):
        npf = npfile(StringIO())
        swapped_code = sys_endian_code == '<' and '>' or '<'
        assert npf.parse_endian('native') == sys_endian_code
        assert npf.parse_endian('swapped') == swapped_code
        assert npf.parse_endian('l') == '<'
        assert npf.parse_endian('B') == '>'
        assert npf.parse_endian('dtype') == 'dtype'
        self.assertRaises(ValueError, npf.parse_endian, 'nonsense')

    def test_raw_read_write(self):
        npf = npfile(StringIO())
        str = 'test me with this string'
        npf.raw_write(str)
        npf.rewind()
        assert str == npf.raw_read(len(str))

    def test_read_write(self):
        npf = npfile(StringIO())
        arr = N.reshape(N.arange(10), (5,2))
        f_arr = arr.reshape((2,5)).T
        bo = arr.dtype.byteorder
        swapped_code = sys_endian_code == '<' and '>' or '<'
        if bo in ['=', sys_endian_code]:
            nbo = swapped_code
        else:
            nbo = sys_endian_code
        bs_arr = arr.newbyteorder(nbo)
        adt = arr.dtype
        shp = arr.shape
        npf.write(arr)
        npf.rewind()
        assert_array_equal(npf.read(shp, adt), arr)
        npf.rewind()
        assert_array_equal(npf.read(shp, adt, endian=swapped_code),
                           bs_arr)
        npf.rewind()
        assert_array_equal(npf.read(shp, adt, order='F'),
                           f_arr)

        npf = npfile(StringIO(), endian='swapped', order='F')
        npf.write(arr)
        npf.rewind()
        assert_array_equal(npf.read(shp, adt), arr)
        npf.rewind()
        assert_array_equal(npf.read(shp, adt, endian='dtype'), bs_arr)
        npf.rewind()
        # assert_array_equal(npf.read(shp, adt, order='C'), f_arr)

<commit_msg>Corrected C/F order tests<commit_after>from StringIO import StringIO
import os
from tempfile import mkstemp
from numpy.testing import *
import numpy as N

set_package_path()
from io.npfile import npfile, sys_endian_code
restore_path()

class test_npfile(NumpyTestCase):

    def test_init(self):
        fd, fname = mkstemp()
        npf = npfile(fname)
        arr = N.reshape(N.arange(10), (5,2))
        self.assertRaises(IOError, npf.write, arr)
        npf.close()
        npf = npfile(fname, 'w')
        npf.write(arr)
        npf.rewind()
        self.assertRaises(IOError, npf.read,
                          arr.shape,
                          arr.dtype)
        npf.close()
        os.remove(fname)

        npf = npfile(StringIO(), endian='>', order='F')
        assert npf.endian == '>', 'Endian not set correctly'
        assert npf.order == 'F', 'Order not set correctly'
        npf.endian = '<'
        assert npf.endian == '<', 'Endian not set correctly'

    def test_parse_endian(self):
        npf = npfile(StringIO())
        swapped_code = sys_endian_code == '<' and '>' or '<'
        assert npf.parse_endian('native') == sys_endian_code
        assert npf.parse_endian('swapped') == swapped_code
        assert npf.parse_endian('l') == '<'
        assert npf.parse_endian('B') == '>'
        assert npf.parse_endian('dtype') == 'dtype'
        self.assertRaises(ValueError, npf.parse_endian, 'nonsense')

    def test_raw_read_write(self):
        npf = npfile(StringIO())
        str = 'test me with this string'
        npf.raw_write(str)
        npf.rewind()
        assert str == npf.raw_read(len(str))

    def test_read_write(self):
        npf = npfile(StringIO())
        arr = N.reshape(N.arange(10), (5,2))
        # Arr as read in fortran order
        f_arr = arr.reshape((2,5)).T
        # Arr written in fortran order read in C order
        cf_arr = arr.T.reshape((5,2))
        # Byteswapped array
        bo = arr.dtype.byteorder
        swapped_code = sys_endian_code == '<' and '>' or '<'
        if bo in ['=', sys_endian_code]:
            nbo = swapped_code
        else:
            nbo = sys_endian_code
        bs_arr = arr.newbyteorder(nbo)
        adt = arr.dtype
        shp = arr.shape
        npf.write(arr)
        npf.rewind()
        assert_array_equal(npf.read(shp, adt), arr)
        npf.rewind()
        assert_array_equal(npf.read(shp, adt, endian=swapped_code),
                           bs_arr)
        npf.rewind()
        assert_array_equal(npf.read(shp, adt, order='F'),
                           f_arr)
        npf.rewind()
        npf.write(arr, order='F')
        npf.rewind()
        assert_array_equal(npf.read(shp, adt),
                           cf_arr)

        npf = npfile(StringIO(), endian='swapped', order='F')
        npf.write(arr)
        npf.rewind()
        assert_array_equal(npf.read(shp, adt), arr)
        npf.rewind()
        assert_array_equal(npf.read(shp, adt, endian='dtype'), bs_arr)
        npf.rewind()
        assert_array_equal(npf.read(shp, adt, order='C'), cf_arr)

<|endoftext|>


<commit_before>#! /usr/bin/env python

import numpy as np
import argparse
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

def main():

	#Define the command line options

	parser = argparse.ArgumentParser(description="A simple line plotting script")

	parser.set_defaults(colours=[])
	parser.set_defaults(sep=",")

	parser.add_argument("-f", "--input", dest="inputfile", help="Define the SEP seperated file used as input")
	parser.add_argument("-o", "--output", dest="outputfile", help="Define the file (with extension) which to save output to")
	parser.add_argument("--xlab",  dest="xlab", help="define a label for the x axis")
	parser.add_argument("--ylab",  dest="ylab", help="define a label for the y axis")
	parser.add_argument("-t", "--title",  dest="title", help="define a title for the plot")
	parser.add_argument("-s", "--seperator", dest="sep", default=",", help="Define SEP, the seperator in the input file (default is ',')")
	parser.add_argument("-x", "--xfields",  dest="xfields", action='append', type=int, help="row indicies to be used as x values (each individual value is appenended to a list)")
	parser.add_argument("-y", "--yfields",  dest="yfields", action='append', type=int, help="row indicies to be used as y values (each individual value is appenended to a list) (must be same size as xfields)")
	parser.add_argument("--legend",  dest="legend",  action='append', help="add legend to plot")
	parser.add_argument("--legend_placement",  dest="legplace", type=int,help="specify legend placement as a numeric code (see matplot lib webpages for details)")
	parser.add_argument("-c", "--colours",  dest="colours", action='append', help="colours to be used for lines (each individual value is appenended to a list) (must be same size or larger than xfields) (default is black, red, blue, green, yellow)")

	#grab options
	args = parser.parse_args()

	if (not len(args.colours[:])):
		args.colours=['k','r','b','g','y']
	#Set default colours if unasssinged

	finput = open(args.inputfile,'r+')

	InputData = []
	#This will become a 2D list of the input file

	for line in finput:
		 InputData.append(line.split(args.sep))

	DataArray = np.array(InputData)
	#An array of doubles, extracted from the input file

	fig = plt.figure()

	for index in range(0,len(args.xfields)):

		xcolumn = args.xfields[index]
		ycolumn = args.yfields[index]
		colour = args.colours[index]
		plt.plot(DataArray[:,xcolumn],DataArray[:,ycolumn],colour)

	if (args.xlab):
		plt.xlabel(args.xlab)
	if (args.ylab):
		plt.ylabel(args.ylab)
	if (args.title):
		plt.title(args.title)
	if (args.legend):
		if (args.legplace):
			plt.legend(args.legend, shadow=True, loc=args.legplace)
		else:
			plt.legend(args.legend, shadow=True)

	# save the image to hardcopy
	plt.savefig(args.outputfile)

if __name__ == "__main__":
	main()
<commit_msg>Cleaned up the argparsing<commit_after>#! /usr/bin/env python

import numpy as np
import argparse
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

def main():

	#Define the command line options

	parser = argparse.ArgumentParser(description="A simple line plotting script")

	parser.set_defaults(colours=[])
	parser.set_defaults(sep=",")

	parser.add_argument("-f", "--input", dest="inputfile", help="Define the SEP seperated file used as input")
	parser.add_argument("-o", "--output", dest="outputfile", help="Define the file (with extension) which to save output to")
	parser.add_argument("--xlab",  dest="xlab", help="define a label for the x axis")
	parser.add_argument("--ylab",  dest="ylab", help="define a label for the y axis")
	parser.add_argument("-t", "--title",  dest="title", help="define a title for the plot")
	parser.add_argument("-s", "--seperator", dest="sep", default=",", help="Define SEP, the seperator in the input file (default is ',')")
	parser.add_argument("-x", "--xfields",  dest="xfields", action='append', type=int, help="row indicies to be used as x values (each individual value is appenended to a list)")
	parser.add_argument("-y", "--yfields",  dest="yfields", action='append', type=int, help="row indicies to be used as y values (each individual value is appenended to a list) (must be same size as xfields)")
	parser.add_argument("--legend",  dest="legend",  action='append', help="add legend to plot")
	parser.add_argument("--legend_placement",  dest="legplace", type=int,help="specify legend placement as a numeric code (see matplot lib webpages for details)")
	parser.add_argument("-c", "--colours",  dest="colours", action='append', help="colours to be used for lines (each individual value is appenended to a list) (must be same size or larger than xfields) (default is black, red, blue, green, yellow)")

	#grab options
	args = parser.parse_args()

	if (not len(args.colours[:])):
		args.colours=['k','r','b','g','y']
	#Set default colours if unasssinged

	finput = open(args.inputfile,'r+')

	InputData = []
	#This will become a 2D list of the input file

	for line in finput:
		 InputData.append(line.split(args.sep))

	DataArray = np.array(InputData)
	#An array of doubles, extracted from the input file

	fig = plt.figure()

	for index in range(0,len(args.xfields)):

		xcolumn = args.xfields[index]
		ycolumn = args.yfields[index]
		colour = args.colours[index]
		plt.plot(DataArray[:,xcolumn],DataArray[:,ycolumn],colour)

	if (args.xlab):
		plt.xlabel(args.xlab)
	if (args.ylab):
		plt.ylabel(args.ylab)
	if (args.title):
		plt.title(args.title)
	if (args.legend):
		if (args.legplace):
			plt.legend(args.legend, shadow=True, loc=args.legplace)
		else:
			plt.legend(args.legend, shadow=True)

	# save the image to hardcopy
	plt.savefig(args.outputfile)

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


<commit_before>r"""Routines to decode AppleSingle files
"""
import struct
import sys
try:
    import MacOS
    import Carbon.File
except:
    class MacOS:
        def openrf(path, mode):
            return open(path + '.rsrc', mode)
        openrf = classmethod(openrf)
    class Carbon:
        class File:
            class FSSpec:
                pass
            class FSRef:
                pass
            class Alias:
                pass

# all of the errors in this module are really errors in the input
# so I think it should test positive against ValueError.
class Error(ValueError):
    pass

# File header format: magic, version, unused, number of entries
AS_HEADER_FORMAT=">ll16sh"
AS_HEADER_LENGTH=26
# The flag words for AppleSingle
AS_MAGIC=0x00051600
AS_VERSION=0x00020000

# Entry header format: id, offset, length
AS_ENTRY_FORMAT=">lll"
AS_ENTRY_LENGTH=12

# The id values
AS_DATAFORK=1
AS_RESOURCEFORK=2
AS_IGNORE=(3,4,5,6,8,9,10,11,12,13,14,15)

class AppleSingle(object):
    datafork = None
    resourcefork = None

    def __init__(self, fileobj, verbose=False):
        header = fileobj.read(AS_HEADER_LENGTH)
        try:
            magic, version, ig, nentry = struct.unpack(AS_HEADER_FORMAT, header)
        except ValueError, arg:
            raise Error, "Unpack header error: %s" % (arg,)
        if verbose:
            print 'Magic:   0x%8.8x' % (magic,)
            print 'Version: 0x%8.8x' % (version,)
            print 'Entries: %d' % (nentry,)
        if magic != AS_MAGIC:
            raise Error, "Unknown AppleSingle magic number 0x%8.8x" % (magic,)
        if version != AS_VERSION:
            raise Error, "Unknown AppleSingle version number 0x%8.8x" % (version,)
        if nentry <= 0:
            raise Error, "AppleSingle file contains no forks"
        headers = [fileobj.read(AS_ENTRY_LENGTH) for i in xrange(nentry)]
        self.forks = []
        for hdr in headers:
            try:
                restype, offset, length = struct.unpack(AS_ENTRY_FORMAT, hdr)
            except ValueError, arg:
                raise Error, "Unpack entry error: %s" % (arg,)
            if verbose:
                print "Fork %d, offset %d, length %d" % (restype, offset, length)
            fileobj.seek(offset)
            data = fileobj.read(length)
            if len(data) != length:
                raise Error, "Short read: expected %d bytes got %d" % (length, len(data))
            self.forks.append((restype, data))
            if restype == AS_DATAFORK:
                self.datafork = data
            elif restype == AS_RESOURCEFORK:
                self.resourcefork = data

    def tofile(self, path, resonly=False):
        outfile = open(path, 'wb')
        data = False
        if resonly:
            if self.resourcefork is None:
                raise Error, "No resource fork found"
            fp = open(path, 'wb')
            fp.write(self.resourcefork)
            fp.close()
        elif (self.resourcefork is None and self.datafork is None):
            raise Error, "No useful forks found"
        else:
            if self.datafork is not None:
                fp = open(path, 'wb')
                fp.write(self.datafork)
                fp.close()
            if self.resourcefork is not None:
                fp = MacOS.openrf(path, '*wb')
                fp.write(self.resourcefork)
                fp.close()

def decode(infile, outpath, resonly=False, verbose=False):
    """decode(infile, outpath [, resonly=False, verbose=False])

    Creates a decoded file from an AppleSingle encoded file.
    If resonly is True, then it will create a regular file at
    outpath containing only the resource fork from infile.
    Otherwise it will create an AppleDouble file at outpath
    with the data and resource forks from infile.  On platforms
    without the MacOS module, it will create inpath and inpath+'.rsrc'
    with the data and resource forks respectively.

    """
    if not hasattr(infile, 'read'):
        if isinstance(infile, Carbon.File.Alias):
            infile = infile.ResolveAlias()[0]
        if isinstance(infile, (Carbon.File.FSSpec, Carbon.File.FSRef)):
            infile = infile.as_pathname()
        infile = open(infile, 'rb')

    as = AppleSingle(infile, verbose=verbose)
    as.tofile(outpath, resonly=resonly)

def _test():
    if len(sys.argv) < 3 or sys.argv[1] == '-r' and len(sys.argv) != 4:
        print 'Usage: applesingle.py [-r] applesinglefile decodedfile'
        sys.exit(1)
    if sys.argv[1] == '-r':
        resonly = True
        del sys.argv[1]
    else:
        resonly = False
    decode(sys.argv[1], sys.argv[2], resonly=resonly)

if __name__ == '__main__':
    _test()
<commit_msg>Damn another occurrence of using as as a keywordf<commit_after>r"""Routines to decode AppleSingle files
"""
import struct
import sys
try:
    import MacOS
    import Carbon.File
except:
    class MacOS:
        def openrf(path, mode):
            return open(path + '.rsrc', mode)
        openrf = classmethod(openrf)
    class Carbon:
        class File:
            class FSSpec:
                pass
            class FSRef:
                pass
            class Alias:
                pass

# all of the errors in this module are really errors in the input
# so I think it should test positive against ValueError.
class Error(ValueError):
    pass

# File header format: magic, version, unused, number of entries
AS_HEADER_FORMAT=">ll16sh"
AS_HEADER_LENGTH=26
# The flag words for AppleSingle
AS_MAGIC=0x00051600
AS_VERSION=0x00020000

# Entry header format: id, offset, length
AS_ENTRY_FORMAT=">lll"
AS_ENTRY_LENGTH=12

# The id values
AS_DATAFORK=1
AS_RESOURCEFORK=2
AS_IGNORE=(3,4,5,6,8,9,10,11,12,13,14,15)

class AppleSingle(object):
    datafork = None
    resourcefork = None

    def __init__(self, fileobj, verbose=False):
        header = fileobj.read(AS_HEADER_LENGTH)
        try:
            magic, version, ig, nentry = struct.unpack(AS_HEADER_FORMAT, header)
        except ValueError, arg:
            raise Error, "Unpack header error: %s" % (arg,)
        if verbose:
            print 'Magic:   0x%8.8x' % (magic,)
            print 'Version: 0x%8.8x' % (version,)
            print 'Entries: %d' % (nentry,)
        if magic != AS_MAGIC:
            raise Error, "Unknown AppleSingle magic number 0x%8.8x" % (magic,)
        if version != AS_VERSION:
            raise Error, "Unknown AppleSingle version number 0x%8.8x" % (version,)
        if nentry <= 0:
            raise Error, "AppleSingle file contains no forks"
        headers = [fileobj.read(AS_ENTRY_LENGTH) for i in xrange(nentry)]
        self.forks = []
        for hdr in headers:
            try:
                restype, offset, length = struct.unpack(AS_ENTRY_FORMAT, hdr)
            except ValueError, arg:
                raise Error, "Unpack entry error: %s" % (arg,)
            if verbose:
                print "Fork %d, offset %d, length %d" % (restype, offset, length)
            fileobj.seek(offset)
            data = fileobj.read(length)
            if len(data) != length:
                raise Error, "Short read: expected %d bytes got %d" % (length, len(data))
            self.forks.append((restype, data))
            if restype == AS_DATAFORK:
                self.datafork = data
            elif restype == AS_RESOURCEFORK:
                self.resourcefork = data

    def tofile(self, path, resonly=False):
        outfile = open(path, 'wb')
        data = False
        if resonly:
            if self.resourcefork is None:
                raise Error, "No resource fork found"
            fp = open(path, 'wb')
            fp.write(self.resourcefork)
            fp.close()
        elif (self.resourcefork is None and self.datafork is None):
            raise Error, "No useful forks found"
        else:
            if self.datafork is not None:
                fp = open(path, 'wb')
                fp.write(self.datafork)
                fp.close()
            if self.resourcefork is not None:
                fp = MacOS.openrf(path, '*wb')
                fp.write(self.resourcefork)
                fp.close()

def decode(infile, outpath, resonly=False, verbose=False):
    """decode(infile, outpath [, resonly=False, verbose=False])

    Creates a decoded file from an AppleSingle encoded file.
    If resonly is True, then it will create a regular file at
    outpath containing only the resource fork from infile.
    Otherwise it will create an AppleDouble file at outpath
    with the data and resource forks from infile.  On platforms
    without the MacOS module, it will create inpath and inpath+'.rsrc'
    with the data and resource forks respectively.

    """
    if not hasattr(infile, 'read'):
        if isinstance(infile, Carbon.File.Alias):
            infile = infile.ResolveAlias()[0]
        if isinstance(infile, (Carbon.File.FSSpec, Carbon.File.FSRef)):
            infile = infile.as_pathname()
        infile = open(infile, 'rb')

    asfile = AppleSingle(infile, verbose=verbose)
    asfile.tofile(outpath, resonly=resonly)

def _test():
    if len(sys.argv) < 3 or sys.argv[1] == '-r' and len(sys.argv) != 4:
        print 'Usage: applesingle.py [-r] applesinglefile decodedfile'
        sys.exit(1)
    if sys.argv[1] == '-r':
        resonly = True
        del sys.argv[1]
    else:
        resonly = False
    decode(sys.argv[1], sys.argv[2], resonly=resonly)

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