<commit_before>from panoply import DataSource, PanoplyException
from datetime import datetime

ERROR_CODES_REGISTRY = {
    400: 'Bad request',
    401: 'Unauthorized',
    403: 'Permissions error',
    404: 'Resource is not found',
    408: 'Timeout',
    422: 'Parsing error',
    429: 'Rate limit',
    500: 'Internal exception',
    501: 'Unclassified error',
    506: 'SDK error in processing an error'
}

EXCEPTIONS_REGISTRY = {}

class NormalizedException(PanoplyException):
    def __init__(self, message, error_code, exception_cls,
                 phase, source_type, source_id, database_id,
                 retryable=True):
        super().__init__(message, retryable)
        self.message = message
        self.error_code = error_code
        self.phase = phase
        self.source_type = source_type
        self.source_id = source_id
        self.database_id = database_id
        self.exception_cls = exception_cls
        self.created_at = datetime.utcnow()

def set_internal_code(error_code: int) -> callable:
    """ A decorator is used on exception classes to register mapping
        of error and internal code from ERROR_CODES_REGISTRY.
        Parameters
        ----------
        error_code : int
           Error code from ERROR_CODES_REGISTRY.
    """
    def decorator(exception_cls: type) -> type:
        if not issubclass(exception_cls, BaseException):
            raise RuntimeError('Unable to set error code for non-Exception class')

        EXCEPTIONS_REGISTRY[exception_cls] = error_code

        return exception_cls

    return decorator

def handle_errors(phase: str) -> callable:
    """ A decorator is used to normalize raised exceptions.
       Parameters
       ----------
       phase : str
           Equals to config / collect.
    """
    def _handle_errors(func: callable) -> callable:
        def wrapper(*args, **kwargs) -> list:
            try:
                return func(*args, **kwargs)
            except Exception as e:
                # source object can be:
                # 1. a first param in dynamic params methods (e.g. definition(source, options))
                # 2. an attribute of the DataSource class (e.g. definition(self, params) -> source = self.source)
                source_config = args[0]
                if isinstance(source_config, DataSource):
                    source_config = getattr(source_config, 'source', None)

                error_code = EXCEPTIONS_REGISTRY.get(type(e))

                if error_code is None:
                    error_code = 501

                if error_code not in ERROR_CODES_REGISTRY:
                    error_code = 506

                details = {
                    'message': str(e),
                    'error_code': error_code,
                    'exception_cls': str(type(e)),
                    'phase': phase,
                    'source_type': source_config['type'],
                    'source_id': source_config['id'],
                    'database_id': source_config['database'],
                    'retryable': getattr(e, 'retryable', True)
                }

                print(details)
                normalized = NormalizedException(**details)

                raise normalized
        return wrapper
    return _handle_errors
<commit_msg>Rename error code property<commit_after>from panoply import DataSource, PanoplyException
from datetime import datetime

ERROR_CODES_REGISTRY = {
    400: 'Bad request',
    401: 'Unauthorized',
    403: 'Permissions error',
    404: 'Resource is not found',
    408: 'Timeout',
    422: 'Parsing error',
    429: 'Rate limit',
    500: 'Internal exception',
    501: 'Unclassified error',
    506: 'SDK error in processing an error'
}

EXCEPTIONS_REGISTRY = {}

class NormalizedException(PanoplyException):
    def __init__(self, message, code, exception_cls,
                 phase, source_type, source_id, database_id,
                 retryable=True):
        super().__init__(message, retryable)
        self.message = message
        self.code = code
        self.phase = phase
        self.source_type = source_type
        self.source_id = source_id
        self.database_id = database_id
        self.exception_cls = exception_cls
        self.created_at = datetime.utcnow()

def set_internal_code(code: int) -> callable:
    """ A decorator is used on exception classes to register mapping
        of error and internal code from ERROR_CODES_REGISTRY.
        Parameters
        ----------
        code : int
           Error code from ERROR_CODES_REGISTRY.
    """
    def decorator(exception_cls: type) -> type:
        if not issubclass(exception_cls, BaseException):
            raise RuntimeError('Unable to set error code for non-Exception class')

        EXCEPTIONS_REGISTRY[exception_cls] = code

        return exception_cls

    return decorator

def handle_errors(phase: str) -> callable:
    """ A decorator is used to normalize raised exceptions.
       Parameters
       ----------
       phase : str
           Equals to config / collect.
    """
    def _handle_errors(func: callable) -> callable:
        def wrapper(*args, **kwargs) -> list:
            try:
                return func(*args, **kwargs)
            except Exception as e:
                # source object can be:
                # 1. a first param in dynamic params methods (e.g. definition(source, options))
                # 2. an attribute of the DataSource class (e.g. definition(self, params) -> source = self.source)
                source_config = args[0]
                if isinstance(source_config, DataSource):
                    source_config = getattr(source_config, 'source', None)

                code = EXCEPTIONS_REGISTRY.get(type(e))

                if code is None:
                    code = 501

                if code not in ERROR_CODES_REGISTRY:
                    code = 506

                details = {
                    'message': str(e),
                    'code': code,
                    'exception_cls': str(type(e)),
                    'phase': phase,
                    'source_type': source_config['type'],
                    'source_id': source_config['id'],
                    'database_id': source_config['database'],
                    'retryable': getattr(e, 'retryable', True)
                }

                print(details)
                normalized = NormalizedException(**details)

                raise normalized
        return wrapper
    return _handle_errors
<|endoftext|>


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

# Copyright (c) Facebook, Inc. and its affiliates.
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

from parlai.core.teachers import FbDialogTeacher
from parlai.utils.misc import warn_once
from .build import build

import copy
import os

'''All teachers have a version with and without label candidates. Each teacher
defaults to using a dataset with label candidates. To use a dataset without
label candidates, specify this using the task flag:

--task convai2:{TEACHER_NAME}:no_cands

where TEACHER_NAME is None, SelfOriginal (Self), or SelfRevised.
'''

def _path(opt, persona, use_cands):
    # Build the data if it doesn't exist.
    build(opt)
    datatype = opt['datatype'].split(':')[0]
    if datatype == 'test':
        warn_once("WARNING: Test set not included. Setting datatype to valid.")
        datatype = 'valid'
    dt = datatype + '_' + persona
    cands = '' if use_cands else '_no_cands'
    return os.path.join(opt['datapath'], 'ConvAI2', dt + cands + '.txt')

class BothTeacher(FbDialogTeacher):
    def __init__(self, opt, shared=None):
        opt = copy.deepcopy(opt)
        try:
            cands = opt['task'].split(":")[2]
            use_cands = False if cands == 'no_cands' else True
        except Exception:
            use_cands = True
        opt['datafile'] = _path(opt, 'both_original', use_cands)
        super().__init__(opt, shared)

class NoneTeacher(FbDialogTeacher):
    def __init__(self, opt, shared=None):
        opt = copy.deepcopy(opt)
        try:
            cands = opt['task'].split(":")[2]
            use_cands = False if cands == 'no_cands' else True
        except Exception:
            use_cands = True
        opt['datafile'] = _path(opt, 'none_original', use_cands)
        super().__init__(opt, shared)

class SelfOriginalTeacher(FbDialogTeacher):
    def __init__(self, opt, shared=None):
        opt = copy.deepcopy(opt)
        try:
            cands = opt['task'].split(":")[2]
            use_cands = False if cands == 'no_cands' else True
        except Exception:
            use_cands = True
        opt['datafile'] = _path(opt, 'self_original', use_cands)
        super().__init__(opt, shared)

class SelfTeacher(SelfOriginalTeacher):
    pass

class SelfRevisedTeacher(FbDialogTeacher):
    def __init__(self, opt, shared=None):
        opt = copy.deepcopy(opt)
        try:
            cands = opt['task'].split(":")[2]
            use_cands = False if cands == 'no_cands' else True
        except Exception:
            use_cands = True
        opt['datafile'] = _path(opt, 'self_revised', use_cands)
        super().__init__(opt, shared)

class DefaultTeacher(SelfOriginalTeacher):
    pass

class InteractiveTeacher(SelfOriginalTeacher):
    # Dummy class to add arguments for interactive world.
    pass

class SelfchatTeacher(SelfOriginalTeacher):
    # Dummy class to add arguments for interactive world.
    pass
<commit_msg>ConvAI2 normalized text (#2466)<commit_after>#!/usr/bin/env python3

# Copyright (c) Facebook, Inc. and its affiliates.
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

from parlai.core.teachers import FbDialogTeacher
from parlai.utils.misc import warn_once
from .build import build
from parlai.utils.strings import normalize_reply

import copy
import os

'''All teachers have a version with and without label candidates. Each teacher
defaults to using a dataset with label candidates. To use a dataset without
label candidates, specify this using the task flag:

--task convai2:{TEACHER_NAME}:no_cands

where TEACHER_NAME is None, SelfOriginal (Self), or SelfRevised.
'''

def _path(opt, persona, use_cands):
    # Build the data if it doesn't exist.
    build(opt)
    datatype = opt['datatype'].split(':')[0]
    if datatype == 'test':
        warn_once("WARNING: Test set not included. Setting datatype to valid.")
        datatype = 'valid'
    dt = datatype + '_' + persona
    cands = '' if use_cands else '_no_cands'
    return os.path.join(opt['datapath'], 'ConvAI2', dt + cands + '.txt')

class BothTeacher(FbDialogTeacher):
    def __init__(self, opt, shared=None):
        opt = copy.deepcopy(opt)
        try:
            cands = opt['task'].split(":")[2]
            use_cands = False if cands == 'no_cands' else True
        except Exception:
            use_cands = True
        opt['datafile'] = _path(opt, 'both_original', use_cands)
        super().__init__(opt, shared)

class NoneTeacher(FbDialogTeacher):
    def __init__(self, opt, shared=None):
        opt = copy.deepcopy(opt)
        try:
            cands = opt['task'].split(":")[2]
            use_cands = False if cands == 'no_cands' else True
        except Exception:
            use_cands = True
        opt['datafile'] = _path(opt, 'none_original', use_cands)
        super().__init__(opt, shared)

class SelfOriginalTeacher(FbDialogTeacher):
    def __init__(self, opt, shared=None):
        opt = copy.deepcopy(opt)
        try:
            cands = opt['task'].split(":")[2]
            use_cands = False if cands == 'no_cands' else True
        except Exception:
            use_cands = True
        opt['datafile'] = _path(opt, 'self_original', use_cands)
        super().__init__(opt, shared)

class SelfTeacher(SelfOriginalTeacher):
    pass

class SelfRevisedTeacher(FbDialogTeacher):
    def __init__(self, opt, shared=None):
        opt = copy.deepcopy(opt)
        try:
            cands = opt['task'].split(":")[2]
            use_cands = False if cands == 'no_cands' else True
        except Exception:
            use_cands = True
        opt['datafile'] = _path(opt, 'self_revised', use_cands)
        super().__init__(opt, shared)

class NormalizedTeacher(SelfOriginalTeacher):
    def normalize_replies(self, x):
        xs = x.split('\n')
        xs2 = []
        for x in xs:
            xs2.append(normalize_reply(x))
        return '\n'.join(xs2)

    def setup_data(self, path):
        print("[loading normalized fbdialog data:" + path + "]")
        with open(path) as read:
            start = True
            x = ''
            reward = 0
            last_conv_id = None
            for line in read:
                line = line.strip().replace('\\n', '\n')
                if len(line) == 0:
                    # empty response
                    continue

                # first, get conversation index -- '1' means start of episode
                space_idx = line.find(' ')
                if space_idx == -1:
                    # empty line, both individuals are saying whitespace
                    conv_id = int(line)
                else:
                    conv_id = int(line[:space_idx])

                # split line into constituent parts, if available:
                # x<tab>y<tab>reward<tab>label_candidates
                # where y, reward, and label_candidates are optional
                split = line[space_idx + 1 :].split('\t')

                # remove empty items and strip each one
                for i in range(len(split)):
                    word = split[i].strip()
                    if len(word) == 0:
                        split[i] = ''
                    else:
                        split[i] = word
                # Empty reward string same as None
                if len(split) > 2 and split[2] == '':
                    split[2] = None

                # now check if we're at a new episode
                if last_conv_id is None or conv_id <= last_conv_id:
                    x = x.strip()
                    if x:
                        x = self.normalize_replies(x)
                        import pdb

                        pdb.set_trace()
                        yield [x, None, reward], start
                    start = True
                    reward = 0
                    # start a new episode
                    x = split[0]
                else:
                    if x:
                        # otherwise add current x to what we have so far
                        x = '{x}\n{next_x}'.format(x=x, next_x=split[0])
                    else:
                        x = split[0]
                last_conv_id = conv_id
                if len(split) > 2 and split[2]:
                    reward += float(split[2])

                if len(split) > 1 and split[1]:
                    # only generate an example if we have a y
                    split[0] = x
                    # split labels
                    split[1] = split[1].split('|')
                    if len(split) > 3:
                        # split label_candidates
                        split[3] = split[3].split('|')
                    if len(split) > 2:
                        split[2] = reward
                    else:
                        split.append(reward)
                    # normalize
                    split[0] = self.normalize_replies(split[0])
                    for i, _c in enumerate(split[1]):
                        split[1][i] = self.normalize_replies(split[1][i])
                    for i, _c in enumerate(split[3]):
                        split[3][i] = self.normalize_replies(split[3][i])
                    if start:
                        yield split, True
                        start = False
                    else:
                        yield split, False
                    # reset x in case there is unlabeled data still left
                    x = ''
                    reward = 0
            if x:
                x = self.normalize_replies(x)
                yield [x, None, reward], start

class DefaultTeacher(SelfOriginalTeacher):
    pass

class InteractiveTeacher(SelfOriginalTeacher):
    # Dummy class to add arguments for interactive world.
    pass

class SelfchatTeacher(SelfOriginalTeacher):
    # Dummy class to add arguments for interactive world.
    pass
<|endoftext|>


<commit_before>#!/usr/bin/env python
#
# Copyright 2014 Trey Morris
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
#
import redis
import time
import datetime
import shortuuid
import pytz

import flask
import flask_appconfig
import flask_bootstrap

r = redis.StrictRedis(unix_socket_path='/run/redis.sock', db=3)

###### REDIS SCHEMA ######
# lexicographically sorted set of tags
#    tags
# time sorted set of paste uuids with tag
#    tag:<tagname>
# time sorted set of pastes (for sorting in tag view and reaping later)
#    pastes
# paste -> tag map for each paste (for reaping from tag:<tagname>)
#    paste_tag:<uuid>
# each paste
#    paste:<uuid>

hilights = ['BOOM']
hilight_color = 'pink'

def tag_index():
    tag_list = r.zrange('tags', 0, -1)
    with r.pipeline() as pipe:
        for tag in tag_list:
            pipe.zcard('tag:%s' % tag)
        tag_num_list = pipe.execute()
    tags = dict(zip(tag_list, tag_num_list))
    return flask.render_template('tag_index.html', tags=tags)

def tag_show(tagname):
    pastes = dict((k, htime(ts))
                  for k, ts in r.zscan('tag:%s' % tagname, 0)[1])
    if not pastes:
        return 'tag not found'
    pastes = [(k, pastes[k]) for k in sorted(pastes, key=pastes.get,
                                             reverse=True)]
    with r.pipeline() as pipe:
        for paste_uuid, ts in pastes:
            pipe.get(paste_uuid)
        paste_text_list = pipe.execute()
    return '%s\n\n\n\n%s' % (str(pastes), str(paste_text_list))
    color_list = [hilight(p) for p in paste_text_list]
    pastes = [(p[0], p[1], c) for p, c in zip(pastes, color_list)]

    return flask.render_template('tag_show.html', tagname=tagname,
                                 pastes=pastes)

def hilight(paste):
    for h in hilights:
        if h in paste:
            return hilight_color
    return 'inherit'

def paste_create():
    params = flask.request.get_json()
    data = params['data']
    tagname = params.get('tag', 'no-tag')
    paste_uuid = shortuuid.uuid()
    ts = time.time()

    with r.pipeline() as pipe:
        # add tagname to lexicographically sorted tags set
        pipe.zadd('tags', 1, tagname)
        # add paste uuid to this tag's time sorted set
        pipe.zadd('tag:%s' % tagname, ts, paste_uuid)
        # add paste uuid to the time sorted pastes set
        pipe.zadd('pastes', ts, paste_uuid)
        # add paste_uuid -> tagname mapping
        pipe.set('paste_tag:%s' % paste_uuid, tagname)
        # add the paste
        pipe.set('paste:%s' % paste_uuid, data)
        pipe.execute()

    return url() + flask.url_for('paste_show', paste_uuid=paste_uuid)

def paste_show_pretty(paste_uuid):
    tagname = r.get('paste_tag:%s' % paste_uuid)
    p = unicode(r.get('paste:%s' % paste_uuid), 'utf8')
    return flask.render_template('paste_show.html', paste_uuid=paste_uuid,
                                 paste=p, tagname=tagname)
#    return flask.Response(p, mimetype='text/plain')

def paste_show(paste_uuid):
    p = r.get('paste:%s' % paste_uuid)
    return flask.Response(p, mimetype='text/plain')

def delete_paste(paste_uuid):
    # get the tagname info related to this paste_uuid
    tagname = r.get('paste_tag:%s' % paste_uuid)
    num_pastes = r.zcard('tag:%s' % tagname)
    msg = 'delete |%s| with tag |%s| which has |%s| pastes'
    with r.pipeline() as pipe:
        # remove paste_uuid from tag's set of paste_uuids
        pipe.zrem('tag:%s' % tagname, paste_uuid)
        # remove paste_uuid from the time sorted pastes set
        pipe.zrem('pastes', paste_uuid)
        # remove paste_uuid from the paste_uuid -> tagname mapping
        pipe.delete('paste_tag:%s' % paste_uuid)
        # delete the paste itself
        pipe.delete('paste:%s' % paste_uuid)

        # if the tagname no longer has any associated paste,
        # remove it from the tags set
        if num_pastes <= 1:
            pipe.zrem('tags', tagname)
        x = pipe.execute()

    msg = ('remove paste uuid from tag |%s|\n'
           'remove paste uuid from pastes set |%s|\n'
           'remove paste uuid from paste_tag mapping |%s|\n'
           'remove the paste |%s|\n')
    if len(x) == 5:
        msg += 'remove tagname from tags |%s|'
    return '|%s| deleted' % paste_uuid

def linky(resource, s, **kwargs):
    return '%s' % (url(),
                                      flask.url_for(resource, **kwargs), s)

def htime(ts):
    return datetime.datetime.fromtimestamp(ts, pytz.utc).strftime('%a %d %b %Y'
                                                                  ' %H:%M:%S'
                                                                  ' %Z')

def url():
    app = flask.current_app
    try:
        return 'http://%s' % app.config['HOSTNAME']
    except:
        return 'http://127.0.0.1:8000'

def create_app(debug=False, *args, **kwargs):
    app = flask.Flask('paste_capsule')
    app.debug = debug
    flask_appconfig.AppConfig(app)
    flask_bootstrap.Bootstrap(app)

    app.add_url_rule('/', 'tag_index', tag_index, methods=['get'])
    app.add_url_rule('/tag/<tagname>', 'tag_show', tag_show, methods=['get'])
    app.add_url_rule('/paste', 'paste_create', paste_create, methods=['post'])
    app.add_url_rule('/paste/<paste_uuid>', 'paste_show', paste_show,
                     methods=['get'])
    app.add_url_rule('/paste/<paste_uuid>', 'delete_paste', delete_paste,
                     methods=['delete'])
    return app

if __name__ == '__main__':
    create_app().run(debug=True, host='127.0.0.1', port=8000)
<commit_msg>syntax error<commit_after>#!/usr/bin/env python
#
# Copyright 2014 Trey Morris
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
#
import redis
import time
import datetime
import shortuuid
import pytz

import flask
import flask_appconfig
import flask_bootstrap

r = redis.StrictRedis(unix_socket_path='/run/redis.sock', db=3)

###### REDIS SCHEMA ######
# lexicographically sorted set of tags
#    tags
# time sorted set of paste uuids with tag
#    tag:<tagname>
# time sorted set of pastes (for sorting in tag view and reaping later)
#    pastes
# paste -> tag map for each paste (for reaping from tag:<tagname>)
#    paste_tag:<uuid>
# each paste
#    paste:<uuid>

hilights = ['BOOM']
hilight_color = 'pink'

def tag_index():
    tag_list = r.zrange('tags', 0, -1)
    with r.pipeline() as pipe:
        for tag in tag_list:
            pipe.zcard('tag:%s' % tag)
        tag_num_list = pipe.execute()
    tags = dict(zip(tag_list, tag_num_list))
    return flask.render_template('tag_index.html', tags=tags)

def tag_show(tagname):
    pastes = dict((k, htime(ts))
                  for k, ts in r.zscan('tag:%s' % tagname, 0)[1])
    if not pastes:
        return 'tag not found'
    pastes = [(k, pastes[k]) for k in sorted(pastes, key=pastes.get,
                                             reverse=True)]
    with r.pipeline() as pipe:
        for paste_uuid, ts in pastes:
            pipe.get('paste:%s' % paste_uuid)
        paste_text_list = pipe.execute()
    color_list = [hilight(p) for p in paste_text_list]
    pastes = [(p[0], p[1], c) for p, c in zip(pastes, color_list)]

    return flask.render_template('tag_show.html', tagname=tagname,
                                 pastes=pastes)

def hilight(paste):
    for h in hilights:
        if h in paste:
            return hilight_color
    return 'inherit'

def paste_create():
    params = flask.request.get_json()
    data = params['data']
    tagname = params.get('tag', 'no-tag')
    paste_uuid = shortuuid.uuid()
    ts = time.time()

    with r.pipeline() as pipe:
        # add tagname to lexicographically sorted tags set
        pipe.zadd('tags', 1, tagname)
        # add paste uuid to this tag's time sorted set
        pipe.zadd('tag:%s' % tagname, ts, paste_uuid)
        # add paste uuid to the time sorted pastes set
        pipe.zadd('pastes', ts, paste_uuid)
        # add paste_uuid -> tagname mapping
        pipe.set('paste_tag:%s' % paste_uuid, tagname)
        # add the paste
        pipe.set('paste:%s' % paste_uuid, data)
        pipe.execute()

    return url() + flask.url_for('paste_show', paste_uuid=paste_uuid)

def paste_show_pretty(paste_uuid):
    tagname = r.get('paste_tag:%s' % paste_uuid)
    p = unicode(r.get('paste:%s' % paste_uuid), 'utf8')
    return flask.render_template('paste_show.html', paste_uuid=paste_uuid,
                                 paste=p, tagname=tagname)
#    return flask.Response(p, mimetype='text/plain')

def paste_show(paste_uuid):
    p = r.get('paste:%s' % paste_uuid)
    return flask.Response(p, mimetype='text/plain')

def delete_paste(paste_uuid):
    # get the tagname info related to this paste_uuid
    tagname = r.get('paste_tag:%s' % paste_uuid)
    num_pastes = r.zcard('tag:%s' % tagname)
    msg = 'delete |%s| with tag |%s| which has |%s| pastes'
    with r.pipeline() as pipe:
        # remove paste_uuid from tag's set of paste_uuids
        pipe.zrem('tag:%s' % tagname, paste_uuid)
        # remove paste_uuid from the time sorted pastes set
        pipe.zrem('pastes', paste_uuid)
        # remove paste_uuid from the paste_uuid -> tagname mapping
        pipe.delete('paste_tag:%s' % paste_uuid)
        # delete the paste itself
        pipe.delete('paste:%s' % paste_uuid)

        # if the tagname no longer has any associated paste,
        # remove it from the tags set
        if num_pastes <= 1:
            pipe.zrem('tags', tagname)
        x = pipe.execute()

    msg = ('remove paste uuid from tag |%s|\n'
           'remove paste uuid from pastes set |%s|\n'
           'remove paste uuid from paste_tag mapping |%s|\n'
           'remove the paste |%s|\n')
    if len(x) == 5:
        msg += 'remove tagname from tags |%s|'
    return '|%s| deleted' % paste_uuid

def linky(resource, s, **kwargs):
    return '%s' % (url(),
                                      flask.url_for(resource, **kwargs), s)

def htime(ts):
    return datetime.datetime.fromtimestamp(ts, pytz.utc).strftime('%a %d %b %Y'
                                                                  ' %H:%M:%S'
                                                                  ' %Z')

def url():
    app = flask.current_app
    try:
        return 'http://%s' % app.config['HOSTNAME']
    except:
        return 'http://127.0.0.1:8000'

def create_app(debug=False, *args, **kwargs):
    app = flask.Flask('paste_capsule')
    app.debug = debug
    flask_appconfig.AppConfig(app)
    flask_bootstrap.Bootstrap(app)

    app.add_url_rule('/', 'tag_index', tag_index, methods=['get'])
    app.add_url_rule('/tag/<tagname>', 'tag_show', tag_show, methods=['get'])
    app.add_url_rule('/paste', 'paste_create', paste_create, methods=['post'])
    app.add_url_rule('/paste/<paste_uuid>', 'paste_show', paste_show,
                     methods=['get'])
    app.add_url_rule('/paste/<paste_uuid>', 'delete_paste', delete_paste,
                     methods=['delete'])
    return app

if __name__ == '__main__':
    create_app().run(debug=True, host='127.0.0.1', port=8000)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals

import copy
import locale
import os
from os.path import abspath, dirname, join
from sys import platform

from pelican.settings import (DEFAULT_CONFIG, DEFAULT_THEME,
                              configure_settings, handle_deprecated_settings,
                              read_settings)
from pelican.tests.support import unittest

class TestSettingsConfiguration(unittest.TestCase):
    """Provided a file, it should read it, replace the default values,
    append new values to the settings (if any), and apply basic settings
    optimizations.
    """
    def setUp(self):
        self.old_locale = locale.setlocale(locale.LC_ALL)
        locale.setlocale(locale.LC_ALL, str('C'))
        self.PATH = abspath(dirname(__file__))
        default_conf = join(self.PATH, 'default_conf.py')
        self.settings = read_settings(default_conf)

    def tearDown(self):
        locale.setlocale(locale.LC_ALL, self.old_locale)

    def test_overwrite_existing_settings(self):
        self.assertEqual(self.settings.get('SITENAME'), "Alexis' log")
        self.assertEqual(
            self.settings.get('SITEURL'),
            'http://blog.notmyidea.org')

    def test_keep_default_settings(self):
        # Keep default settings if not defined.
        self.assertEqual(
            self.settings.get('DEFAULT_CATEGORY'),
            DEFAULT_CONFIG['DEFAULT_CATEGORY'])

    def test_dont_copy_small_keys(self):
        # Do not copy keys not in caps.
        self.assertNotIn('foobar', self.settings)

    def test_read_empty_settings(self):
        # Ensure an empty settings file results in default settings.
        settings = read_settings(None)
        expected = copy.deepcopy(DEFAULT_CONFIG)
        # Added by configure settings
        expected['FEED_DOMAIN'] = ''
        expected['ARTICLE_EXCLUDES'] = ['pages']
        expected['PAGE_EXCLUDES'] = ['']
        self.maxDiff = None
        self.assertDictEqual(settings, expected)

    def test_settings_return_independent(self):
        # Make sure that the results from one settings call doesn't
        # effect past or future instances.
        self.PATH = abspath(dirname(__file__))
        default_conf = join(self.PATH, 'default_conf.py')
        settings = read_settings(default_conf)
        settings['SITEURL'] = 'new-value'
        new_settings = read_settings(default_conf)
        self.assertNotEqual(new_settings['SITEURL'], settings['SITEURL'])

    def test_defaults_not_overwritten(self):
        # This assumes 'SITENAME': 'A Pelican Blog'
        settings = read_settings(None)
        settings['SITENAME'] = 'Not a Pelican Blog'
        self.assertNotEqual(settings['SITENAME'], DEFAULT_CONFIG['SITENAME'])

    def test_static_path_settings_safety(self):
        # Disallow static paths from being strings
        settings = {
            'STATIC_PATHS': 'foo/bar',
            'THEME_STATIC_PATHS': 'bar/baz',
            # These 4 settings are required to run configure_settings
            'PATH': '.',
            'THEME': DEFAULT_THEME,
            'SITEURL': 'http://blog.notmyidea.org/',
            'LOCALE': '',
        }
        configure_settings(settings)
        self.assertEqual(
            settings['STATIC_PATHS'],
            DEFAULT_CONFIG['STATIC_PATHS'])
        self.assertEqual(
            settings['THEME_STATIC_PATHS'],
            DEFAULT_CONFIG['THEME_STATIC_PATHS'])

    def test_configure_settings(self):
        # Manipulations to settings should be applied correctly.
        settings = {
            'SITEURL': 'http://blog.notmyidea.org/',
            'LOCALE': '',
            'PATH': os.curdir,
            'THEME': DEFAULT_THEME,
        }
        configure_settings(settings)

        # SITEURL should not have a trailing slash
        self.assertEqual(settings['SITEURL'], 'http://blog.notmyidea.org')

        # FEED_DOMAIN, if undefined, should default to SITEURL
        self.assertEqual(settings['FEED_DOMAIN'], 'http://blog.notmyidea.org')

        settings['FEED_DOMAIN'] = 'http://feeds.example.com'
        configure_settings(settings)
        self.assertEqual(settings['FEED_DOMAIN'], 'http://feeds.example.com')

    def test_theme_settings_exceptions(self):
        settings = self.settings

        # Check that theme lookup in "pelican/themes" functions as expected
        settings['THEME'] = os.path.split(settings['THEME'])[1]
        configure_settings(settings)
        self.assertEqual(settings['THEME'], DEFAULT_THEME)

        # Check that non-existent theme raises exception
        settings['THEME'] = 'foo'
        self.assertRaises(Exception, configure_settings, settings)

    def test_deprecated_dir_setting(self):
        settings = self.settings

        settings['ARTICLE_DIR'] = 'foo'
        settings['PAGE_DIR'] = 'bar'

        settings = handle_deprecated_settings(settings)

        self.assertEqual(settings['ARTICLE_PATHS'], ['foo'])
        self.assertEqual(settings['PAGE_PATHS'], ['bar'])

        with self.assertRaises(KeyError):
            settings['ARTICLE_DIR']
            settings['PAGE_DIR']

    @unittest.skipIf(platform == 'win32', "Doesn't work on Windows")
    def test_default_encoding(self):
        # Test that the default locale is set if not specified in settings

        # Reset locale to Python's default locale
        locale.setlocale(locale.LC_ALL, str('C'))
        self.assertEqual(self.settings['LOCALE'], DEFAULT_CONFIG['LOCALE'])

        configure_settings(self.settings)
        self.assertEqual(locale.getlocale(), locale.getdefaultlocale())

    def test_invalid_settings_throw_exception(self):
        # Test that the path name is valid

        # test that 'PATH' is set
        settings = {
        }

        self.assertRaises(Exception, configure_settings, settings)

        # Test that 'PATH' is valid
        settings['PATH'] = ''
        self.assertRaises(Exception, configure_settings, settings)

        # Test nonexistent THEME
        settings['PATH'] = os.curdir
        settings['THEME'] = 'foo'

        self.assertRaises(Exception, configure_settings, settings)

    def test_deprecated_extra_templates_paths(self):
        settings = self.settings
        settings['EXTRA_TEMPLATES_PATHS'] = ['/foo/bar', '/ha']

        settings = handle_deprecated_settings(settings)

        self.assertEqual(settings['THEME_TEMPLATES_OVERRIDES'],
                         ['/foo/bar', '/ha'])
        self.assertNotIn('EXTRA_TEMPLATES_PATHS', settings)

    def test_deprecated_paginated_direct_templates(self):
        settings = self.settings
        settings['PAGINATED_DIRECT_TEMPLATES'] = ['index', 'archives']
        settings['PAGINATED_TEMPLATES'] = {'index': 10, 'category': None}
        settings = handle_deprecated_settings(settings)
        self.assertEqual(settings['PAGINATED_TEMPLATES'],
                         {'index': 10, 'category': None, 'archives': None})
        self.assertNotIn('PAGINATED_DIRECT_TEMPLATES', settings)

    def test_deprecated_paginated_direct_templates_from_file(self):
        # This is equivalent to reading a settings file that has
        # PAGINATED_DIRECT_TEMPLATES defined but no PAGINATED_TEMPLATES.
        settings = read_settings(None, override={
            'PAGINATED_DIRECT_TEMPLATES': ['index', 'archives']
        })
        self.assertEqual(settings['PAGINATED_TEMPLATES'], {
            'archives': None,
            'author': None,
            'index': None,
            'category': None,
            'tag': None})
        self.assertNotIn('PAGINATED_DIRECT_TEMPLATES', settings)

    def test_theme_and_extra_templates_exception(self):
        settings = self.settings
        settings['EXTRA_TEMPLATES_PATHS'] = ['/ha']
        settings['THEME_TEMPLATES_OVERRIDES'] = ['/foo/bar']

        self.assertRaises(Exception, handle_deprecated_settings, settings)

    def test_slug_and_slug_regex_substitutions_exception(self):
        settings = {}
        settings['SLUG_REGEX_SUBSTITUTIONS'] = [('C++', 'cpp')]
        settings['TAG_SUBSTITUTIONS'] = [('C#', 'csharp')]

        self.assertRaises(Exception, handle_deprecated_settings, settings)

    def test_deprecated_slug_substitutions(self):
        default_slug_regex_subs = self.settings['SLUG_REGEX_SUBSTITUTIONS']

        # If no deprecated setting is set, don't set new ones
        settings = {}
        settings = handle_deprecated_settings(settings)
        self.assertNotIn('SLUG_REGEX_SUBSTITUTIONS', settings)
        self.assertNotIn('TAG_REGEX_SUBSTITUTIONS', settings)
        self.assertNotIn('CATEGORY_REGEX_SUBSTITUTIONS', settings)
        self.assertNotIn('AUTHOR_REGEX_SUBSTITUTIONS', settings)

        # If SLUG_SUBSTITUTIONS is set, set {SLUG, AUTHOR}_REGEX_SUBSTITUTIONS
        # correctly, don't set {CATEGORY, TAG}_REGEX_SUBSTITUTIONS
        settings = {}
        settings['SLUG_SUBSTITUTIONS'] = [('C++', 'cpp')]
        settings = handle_deprecated_settings(settings)
        self.assertEqual(settings.get('SLUG_REGEX_SUBSTITUTIONS'),
                         [(r'C\+\+', 'cpp')] + default_slug_regex_subs)
        self.assertNotIn('TAG_REGEX_SUBSTITUTIONS', settings)
        self.assertNotIn('CATEGORY_REGEX_SUBSTITUTIONS', settings)
        self.assertEqual(settings.get('AUTHOR_REGEX_SUBSTITUTIONS'),
                         default_slug_regex_subs)

        # If {CATEGORY, TAG, AUTHOR}_SUBSTITUTIONS are set, set
        # {CATEGORY, TAG, AUTHOR}_REGEX_SUBSTITUTIONS correctly, don't set
        # SLUG_REGEX_SUBSTITUTIONS
        settings = {}
        settings['TAG_SUBSTITUTIONS'] = [('C#', 'csharp')]
        settings['CATEGORY_SUBSTITUTIONS'] = [('C#', 'csharp')]
        settings['AUTHOR_SUBSTITUTIONS'] = [('Alexander Todorov', 'atodorov')]
        settings = handle_deprecated_settings(settings)
        self.assertNotIn('SLUG_REGEX_SUBSTITUTIONS', settings)
        self.assertEqual(settings['TAG_REGEX_SUBSTITUTIONS'],
                         [(r'C\#', 'csharp')] + default_slug_regex_subs)
        self.assertEqual(settings['CATEGORY_REGEX_SUBSTITUTIONS'],
                         [(r'C\#', 'csharp')] + default_slug_regex_subs)
        self.assertEqual(settings['AUTHOR_REGEX_SUBSTITUTIONS'],
                         [(r'Alexander\ Todorov', 'atodorov')] +
                         default_slug_regex_subs)

        # If {SLUG, CATEGORY, TAG, AUTHOR}_SUBSTITUTIONS are set, set
        # {SLUG, CATEGORY, TAG, AUTHOR}_REGEX_SUBSTITUTIONS correctly
        settings = {}
        settings['SLUG_SUBSTITUTIONS'] = [('C++', 'cpp')]
        settings['TAG_SUBSTITUTIONS'] = [('C#', 'csharp')]
        settings['CATEGORY_SUBSTITUTIONS'] = [('C#', 'csharp')]
        settings['AUTHOR_SUBSTITUTIONS'] = [('Alexander Todorov', 'atodorov')]
        settings = handle_deprecated_settings(settings)
        self.assertEqual(settings['TAG_REGEX_SUBSTITUTIONS'],
                         [(r'C\+\+', 'cpp')] + [(r'C\#', 'csharp')] +
                         default_slug_regex_subs)
        self.assertEqual(settings['CATEGORY_REGEX_SUBSTITUTIONS'],
                         [(r'C\+\+', 'cpp')] + [(r'C\#', 'csharp')] +
                         default_slug_regex_subs)
        self.assertEqual(settings['AUTHOR_REGEX_SUBSTITUTIONS'],
                         [(r'Alexander\ Todorov', 'atodorov')] +
                         default_slug_regex_subs)

        # Handle old 'skip' flags correctly
        settings = {}
        settings['SLUG_SUBSTITUTIONS'] = [('C++', 'cpp', True)]
        settings['AUTHOR_SUBSTITUTIONS'] = [('Alexander Todorov', 'atodorov',
                                             False)]
        settings = handle_deprecated_settings(settings)
        self.assertEqual(settings.get('SLUG_REGEX_SUBSTITUTIONS'),
                         [(r'C\+\+', 'cpp')] +
                         [(r'(?u)\A\s*', ''), (r'(?u)\s*\Z', '')])
        self.assertEqual(settings['AUTHOR_REGEX_SUBSTITUTIONS'],
                         [(r'Alexander\ Todorov', 'atodorov')] +
                         default_slug_regex_subs)
<commit_msg>settings: add another consistency test for SLUG_SUBSTITUTIONS.<commit_after># -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals

import copy
import locale
import os
from os.path import abspath, dirname, join
from sys import platform

from pelican.settings import (DEFAULT_CONFIG, DEFAULT_THEME,
                              configure_settings, handle_deprecated_settings,
                              read_settings)
from pelican.tests.support import unittest

class TestSettingsConfiguration(unittest.TestCase):
    """Provided a file, it should read it, replace the default values,
    append new values to the settings (if any), and apply basic settings
    optimizations.
    """
    def setUp(self):
        self.old_locale = locale.setlocale(locale.LC_ALL)
        locale.setlocale(locale.LC_ALL, str('C'))
        self.PATH = abspath(dirname(__file__))
        default_conf = join(self.PATH, 'default_conf.py')
        self.settings = read_settings(default_conf)

    def tearDown(self):
        locale.setlocale(locale.LC_ALL, self.old_locale)

    def test_overwrite_existing_settings(self):
        self.assertEqual(self.settings.get('SITENAME'), "Alexis' log")
        self.assertEqual(
            self.settings.get('SITEURL'),
            'http://blog.notmyidea.org')

    def test_keep_default_settings(self):
        # Keep default settings if not defined.
        self.assertEqual(
            self.settings.get('DEFAULT_CATEGORY'),
            DEFAULT_CONFIG['DEFAULT_CATEGORY'])

    def test_dont_copy_small_keys(self):
        # Do not copy keys not in caps.
        self.assertNotIn('foobar', self.settings)

    def test_read_empty_settings(self):
        # Ensure an empty settings file results in default settings.
        settings = read_settings(None)
        expected = copy.deepcopy(DEFAULT_CONFIG)
        # Added by configure settings
        expected['FEED_DOMAIN'] = ''
        expected['ARTICLE_EXCLUDES'] = ['pages']
        expected['PAGE_EXCLUDES'] = ['']
        self.maxDiff = None
        self.assertDictEqual(settings, expected)

    def test_settings_return_independent(self):
        # Make sure that the results from one settings call doesn't
        # effect past or future instances.
        self.PATH = abspath(dirname(__file__))
        default_conf = join(self.PATH, 'default_conf.py')
        settings = read_settings(default_conf)
        settings['SITEURL'] = 'new-value'
        new_settings = read_settings(default_conf)
        self.assertNotEqual(new_settings['SITEURL'], settings['SITEURL'])

    def test_defaults_not_overwritten(self):
        # This assumes 'SITENAME': 'A Pelican Blog'
        settings = read_settings(None)
        settings['SITENAME'] = 'Not a Pelican Blog'
        self.assertNotEqual(settings['SITENAME'], DEFAULT_CONFIG['SITENAME'])

    def test_static_path_settings_safety(self):
        # Disallow static paths from being strings
        settings = {
            'STATIC_PATHS': 'foo/bar',
            'THEME_STATIC_PATHS': 'bar/baz',
            # These 4 settings are required to run configure_settings
            'PATH': '.',
            'THEME': DEFAULT_THEME,
            'SITEURL': 'http://blog.notmyidea.org/',
            'LOCALE': '',
        }
        configure_settings(settings)
        self.assertEqual(
            settings['STATIC_PATHS'],
            DEFAULT_CONFIG['STATIC_PATHS'])
        self.assertEqual(
            settings['THEME_STATIC_PATHS'],
            DEFAULT_CONFIG['THEME_STATIC_PATHS'])

    def test_configure_settings(self):
        # Manipulations to settings should be applied correctly.
        settings = {
            'SITEURL': 'http://blog.notmyidea.org/',
            'LOCALE': '',
            'PATH': os.curdir,
            'THEME': DEFAULT_THEME,
        }
        configure_settings(settings)

        # SITEURL should not have a trailing slash
        self.assertEqual(settings['SITEURL'], 'http://blog.notmyidea.org')

        # FEED_DOMAIN, if undefined, should default to SITEURL
        self.assertEqual(settings['FEED_DOMAIN'], 'http://blog.notmyidea.org')

        settings['FEED_DOMAIN'] = 'http://feeds.example.com'
        configure_settings(settings)
        self.assertEqual(settings['FEED_DOMAIN'], 'http://feeds.example.com')

    def test_theme_settings_exceptions(self):
        settings = self.settings

        # Check that theme lookup in "pelican/themes" functions as expected
        settings['THEME'] = os.path.split(settings['THEME'])[1]
        configure_settings(settings)
        self.assertEqual(settings['THEME'], DEFAULT_THEME)

        # Check that non-existent theme raises exception
        settings['THEME'] = 'foo'
        self.assertRaises(Exception, configure_settings, settings)

    def test_deprecated_dir_setting(self):
        settings = self.settings

        settings['ARTICLE_DIR'] = 'foo'
        settings['PAGE_DIR'] = 'bar'

        settings = handle_deprecated_settings(settings)

        self.assertEqual(settings['ARTICLE_PATHS'], ['foo'])
        self.assertEqual(settings['PAGE_PATHS'], ['bar'])

        with self.assertRaises(KeyError):
            settings['ARTICLE_DIR']
            settings['PAGE_DIR']

    @unittest.skipIf(platform == 'win32', "Doesn't work on Windows")
    def test_default_encoding(self):
        # Test that the default locale is set if not specified in settings

        # Reset locale to Python's default locale
        locale.setlocale(locale.LC_ALL, str('C'))
        self.assertEqual(self.settings['LOCALE'], DEFAULT_CONFIG['LOCALE'])

        configure_settings(self.settings)
        self.assertEqual(locale.getlocale(), locale.getdefaultlocale())

    def test_invalid_settings_throw_exception(self):
        # Test that the path name is valid

        # test that 'PATH' is set
        settings = {
        }

        self.assertRaises(Exception, configure_settings, settings)

        # Test that 'PATH' is valid
        settings['PATH'] = ''
        self.assertRaises(Exception, configure_settings, settings)

        # Test nonexistent THEME
        settings['PATH'] = os.curdir
        settings['THEME'] = 'foo'

        self.assertRaises(Exception, configure_settings, settings)

    def test_deprecated_extra_templates_paths(self):
        settings = self.settings
        settings['EXTRA_TEMPLATES_PATHS'] = ['/foo/bar', '/ha']

        settings = handle_deprecated_settings(settings)

        self.assertEqual(settings['THEME_TEMPLATES_OVERRIDES'],
                         ['/foo/bar', '/ha'])
        self.assertNotIn('EXTRA_TEMPLATES_PATHS', settings)

    def test_deprecated_paginated_direct_templates(self):
        settings = self.settings
        settings['PAGINATED_DIRECT_TEMPLATES'] = ['index', 'archives']
        settings['PAGINATED_TEMPLATES'] = {'index': 10, 'category': None}
        settings = handle_deprecated_settings(settings)
        self.assertEqual(settings['PAGINATED_TEMPLATES'],
                         {'index': 10, 'category': None, 'archives': None})
        self.assertNotIn('PAGINATED_DIRECT_TEMPLATES', settings)

    def test_deprecated_paginated_direct_templates_from_file(self):
        # This is equivalent to reading a settings file that has
        # PAGINATED_DIRECT_TEMPLATES defined but no PAGINATED_TEMPLATES.
        settings = read_settings(None, override={
            'PAGINATED_DIRECT_TEMPLATES': ['index', 'archives']
        })
        self.assertEqual(settings['PAGINATED_TEMPLATES'], {
            'archives': None,
            'author': None,
            'index': None,
            'category': None,
            'tag': None})
        self.assertNotIn('PAGINATED_DIRECT_TEMPLATES', settings)

    def test_theme_and_extra_templates_exception(self):
        settings = self.settings
        settings['EXTRA_TEMPLATES_PATHS'] = ['/ha']
        settings['THEME_TEMPLATES_OVERRIDES'] = ['/foo/bar']

        self.assertRaises(Exception, handle_deprecated_settings, settings)

    def test_slug_and_slug_regex_substitutions_exception(self):
        settings = {}
        settings['SLUG_REGEX_SUBSTITUTIONS'] = [('C++', 'cpp')]
        settings['TAG_SUBSTITUTIONS'] = [('C#', 'csharp')]

        self.assertRaises(Exception, handle_deprecated_settings, settings)

    def test_deprecated_slug_substitutions(self):
        default_slug_regex_subs = self.settings['SLUG_REGEX_SUBSTITUTIONS']

        # If no deprecated setting is set, don't set new ones
        settings = {}
        settings = handle_deprecated_settings(settings)
        self.assertNotIn('SLUG_REGEX_SUBSTITUTIONS', settings)
        self.assertNotIn('TAG_REGEX_SUBSTITUTIONS', settings)
        self.assertNotIn('CATEGORY_REGEX_SUBSTITUTIONS', settings)
        self.assertNotIn('AUTHOR_REGEX_SUBSTITUTIONS', settings)

        # If SLUG_SUBSTITUTIONS is set, set {SLUG, AUTHOR}_REGEX_SUBSTITUTIONS
        # correctly, don't set {CATEGORY, TAG}_REGEX_SUBSTITUTIONS
        settings = {}
        settings['SLUG_SUBSTITUTIONS'] = [('C++', 'cpp')]
        settings = handle_deprecated_settings(settings)
        self.assertEqual(settings.get('SLUG_REGEX_SUBSTITUTIONS'),
                         [(r'C\+\+', 'cpp')] + default_slug_regex_subs)
        self.assertNotIn('TAG_REGEX_SUBSTITUTIONS', settings)
        self.assertNotIn('CATEGORY_REGEX_SUBSTITUTIONS', settings)
        self.assertEqual(settings.get('AUTHOR_REGEX_SUBSTITUTIONS'),
                         default_slug_regex_subs)

        # If {CATEGORY, TAG, AUTHOR}_SUBSTITUTIONS are set, set
        # {CATEGORY, TAG, AUTHOR}_REGEX_SUBSTITUTIONS correctly, don't set
        # SLUG_REGEX_SUBSTITUTIONS
        settings = {}
        settings['TAG_SUBSTITUTIONS'] = [('C#', 'csharp')]
        settings['CATEGORY_SUBSTITUTIONS'] = [('C#', 'csharp')]
        settings['AUTHOR_SUBSTITUTIONS'] = [('Alexander Todorov', 'atodorov')]
        settings = handle_deprecated_settings(settings)
        self.assertNotIn('SLUG_REGEX_SUBSTITUTIONS', settings)
        self.assertEqual(settings['TAG_REGEX_SUBSTITUTIONS'],
                         [(r'C\#', 'csharp')] + default_slug_regex_subs)
        self.assertEqual(settings['CATEGORY_REGEX_SUBSTITUTIONS'],
                         [(r'C\#', 'csharp')] + default_slug_regex_subs)
        self.assertEqual(settings['AUTHOR_REGEX_SUBSTITUTIONS'],
                         [(r'Alexander\ Todorov', 'atodorov')] +
                         default_slug_regex_subs)

        # If {SLUG, CATEGORY, TAG, AUTHOR}_SUBSTITUTIONS are set, set
        # {SLUG, CATEGORY, TAG, AUTHOR}_REGEX_SUBSTITUTIONS correctly
        settings = {}
        settings['SLUG_SUBSTITUTIONS'] = [('C++', 'cpp')]
        settings['TAG_SUBSTITUTIONS'] = [('C#', 'csharp')]
        settings['CATEGORY_SUBSTITUTIONS'] = [('C#', 'csharp')]
        settings['AUTHOR_SUBSTITUTIONS'] = [('Alexander Todorov', 'atodorov')]
        settings = handle_deprecated_settings(settings)
        self.assertEqual(settings['TAG_REGEX_SUBSTITUTIONS'],
                         [(r'C\+\+', 'cpp')] + [(r'C\#', 'csharp')] +
                         default_slug_regex_subs)
        self.assertEqual(settings['CATEGORY_REGEX_SUBSTITUTIONS'],
                         [(r'C\+\+', 'cpp')] + [(r'C\#', 'csharp')] +
                         default_slug_regex_subs)
        self.assertEqual(settings['AUTHOR_REGEX_SUBSTITUTIONS'],
                         [(r'Alexander\ Todorov', 'atodorov')] +
                         default_slug_regex_subs)

        # Handle old 'skip' flags correctly
        settings = {}
        settings['SLUG_SUBSTITUTIONS'] = [('C++', 'cpp', True)]
        settings['AUTHOR_SUBSTITUTIONS'] = [('Alexander Todorov', 'atodorov',
                                             False)]
        settings = handle_deprecated_settings(settings)
        self.assertEqual(settings.get('SLUG_REGEX_SUBSTITUTIONS'),
                         [(r'C\+\+', 'cpp')] +
                         [(r'(?u)\A\s*', ''), (r'(?u)\s*\Z', '')])
        self.assertEqual(settings['AUTHOR_REGEX_SUBSTITUTIONS'],
                         [(r'Alexander\ Todorov', 'atodorov')] +
                         default_slug_regex_subs)

    def test_deprecated_slug_substitutions_from_file(self):
        # This is equivalent to reading a settings file that has
        # SLUG_SUBSTITUTIONS defined but no SLUG_REGEX_SUBSTITUTIONS.
        settings = read_settings(None, override={
            'SLUG_SUBSTITUTIONS': [('C++', 'cpp')]
        })
        self.assertEqual(settings['SLUG_REGEX_SUBSTITUTIONS'],
                         [(r'C\+\+', 'cpp')] +
                         self.settings['SLUG_REGEX_SUBSTITUTIONS'])
        self.assertNotIn('SLUG_SUBSTITUTIONS', settings)
<|endoftext|>


<commit_before>import numpy as np
import tensorflow as tf
from cleverhans.utils_tf import infer_devices

def run_canary():
  """
  Runs some code that will crash if the GPUs / GPU driver are suffering from
  a common bug. This helps to prevent contaminating results in the rest of
  the library with incorrect calculations.
  """

  # Note: please do not edit this function unless you have access to a machine
  # with GPUs suffering from the bug and can verify that the canary still
  # crashes after your edits. Due to the transient nature of the GPU bug it is
  # not possible to unit test the canary in our continuous integration system.

  # Try very hard not to let the canary affect the graph for the rest of the
  # python process
  canary_graph = tf.Graph()
  with canary_graph.as_default():
    devices = infer_devices()
    num_devices = len(devices)
    if num_devices < 3:
      # We have never observed GPU failure when less than 3 GPUs were used
      return

    v = np.random.RandomState([2018, 10, 16]).randn(2, 2)
    # Try very hard not to let this Variable end up in any collections used
    # by the rest of the python process
    w = tf.Variable(v, trainable=False, collections=[])
    loss = tf.reduce_sum(tf.square(w))

    grads = []
    for device in devices:
      with tf.device(device):
        grad, = tf.gradients(loss, w)
        grads.append(grad)

    sess = tf.Session()
    sess.run(tf.variables_initializer([w]))
    grads = sess.run(grads)
    first = grads[0]
    for grad in grads[1:]:
      if not np.allclose(first, grad):
        # pylint can't see when we use variables via locals()
        # pylint: disable=unused-variable,possibly-unused-variable
        first_string = str(first)
        grad_string = str(grad)
        raise RuntimeError("Something is wrong with your GPUs or GPU driver."
                           "%(num_devices)d different GPUS were asked to "
                           "calculate the same 2x2 gradient. One returned "
                           "%(first_string)s and another returned "
                           "%(grad_string)s. This can usually be fixed by "
                           "rebooting the machine." % locals())
    sess.close()

if __name__ == "__main__":
  run_canary()
<commit_msg>pylint<commit_after>import numpy as np
import tensorflow as tf
from cleverhans.utils_tf import infer_devices

def run_canary():
  """
  Runs some code that will crash if the GPUs / GPU driver are suffering from
  a common bug. This helps to prevent contaminating results in the rest of
  the library with incorrect calculations.
  """

  # Note: please do not edit this function unless you have access to a machine
  # with GPUs suffering from the bug and can verify that the canary still
  # crashes after your edits. Due to the transient nature of the GPU bug it is
  # not possible to unit test the canary in our continuous integration system.

  # Try very hard not to let the canary affect the graph for the rest of the
  # python process
  canary_graph = tf.Graph()
  with canary_graph.as_default():
    devices = infer_devices()
    num_devices = len(devices)
    if num_devices < 3:
      # We have never observed GPU failure when less than 3 GPUs were used
      return

    v = np.random.RandomState([2018, 10, 16]).randn(2, 2)
    # Try very hard not to let this Variable end up in any collections used
    # by the rest of the python process
    w = tf.Variable(v, trainable=False, collections=[])
    loss = tf.reduce_sum(tf.square(w))

    grads = []
    for device in devices:
      with tf.device(device):
        grad, = tf.gradients(loss, w)
        grads.append(grad)

    sess = tf.Session()
    sess.run(tf.variables_initializer([w]))
    grads = sess.run(grads)
    first = grads[0]
    for grad in grads[1:]:
      if not np.allclose(first, grad):
        first_string = str(first)
        grad_string = str(grad)
        raise RuntimeError("Something is wrong with your GPUs or GPU driver."
                           "%(num_devices)d different GPUS were asked to "
                           "calculate the same 2x2 gradient. One returned "
                           "%(first_string)s and another returned "
                           "%(grad_string)s. This can usually be fixed by "
                           "rebooting the machine." %
                           {"num_devices" : num_devices,
                            "first_string" : first_string,
                            "grad_string" : grad_string})
    sess.close()

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


<commit_before># -*- coding: utf-8 -*-
from cms.compat import get_user_model, user_related_query_name
from cms.exceptions import NoPermissionsException
from cms.models import Page, PagePermission, GlobalPagePermission
from cms.plugin_pool import plugin_pool
from cms.utils import get_cms_setting
from django.conf import settings
from django.contrib.auth.models import Group
from django.contrib.sites.models import Site
from django.db.models import Q

try:
    from threading import local
except ImportError:
    from django.utils._threading_local import local

# thread local support
_thread_locals = local()

def set_current_user(user):
    """
    Assigns current user from request to thread_locals, used by
    CurrentUserMiddleware.
    """
    _thread_locals.user = user

def get_current_user():
    """
    Returns current user, or None
    """
    return getattr(_thread_locals, 'user', None)

def has_page_add_permission(request):
    """
    Return true if the current user has permission to add a new page. This is
    just used for general add buttons - only superuser, or user with can_add in
    globalpagepermission can add page.

    Special case occur when page is going to be added from add page button in
    change list - then we have target and position there, so check if user can
    add page under target page will occur.
    """
    opts = Page._meta
    if request.user.is_superuser:
        return True

    # if add under page
    target = request.GET.get('target', None)
    position = request.GET.get('position', None)

    if target is not None:
        try:
            page = Page.objects.get(pk=target)
        except Page.DoesNotExist:
            return False
        global_add_perm = GlobalPagePermission.objects.user_has_add_permission(
            request.user, site).exists()
        if (request.user.has_perm(opts.app_label + '.' + opts.get_add_permission())
                and global_add_perm):
            return True
        if position in ("first-child", "last-child"):
            return page.has_add_permission(request)
        elif position in ("left", "right"):
            if page.parent_id:
                return has_generic_permission(page.parent_id, request.user, "add", page.site)
    else:
        from cms.utils.plugins import current_site
        site = current_site(request)
        global_add_perm = GlobalPagePermission.objects.user_has_add_permission(
            request.user, site).exists()
        if (request.user.has_perm(opts.app_label + '.' + opts.get_add_permission())
                and global_add_perm):
            return True
    return False

def has_any_page_change_permissions(request):
    from cms.utils.plugins import current_site
    if not request.user.is_authenticated():
        return False
    return request.user.is_superuser or PagePermission.objects.filter(
            page__site=current_site(request)
        ).filter((
            Q(user=request.user) |
            Q(group__in=request.user.groups.all())
        )).exists()

def has_page_change_permission(request):
    """
    Return true if the current user has permission to change this page.
    To be granted this permission, you need the cms.change_page permission.
    In addition, if CMS_PERMISSION is enabled you also need to either have
    global can_change permission or just on this page.
    """
    from cms.utils.plugins import current_site
    opts = Page._meta
    site = current_site(request)
    global_change_perm = GlobalPagePermission.objects.user_has_change_permission(
        request.user, site).exists()
    return request.user.is_superuser or (
        request.user.has_perm(opts.app_label + '.' + opts.get_change_permission())
        and global_change_perm or has_any_page_change_permissions(request))

def has_global_page_permission(request, site=None, **filters):
    """
    A helper function to check for global page permissions for the current user
    and site. Caches the result on a request basis, so multiple calls to this
    function inside of one request/response cycle only generate one query.

    :param request: the Request object
    :param site: the Site object or ID
    :param filters: queryset filters, e.g. ``can_add = True``
    :return: ``True`` or ``False``
    """
    if request.user.is_superuser:
        return True
    if not hasattr(request, '_cms_global_perms'):
        request._cms_global_perms = {}
    key = tuple((k, v) for k, v in filters.items())
    if site:
        key = (('site', site.pk if hasattr(site, 'pk') else int(site)),) + key
    if key not in request._cms_global_perms:
        qs = GlobalPagePermission.objects.with_user(request.user).filter(**filters)
        if site:
            qs = qs.filter(Q(sites__in=[site]) | Q(sites__isnull=True))
        request._cms_global_perms[key] = qs.exists()
    return request._cms_global_perms[key]

def get_any_page_view_permissions(request, page):
    """
    Used by the admin template tag is_restricted
    """
    return PagePermission.objects.for_page(page=page).filter(can_view=True)

def get_user_permission_level(user):
    """
    Returns highest user level from the page/permission hierarchy on which
    user haves can_change_permission. Also takes look into user groups. Higher
    level equals to lover number. Users on top of hierarchy have level 0. Level
    is the same like page.level attribute.

    Example:
                              A,W                    level 0
                            /    \
                          user    B,GroupE           level 1
                        /     \
                      C,X     D,Y,W                  level 2

        Users A, W have user level 0. GroupE and all his users have user level 1
        If user D is a member of GroupE, his user level will be 1, otherwise is
        2.

    """
    if (user.is_superuser or
            GlobalPagePermission.objects.with_can_change_permissions(user).exists()):
        # those
        return 0
    try:
        permission = PagePermission.objects.with_can_change_permissions(user).order_by('page__level')[0]
    except IndexError:
        # user isn't assigned to any node
        raise NoPermissionsException
    return permission.page.level

def get_subordinate_users(user):
    """
    Returns users queryset, containing all subordinate users to given user
    including users created by given user and not assigned to any page.

    Not assigned users must be returned, because they shouldn't get lost, and
    user should still have possibility to see them.

    Only users created_by given user which are on the same, or lover level are
    returned.

    If user haves global permissions or is a superuser, then he can see all the
    users.

    This function is currently used in PagePermissionInlineAdminForm for limit
    users in permission combobox.

    Example:
                              A,W                    level 0
                            /    \
                          user    B,GroupE           level 1
                Z       /     \
                      C,X     D,Y,W                  level 2

        Rules: W was created by user, Z was created by user, but is not assigned
        to any page.

        Will return [user, C, X, D, Y, Z]. W was created by user, but is also
        assigned to higher level.
    """

    # TODO: try to merge with PagePermissionManager.subordinate_to_user()

    if user.is_superuser or \
            GlobalPagePermission.objects.with_can_change_permissions(user):
        return get_user_model().objects.all()
    site = Site.objects.get_current()
    page_id_allow_list = Page.permissions.get_change_permissions_id_list(user, site)
    try:
        user_level = get_user_permission_level(user)
    except NoPermissionsException:
        # no permission so only staff and no page permissions
        qs = get_user_model().objects.distinct().filter(
                Q(is_staff=True) &
                Q(pageuser__created_by=user) &
                Q(pagepermission__page=None)
        )
        qs = qs.exclude(pk=user.id).exclude(groups__user__pk=user.id)
        return qs
    # normal query
    qs = get_user_model().objects.distinct().filter(
        Q(is_staff=True) &
        (Q(pagepermission__page__id__in=page_id_allow_list) & Q(pagepermission__page__level__gte=user_level))
        | (Q(pageuser__created_by=user) & Q(pagepermission__page=None))
    )
    qs = qs.exclude(pk=user.id).exclude(groups__user__pk=user.id)
    return qs

def get_subordinate_groups(user):
    """
    Similar to get_subordinate_users, but returns queryset of Groups instead
    of Users.
    """
    if (user.is_superuser or
            GlobalPagePermission.objects.with_can_change_permissions(user)):
        return Group.objects.all()
    site = Site.objects.get_current()
    page_id_allow_list = Page.permissions.get_change_permissions_id_list(user, site)
    try:
        user_level = get_user_permission_level(user)
    except NoPermissionsException:
        # no permission no records
        # page_id_allow_list is empty
        qs = Group.objects.distinct().filter(
         Q(pageusergroup__created_by=user) &
         Q(pagepermission__page=None)
        )
        return qs

    qs = Group.objects.distinct().filter(
         (Q(pagepermission__page__id__in=page_id_allow_list) & Q(pagepermission__page__level__gte=user_level))
        | (Q(pageusergroup__created_by=user) & Q(pagepermission__page=None))
    )
    return qs

def has_global_change_permissions_permission(request):
    opts = GlobalPagePermission._meta
    user = request.user
    if user.is_superuser or (
        user.has_perm(opts.app_label + '.' + opts.get_change_permission()) and
        has_global_page_permission(request, can_change=True)):
        return True
    return False

def has_generic_permission(page_id, user, attr, site):
    """
    Permission getter for single page with given id.
    Internally, this calls a method on PagePermissionsPermissionManager
    """
    func = getattr(Page.permissions, "get_%s_id_list" % attr)
    permission = func(user, site)
    return permission == Page.permissions.GRANT_ALL or page_id in permission

def get_user_sites_queryset(user):
    """
    Returns queryset of all sites available for given user.

    1.  For superuser always returns all sites.
    2.  For global user returns all sites he haves in global page permissions
        together with any sites he is assigned to over an page.
    3.  For standard user returns just sites he is assigned to over pages.
    """
    qs = Site.objects.all()

    if user.is_superuser:
        return qs

    global_ids = GlobalPagePermission.objects.with_user(user).filter(
        Q(can_add=True) | Q(can_change=True)
    ).values_list('id', flat=True)

    query = Q()
    if global_ids:
        query = Q(globalpagepermission__id__in=global_ids)
        # haves some global permissions assigned
        if not qs.filter(query).exists():
            # haves global permissions, but none of sites is specified,
            # so he haves access to all sites
            return qs
    # add some pages if he has permission to add / change them
    user_query = dict()
    user_query['djangocms_pages__pagepermission__group__'+user_related_query_name] = user
    query |= Q(Q(djangocms_pages__pagepermission__user=user) | Q(**user_query)) & \
        (Q(Q(djangocms_pages__pagepermission__can_add=True) | Q(djangocms_pages__pagepermission__can_change=True)))
    return qs.filter(query).distinct()

def has_plugin_permission(user, plugin_type, permission_type):
    """
    Checks that a user has permissions for the plugin-type given to perform
    the action defined in permission_type
    permission_type should be 'add', 'change' or 'delete'.
    """
    plugin_class = plugin_pool.get_plugin(plugin_type)
    plugin_model = plugin_class.model
    plugin_opts = plugin_model._meta
    return user.has_perm('%s.%s_%s' % (plugin_opts.app_label, permission_type,
                                      plugin_opts.object_name.lower()))
<commit_msg>fixed site not being defined<commit_after># -*- coding: utf-8 -*-
from django.contrib.auth.models import Group
from django.contrib.sites.models import Site
from django.db.models import Q

from cms.compat import get_user_model, user_related_query_name
from cms.exceptions import NoPermissionsException
from cms.models import Page, PagePermission, GlobalPagePermission
from cms.plugin_pool import plugin_pool

try:
    from threading import local
except ImportError:
    from django.utils._threading_local import local

# thread local support
_thread_locals = local()

def set_current_user(user):
    """
    Assigns current user from request to thread_locals, used by
    CurrentUserMiddleware.
    """
    _thread_locals.user = user

def get_current_user():
    """
    Returns current user, or None
    """
    return getattr(_thread_locals, 'user', None)

def has_page_add_permission(request):
    """
    Return true if the current user has permission to add a new page. This is
    just used for general add buttons - only superuser, or user with can_add in
    globalpagepermission can add page.

    Special case occur when page is going to be added from add page button in
    change list - then we have target and position there, so check if user can
    add page under target page will occur.
    """
    opts = Page._meta
    if request.user.is_superuser:
        return True

    # if add under page
    target = request.GET.get('target', None)
    position = request.GET.get('position', None)

    from cms.utils.plugins import current_site
    site = current_site(request)

    if target is not None:
        try:
            page = Page.objects.get(pk=target)
        except Page.DoesNotExist:
            return False
        global_add_perm = GlobalPagePermission.objects.user_has_add_permission(
            request.user, site).exists()
        if (request.user.has_perm(opts.app_label + '.' + opts.get_add_permission())
                and global_add_perm):
            return True
        if position in ("first-child", "last-child"):
            return page.has_add_permission(request)
        elif position in ("left", "right"):
            if page.parent_id:
                return has_generic_permission(page.parent_id, request.user, "add", page.site)
    else:
        global_add_perm = GlobalPagePermission.objects.user_has_add_permission(
            request.user, site).exists()
        if (request.user.has_perm(opts.app_label + '.' + opts.get_add_permission())
                and global_add_perm):
            return True
    return False

def has_any_page_change_permissions(request):
    from cms.utils.plugins import current_site
    if not request.user.is_authenticated():
        return False
    return request.user.is_superuser or PagePermission.objects.filter(
            page__site=current_site(request)
        ).filter((
            Q(user=request.user) |
            Q(group__in=request.user.groups.all())
        )).exists()

def has_page_change_permission(request):
    """
    Return true if the current user has permission to change this page.
    To be granted this permission, you need the cms.change_page permission.
    In addition, if CMS_PERMISSION is enabled you also need to either have
    global can_change permission or just on this page.
    """
    from cms.utils.plugins import current_site
    opts = Page._meta
    site = current_site(request)
    global_change_perm = GlobalPagePermission.objects.user_has_change_permission(
        request.user, site).exists()
    return request.user.is_superuser or (
        request.user.has_perm(opts.app_label + '.' + opts.get_change_permission())
        and global_change_perm or has_any_page_change_permissions(request))

def has_global_page_permission(request, site=None, **filters):
    """
    A helper function to check for global page permissions for the current user
    and site. Caches the result on a request basis, so multiple calls to this
    function inside of one request/response cycle only generate one query.

    :param request: the Request object
    :param site: the Site object or ID
    :param filters: queryset filters, e.g. ``can_add = True``
    :return: ``True`` or ``False``
    """
    if request.user.is_superuser:
        return True
    if not hasattr(request, '_cms_global_perms'):
        request._cms_global_perms = {}
    key = tuple((k, v) for k, v in filters.items())
    if site:
        key = (('site', site.pk if hasattr(site, 'pk') else int(site)),) + key
    if key not in request._cms_global_perms:
        qs = GlobalPagePermission.objects.with_user(request.user).filter(**filters)
        if site:
            qs = qs.filter(Q(sites__in=[site]) | Q(sites__isnull=True))
        request._cms_global_perms[key] = qs.exists()
    return request._cms_global_perms[key]

def get_any_page_view_permissions(request, page):
    """
    Used by the admin template tag is_restricted
    """
    return PagePermission.objects.for_page(page=page).filter(can_view=True)

def get_user_permission_level(user):
    """
    Returns highest user level from the page/permission hierarchy on which
    user haves can_change_permission. Also takes look into user groups. Higher
    level equals to lover number. Users on top of hierarchy have level 0. Level
    is the same like page.level attribute.

    Example:
                              A,W                    level 0
                            /    \
                          user    B,GroupE           level 1
                        /     \
                      C,X     D,Y,W                  level 2

        Users A, W have user level 0. GroupE and all his users have user level 1
        If user D is a member of GroupE, his user level will be 1, otherwise is
        2.

    """
    if (user.is_superuser or
            GlobalPagePermission.objects.with_can_change_permissions(user).exists()):
        # those
        return 0
    try:
        permission = PagePermission.objects.with_can_change_permissions(user).order_by('page__level')[0]
    except IndexError:
        # user isn't assigned to any node
        raise NoPermissionsException
    return permission.page.level

def get_subordinate_users(user):
    """
    Returns users queryset, containing all subordinate users to given user
    including users created by given user and not assigned to any page.

    Not assigned users must be returned, because they shouldn't get lost, and
    user should still have possibility to see them.

    Only users created_by given user which are on the same, or lover level are
    returned.

    If user haves global permissions or is a superuser, then he can see all the
    users.

    This function is currently used in PagePermissionInlineAdminForm for limit
    users in permission combobox.

    Example:
                              A,W                    level 0
                            /    \
                          user    B,GroupE           level 1
                Z       /     \
                      C,X     D,Y,W                  level 2

        Rules: W was created by user, Z was created by user, but is not assigned
        to any page.

        Will return [user, C, X, D, Y, Z]. W was created by user, but is also
        assigned to higher level.
    """

    # TODO: try to merge with PagePermissionManager.subordinate_to_user()

    if user.is_superuser or \
            GlobalPagePermission.objects.with_can_change_permissions(user):
        return get_user_model().objects.all()
    site = Site.objects.get_current()
    page_id_allow_list = Page.permissions.get_change_permissions_id_list(user, site)
    try:
        user_level = get_user_permission_level(user)
    except NoPermissionsException:
        # no permission so only staff and no page permissions
        qs = get_user_model().objects.distinct().filter(
                Q(is_staff=True) &
                Q(pageuser__created_by=user) &
                Q(pagepermission__page=None)
        )
        qs = qs.exclude(pk=user.id).exclude(groups__user__pk=user.id)
        return qs
    # normal query
    qs = get_user_model().objects.distinct().filter(
        Q(is_staff=True) &
        (Q(pagepermission__page__id__in=page_id_allow_list) & Q(pagepermission__page__level__gte=user_level))
        | (Q(pageuser__created_by=user) & Q(pagepermission__page=None))
    )
    qs = qs.exclude(pk=user.id).exclude(groups__user__pk=user.id)
    return qs

def get_subordinate_groups(user):
    """
    Similar to get_subordinate_users, but returns queryset of Groups instead
    of Users.
    """
    if (user.is_superuser or
            GlobalPagePermission.objects.with_can_change_permissions(user)):
        return Group.objects.all()
    site = Site.objects.get_current()
    page_id_allow_list = Page.permissions.get_change_permissions_id_list(user, site)
    try:
        user_level = get_user_permission_level(user)
    except NoPermissionsException:
        # no permission no records
        # page_id_allow_list is empty
        qs = Group.objects.distinct().filter(
         Q(pageusergroup__created_by=user) &
         Q(pagepermission__page=None)
        )
        return qs

    qs = Group.objects.distinct().filter(
         (Q(pagepermission__page__id__in=page_id_allow_list) & Q(pagepermission__page__level__gte=user_level))
        | (Q(pageusergroup__created_by=user) & Q(pagepermission__page=None))
    )
    return qs

def has_global_change_permissions_permission(request):
    opts = GlobalPagePermission._meta
    user = request.user
    if user.is_superuser or (
        user.has_perm(opts.app_label + '.' + opts.get_change_permission()) and
        has_global_page_permission(request, can_change=True)):
        return True
    return False

def has_generic_permission(page_id, user, attr, site):
    """
    Permission getter for single page with given id.
    Internally, this calls a method on PagePermissionsPermissionManager
    """
    func = getattr(Page.permissions, "get_%s_id_list" % attr)
    permission = func(user, site)
    return permission == Page.permissions.GRANT_ALL or page_id in permission

def get_user_sites_queryset(user):
    """
    Returns queryset of all sites available for given user.

    1.  For superuser always returns all sites.
    2.  For global user returns all sites he haves in global page permissions
        together with any sites he is assigned to over an page.
    3.  For standard user returns just sites he is assigned to over pages.
    """
    qs = Site.objects.all()

    if user.is_superuser:
        return qs

    global_ids = GlobalPagePermission.objects.with_user(user).filter(
        Q(can_add=True) | Q(can_change=True)
    ).values_list('id', flat=True)

    query = Q()
    if global_ids:
        query = Q(globalpagepermission__id__in=global_ids)
        # haves some global permissions assigned
        if not qs.filter(query).exists():
            # haves global permissions, but none of sites is specified,
            # so he haves access to all sites
            return qs
    # add some pages if he has permission to add / change them
    user_query = dict()
    user_query['djangocms_pages__pagepermission__group__'+user_related_query_name] = user
    query |= Q(Q(djangocms_pages__pagepermission__user=user) | Q(**user_query)) & \
        (Q(Q(djangocms_pages__pagepermission__can_add=True) | Q(djangocms_pages__pagepermission__can_change=True)))
    return qs.filter(query).distinct()

def has_plugin_permission(user, plugin_type, permission_type):
    """
    Checks that a user has permissions for the plugin-type given to perform
    the action defined in permission_type
    permission_type should be 'add', 'change' or 'delete'.
    """
    plugin_class = plugin_pool.get_plugin(plugin_type)
    plugin_model = plugin_class.model
    plugin_opts = plugin_model._meta
    return user.has_perm('%s.%s_%s' % (plugin_opts.app_label, permission_type,
                                      plugin_opts.object_name.lower()))
<|endoftext|>