Example #1
0
def refresh_metadata():
    """
    Cycle through all documents for all users and regenerate their cache and
    metadata entries. This needs a
    """
    raise RuntimeError("Must be able to document.set_host")
    data = get_redis_client()
    for user_slug in data.userSet_list():
        for doc_slug in data.userDocumentSet_list(user_slug):
            document = Document(data)
            document.set_host()  # <-- TODO
            document.load(user_slug, doc_slug)
            document.save()
Example #2
0
def delete_part(user_slug, doc_slug, part_slug):
    """
    Delete a part from a document. Must be logged in, and be the owner.

    To Do:
        - Form and confirmation step?
        - Delete parts including unused?
    """
    require_authority_for_user(user_slug)  # or 401
    document = Document(data)
    document.set_host(domain_name(bottle.request))
    if not document.load(user_slug, doc_slug):
        msg = "Document '{:s}/{:s}' not found."
        bottle.abort(HTTP_NOT_FOUND, msg.format(user_slug, doc_slug))
    document.delete_part(part_slug)
    if len(document.parts) > 0:
        document.save()
        bottle.redirect('/read/{:s}/{:s}'.format(user_slug, doc_slug))
    else:
        document.delete()
        bottle.redirect('/user/{:s}'.format(user_slug))
Example #3
0
def post_upload_txt(user_slug, doc_slug):
    """
    Create a document from an download file.
    @todo: Show a diff?
    """
    require_authority_for_user(user_slug)  # else 401s
    upload = bottle.request.files.get('upload')

    # Validation
    limit = int(config['UPLOAD_LIMIT_KB'])
    if upload.content_length > (limit * 1024):
        msg = "The uploaded file is too large (limit: {:d}K)."
        bottle.abort(msg.format(limit))
    name = upload.filename
    prefix = 'article-wiki_{:s}_{:s}_'.format(user_slug, doc_slug)
    if not name.startswith(prefix) or not name.endswith('.txt'):
        msg = "A '{:s}*.txt' filename is expected."
        bottle.abort(400, msg.format(prefix))

    # Load contents
    filepath = '/tmp/' + upload.filename
    if os.path.exists(filepath):
        os.unlink(filepath)
    upload.save('/tmp')
    try:
        contents = codecs.open(filepath, 'r', 'utf-8').read()
    except Exception:
        msg = "Failed to read path '{:s}'."
        bottle.abort(HTTP_NOT_FOUND, msg.format(user_slug))
    os.unlink(filepath)

    document = Document(data)
    host = domain_name(bottle.request)
    document.set_host(host)
    document.import_txt_file(user_slug, doc_slug, contents)
    document.save()

    uri = '/read/{:s}/{:s}'.format(user_slug, doc_slug)
    bottle.redirect(uri)
Example #4
0
def post_edit_part(user_slug, doc_slug, part_slug):
    """
    Wiki editor for existing doc part (or '_' if new).
    """
    if user_slug == '_':  # New user
        msg = "Blank user '_' not supported."
        bottle.abort(HTTP_BAD_REQUEST, msg)
    if doc_slug == '_' and part_slug == '_':
        msg = "Blank document and part '_/_' not supported."
        bottle.abort(HTTP_BAD_REQUEST, msg)

    if 'they_selected_save' in bottle.request.forms:
        require_authority_for_user(user_slug)
    if 'content' not in bottle.request.forms:
        bottle.abort(HTTP_BAD_REQUEST, "Form data was missing.")

    new_text = clean_text(bottle.request.forms.content)

    # Default slugs unless we change them
    new_part_slug = part_slug
    new_doc_slug, old_doc_slug = doc_slug, doc_slug

    document = Document(data)
    host = domain_name(bottle.request)
    document.set_host(host)
    if doc_slug == "_":
        # New article...
        new_doc_slug = document.set_index(new_text)
        new_doc_slug = data.userDocument_unique_slug(user_slug, new_doc_slug)
        document.set_slugs(user_slug, new_doc_slug)
    elif document.load(user_slug, doc_slug):
        if part_slug == 'index':
            new_doc_slug = document.set_index(new_text)
            if new_doc_slug != doc_slug:
                unique_slug = data.userDocument_unique_slug(
                    user_slug, new_doc_slug)
                document.set_slugs(user_slug, unique_slug)
        else:
            new_part_slug = document.set_part(part_slug, new_text)
    else:
        msg = "Document '{:s}/{:s}' not found."
        bottle.abort(HTTP_NOT_FOUND, msg.format(user_slug, doc_slug))

    okay_to_save = all([
        'they_selected_save' in bottle.request.forms,
        has_authority_for_user(user_slug)
    ])

    if okay_to_save:

        new_doc_slug = document.save(pregenerate=True)

        old_doc = Document(data)
        if old_doc.load(user_slug, old_doc_slug):
            if old_doc.doc_slug != new_doc_slug:
                old_doc.delete()

        # Special redirects when editing fixtures
        uri = '/read/{:s}/{:s}'.format(user_slug, new_doc_slug)
        if doc_slug == 'fixtures':
            if part_slug == 'homepage':
                uri = '/'
            elif part_slug == 'author':
                uri = '/user/{:s}'.format(user_slug)
        bottle.redirect(uri)

    is_preview = 'they_selected_preview' in bottle.request.forms

    return show_editor(new_text,
                       document.user_slug,
                       document.doc_slug,
                       new_part_slug,
                       is_preview,
                       can_be_saved=has_authority_for_user(user_slug))
Example #5
0
def test_repr_save_load_delete():
    """
    Confirms data in data out. Builds upon data.py.
    """
    data.redis.flushdb()

    user_slug = random_slug('test-user-')
    doc_slug = random_slug('test-doc-')
    doc = Document(data)
    doc.set_host('http://example.org')
    doc.set_parts(user_slug, doc_slug, minimal_document)

    # Create
    new_doc_slug = doc.save(pregenerate=True, update_doc_slug=True)

    assert user_slug in str(doc)
    assert new_doc_slug in str(doc)
    assert "(3 parts)" in str(doc)

    assert new_doc_slug == 'example-document'
    assert data.userSet_exists(user_slug)
    assert data.userDocument_exists(user_slug, new_doc_slug)

    latest_slugs = [
        _['slug'] for _ in data.userDocumentLastChanged_list(user_slug)
    ]
    assert new_doc_slug in latest_slugs
    assert data.userDocumentMetadata_exists(user_slug, new_doc_slug)
    assert data.userDocumentCache_exists(user_slug, new_doc_slug)
    assert data.userDocumentSet_exists(user_slug, new_doc_slug)

    # Rename
    doc.set_index(
        trim("""
        New Example Document

        Text Goes Here!
    """))
    new_doc_slug = doc.save(pregenerate=True, update_doc_slug=True)
    assert new_doc_slug == "new-example-document"

    assert not data.userDocumentSet_exists(user_slug, doc_slug)
    assert not data.userDocument_exists(user_slug, doc_slug)
    assert not data.userDocumentMetadata_exists(user_slug, doc_slug)
    assert not data.userDocumentCache_exists(user_slug, doc_slug)

    latest_metadata = data.userDocumentLastChanged_list(user_slug)
    assert not any([_.get('slug') == doc_slug for _ in latest_metadata])
    assert any([_.get('slug') == new_doc_slug for _ in latest_metadata])

    assert data.userDocumentSet_exists(user_slug, new_doc_slug)
    assert data.userDocument_exists(user_slug, new_doc_slug)
    assert data.userDocumentMetadata_exists(user_slug, new_doc_slug)
    assert data.userDocumentCache_exists(user_slug, new_doc_slug)
    assert data.userDocumentSet_exists(user_slug, new_doc_slug)

    doc2 = Document(data)
    doc2.load(user_slug, new_doc_slug)

    assert doc.user_slug == doc2.user_slug
    assert doc.doc_slug == doc2.doc_slug
    assert doc.parts == doc2.parts

    # Delete
    doc.delete()

    assert not data.userDocument_exists(user_slug, new_doc_slug)
    assert not data.userDocumentSet_exists(user_slug, new_doc_slug)
    assert not data.userDocumentMetadata_exists(user_slug, new_doc_slug)
    latest_metadata = data.userDocumentLastChanged_list(user_slug)
    assert not any([_.get('slug') == new_doc_slug for _ in latest_metadata])
    assert not data.userDocumentCache_exists(user_slug, new_doc_slug)
Example #6
0
def main():
    clause2method = {'insert':'POST', 'update':'PUT', 'query':'GET', 'delete':'DELETE'}
    combined_sql_list = [] # eventually is written to a file
    # [Generate API sql file]
    print('Generate API')
    print('  - load api configuration, generate funcPattern key and values')
    # get configuration file name {folder: "", name: ""}
    # get list of files of type .json in folder ./config

    # [Use a configuration file]
    config_folder = '{}'.format(os.getcwd().replace('_tasks','config'))

    # [Select API Source ]
    sourceConfiguration = open_api(config_folder,file_type="source")
    if not sourceConfiguration:
        print('cancel')
        exit(0)

    # [Select API Target ]
    targetConfiguration = open_api(config_folder,file_type="target")
    if not targetConfiguration:
        print('cancel')
        exit(0)

    # [Merge Source and Target]
    sourceConfiguration.update(targetConfiguration)
    apiConfiguration = sourceConfiguration

    # setup default environment
    homeDev = HomeDevelopment().setup()

    # [Create missing folders]
    sourceDev = HomeDevelopment().setup()
    targetDev = HomeDevelopment().setup()

    # [Scan configuration for home, source, and target environment configurations]
    for apiName in apiConfiguration:
        if apiName == 'source':
            # [Configure input sources from GIT repositories]
            sourceDev = get_environment(apiConfiguration[apiName])

        elif apiName == 'target':
            # [Configure output targets from GIT repositories]
            targetDev = get_environment(apiConfiguration[apiName])

    print('=================')
    report(homeDev, sourceDev, targetDev)
    print('=================')
    print('=================')
    print('Base Tests Combined')
    print('=================')
    #fileList = Util().getFileList(sourceDev.getDbFolder('sql'),'static.sql')
    fileList = Util().getFileList(sourceDev.getFolder('scripts'),'base.test.sql')
    fileList.sort()
    # [Replace project specific values]
    replace_ = ['one_db', 'hapi-api']
    replace_with = [targetDev.getName('db'), targetDev.getName('db_api')]

    targetName = '90.base.test.sql'
    combinedDocument = Document(targetDev.getFolder('scripts'), targetName)


    # [Backup the target file]
    backup = Util().makeBackupFile(targetDev.getFolder('scripts'), targetName)
    print('  - backup : {}'.format(backup))

    # [Move Static Files to Target Folder]
    for fileName in fileList:
        # [Combine base tests into one file]
        # [Copy from a source folder to a target folder]

        staticDocument = Document(sourceDev.getFolder('scripts'), fileName) \
            .load() \
            .replace(replace_, replace_with)

        combinedDocument.extend(staticDocument)

    combinedDocument.save()

    print('=================')
    print('API Tests')
    print('=================')

    apiNameList = [nm for nm in apiConfiguration if apiConfiguration[nm]['kind'] == 'api-definition' or apiConfiguration[nm]['kind'] == 'api-static']

    # [Move Static Files to Target Folder]
    #targetNames = []
    #sourceNames = []
    names = []
    src_folder = sourceDev.getFolder('scripts')
    tmpl_folder = '../templates'
    trg_folder = targetDev.getFolder('scripts')
    clauses = ['insert','query','update','delete']
    for apiName in apiNameList:
        schema = apiConfiguration[apiName]['schema'].replace('_','.')
        prefix = apiConfiguration[apiName]['prefix-test']
        # make list of existing test files
        names = [{"source":'{}.test.{}.{}.{}.api.test.sql'.format(prefix,schema, apiName.upper(), clause),
                  "target":'{}.{}.{}.api.test.sql'.format(prefix,apiName.upper(), clause),
                  "template": '{}.test.sql.template'.format(clause),
                  "clause": '{}'.format(clause),
                  "method": '{}'.format(clause2method[clause])} for clause in clauses]
        names = [pair for pair in names if Util().file_exists(src_folder, pair['source'])]
        #
        for pair in names:
            backup = None
            #print('pair', pair, 'kind', apiConfiguration[apiName]['kind'])
            if apiConfiguration[apiName]['kind'] == 'api-definition':
                # handle backup
                if Util().file_exists(trg_folder, pair['target']):
                    backup = Util().makeBackupFile(targetDev.getFolder('scripts'), pair['target'])

                # Use Template
                if Util().file_exists(tmpl_folder, pair['template']): # Use Template
                    # Use Template
                    print('    - generate test {} FROM {}'.format(pair['target'], pair['template']))
                    if backup: print('       -- backup ', backup)
                    templateDoc = TestTemplate(apiName, pair['method'], pair['template']) \
                        .apply(apiConfiguration)\
                        .saveAs(trg_folder, pair['target'])

                elif Util().file_exists(src_folder, pair['source']): # Copy from existing file
                    # Copy from source
                    print('    - copy test {} FROM {} '.format(pair['target'],pair['source']))
                    # load
                    # replace
                    # save
                    doc = Document(src_folder, pair['source']) \
                        .load() \
                        .replace(replace_, replace_with)\
                        .saveAs(trg_folder,pair['target'])

                else: # No test available
                    print('No Test Available for ', pair['source'])

            elif apiConfiguration[apiName]['kind'] == 'api-static':
                #print('template', tmpl_folder)
                print('    - copy test for api-static ', pair['source'])

        # [Backup the target file]

        #print('  - backup : {}'.format(fileName))

    apiNameList = [nm for nm in apiConfiguration if apiConfiguration[nm]['kind'] == 'api-static']

    # [Move Static Files to Target Folder]
    '''