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

"""

    # TODO
    # - featured members (i don't think we have filters for them yet)
    #   - that we cannot block a featured member
    # - test for failure of post by non-member / blocked user
    # - asset deletion failure by a non-creator, non-admin user
    # - comment deletion failure by non-commenter user

Input test data should have this form:

    testdata = {
        'configuration': {
            'backend_url': '...',
            'oauth_consumer_key': '...',
            'oauth_consumer_secret': '...',
            'cookies': { 'cookie_name': 'value' }
        },
        'admin': {
            'xid': '...',
            'oauth_key': '...',
            'oauth_secret': '...'
        },
        'member': {
            'xid': '...',
            'oauth_key': '...',
            'oauth_secret': '...'
        },
        'blocked': {
            'xid': '...',
            'oauth_key': '...',
            'oauth_secret': '...',
        },
        'featured': {
            'xid': '...',
            'oauth_key': '...',
            'oauth_secret': '...',
        },
        'group': {
            'xid': '...',
            'name': '...'
            'oauth_key': '...',
            'oauth_secret': '...'
        }
    }

    the member should follow admin
    the admin should follow member

    the member should have 2 or more elsewhere accounts

    'blocked' identifies a member who will become blocked by the
    test suite

Numbering prefix scheme for tests.
Some tests should be run in a specific order. The only way to do this
is through the test method name, as tests are run in alphabetic order.

    0 - POSTs for setting up data for tests

    1 - GET requests, relying on test data as described above.

    2 - Relationship test to unblock the blocked member
    3 - Test to (re-)block the user who was blocked to begin with

    4 - PUT requests

    5 - POST requests for parent objects (assets)
    6 - POST requests for child objects (favorites, comments)

    6z - HEAD, OPTIONS requests made after POSTs but before DELETEs

    7 - DELETE requests for child objects (favorites, comments)
    8 - DELETE requests for top-level objects (assets)

    9 - DELETE for remaining assets (final cleanup)

"""


import base64
import cgi
import httplib
import logging
import os
from pprint import pprint
import re
from StringIO import StringIO
import time
import unittest
from urllib import urlencode, unquote
from urlparse import urlsplit, urlunsplit, urlparse

import httplib2
import nose
import nose.plugins.attrib
import nose.tools
from oauth import oauth
from remoteobjects.http import HttpObject
import simplejson as json

import typepad


def load_test_data():
    filename = os.getenv('TEST_TYPEPAD_JSON')
    if filename is None:
        raise nose.SkipTest('no test data provided')
    f = open(filename, 'r')
    s = f.read()
    f.close()
    return json.loads(s)


def setUpModule():
    global testdata
    testdata = load_test_data()
    typepad.client.endpoint = testdata['configuration']['backend_url']
    testdata['assets'] = []
    testdata['assets_created'] = []
    testdata['comments_created'] = []
    if 'coookies' in testdata['configuration']:
        typepad.client.cookies.update(testdata['configuration']['cookies'])


def attr(*args, **kwargs):
    """Decorator wrapper for the nose 'attrib' attr decorator.
    
    This attr decorator recognizes the 'user' attribute when assigned and<commit_msg>Fix what I assume is a typo<commit_after># Copyright (c) 2009-2010 Six Apart Ltd.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
#   this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# * Neither the name of Six Apart Ltd. nor the names of its contributors may
#   be used to endorse or promote products derived from this software without
#   specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

"""

    # TODO
    # - featured members (i don't think we have filters for them yet)
    #   - that we cannot block a featured member
    # - test for failure of post by non-member / blocked user
    # - asset deletion failure by a non-creator, non-admin user
    # - comment deletion failure by non-commenter user

Input test data should have this form:

    testdata = {
        'configuration': {
            'backend_url': '...',
            'oauth_consumer_key': '...',
            'oauth_consumer_secret': '...',
            'cookies': { 'cookie_name': 'value' }
        },
        'admin': {
            'xid': '...',
            'oauth_key': '...',
            'oauth_secret': '...'
        },
        'member': {
            'xid': '...',
            'oauth_key': '...',
            'oauth_secret': '...'
        },
        'blocked': {
            'xid': '...',
            'oauth_key': '...',
            'oauth_secret': '...',
        },
        'featured': {
            'xid': '...',
            'oauth_key': '...',
            'oauth_secret': '...',
        },
        'group': {
            'xid': '...',
            'name': '...'
            'oauth_key': '...',
            'oauth_secret': '...'
        }
    }

    the member should follow admin
    the admin should follow member

    the member should have 2 or more elsewhere accounts

    'blocked' identifies a member who will become blocked by the
    test suite

Numbering prefix scheme for tests.
Some tests should be run in a specific order. The only way to do this
is through the test method name, as tests are run in alphabetic order.

    0 - POSTs for setting up data for tests

    1 - GET requests, relying on test data as described above.

    2 - Relationship test to unblock the blocked member
    3 - Test to (re-)block the user who was blocked to begin with

    4 - PUT requests

    5 - POST requests for parent objects (assets)
    6 - POST requests for child objects (favorites, comments)

    6z - HEAD, OPTIONS requests made after POSTs but before DELETEs

    7 - DELETE requests for child objects (favorites, comments)
    8 - DELETE requests for top-level objects (assets)

    9 - DELETE for remaining assets (final cleanup)

"""


import base64
import cgi
import httplib
import logging
import os
from pprint import pprint
import re
from StringIO import StringIO
import time
import unittest
from urllib import urlencode, unquote
from urlparse import urlsplit, urlunsplit, urlparse

import httplib2
import nose
import nose.plugins.attrib
import nose.tools
from oauth import oauth
from remoteobjects.http import HttpObject
import simplejson as json

import typepad


def load_test_data():
    filename = os.getenv('TEST_TYPEPAD_JSON')
    if filename is None:
        raise nose.SkipTest('no test data provided')
    f = open(filename, 'r')
    s = f.read()
    f.close()
    return json.loads(s)


def setUpModule():
    global testdata
    testdata = load_test_data()
    typepad.client.endpoint = testdata['configuration']['backend_url']
    testdata['assets'] = []
    testdata['assets_created'] = []
    testdata['comments_created'] = []
    if 'cookies' in testdata['configuration']:
        typepad.client.cookies.update(testdata['configuration']['cookies'])


def attr(*args, **kwargs):
    """Decorator wrapper for the nose 'attrib' attr decorator.
    
    This attr decorator recognizes the 'user' attribute when assigned and
{'fraction_non_alphanumeric': 0.0926055283903802, 'fraction_numerical': 0.004590360243488674, 'mean_word_length': 2.757780277465317, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2060051', 'n_tokens_mistral': 2825, 'n_tokens_neox': 2646, 'n_words': 1143}