def upgrade():
    conn = Connection(op.get_bind())
    example_map = {}

    sid = 204
    for example in jsonload(data_file('lingala_examples.json')):
        sid += 1
        kw = {
            'id': '60-%s' % sid,
            'language_pk': conn.pk(Language, '60'),
            'name': example['Text'],
            'description': example['Translation'],
            'gloss': '\t'.join(example['Gloss'].split()),
            'analyzed': '\t'.join(example['Text'].split()),
            'type': example['Type'].strip().lower(),
            'jsondata': {'sort': int(example['Order_number']), 'alt_translation': None}
        }
        example_map[example['Example_number']] = conn.insert(Sentence, **kw)

    for ve in jsonload(data_file('lingala_value_examples.json')):
        vspk = conn.pk(ValueSet, '60-%s' % ve['Features::Feature_number'])
        vpk = conn.pk(Value, vspk, attr='valueset_pk')
        conn.insert(
            ValueSentence, value_pk=vpk, sentence_pk=example_map[ve['Example_number']])

    for i, comment in enumerate(reader(data_file('lingala_valueset_comments.tab'), delimiter='\t', dicts=True)):
        vspk = conn.pk(ValueSet, '60-%s' % comment['Features::Feature_number'])
        comment['Comments_on_value_assignment'] = comment['Comments_on_value_assignment'].replace('\x0b', '\n')
        conn.update(
            ValueSet,
            {
                'description': comment['Comments_on_value_assignment'],
                'markup_description': None,
            },
            pk=vspk)
def upgrade():
    conn = Connection(op.get_bind())

    for hid, countries in REMOVE.items():
        l = conn.pk(Languoid, hid, attr='hid')
        for country in set(countries):
            c = conn.pk(Country, country)
            assert conn.first(Languoidcountry, country_pk=c, languoid_pk=l)
            conn.delete(Languoidcountry, country_pk=c, languoid_pk=l)

    for hid, countries in ADD.items():
        l = conn.pk(Languoid, hid, attr='hid')
        for c in set(countries):
            c = conn.pk(Country, c)
            conn.insert(Languoidcountry, country_pk=c, languoid_pk=l)
def upgrade():
    conn = Connection(op.get_bind())

    for hid, countries in REMOVE.items():
        l = conn.pk(Languoid, hid, attr='hid')
        for country in set(countries):
            c = conn.pk(Country, country)
            assert conn.first(Languoidcountry, country_pk=c, languoid_pk=l)
            conn.delete(Languoidcountry, country_pk=c, languoid_pk=l)

    for hid, countries in ADD.items():
        l = conn.pk(Languoid, hid, attr='hid')
        for c in set(countries):
            c = conn.pk(Country, c)
            conn.insert(Languoidcountry, country_pk=c, languoid_pk=l)
Example #4
0
    def test_crud(self):
        from clld.db.migration import Connection

        migration = Connection(DBSession)

        assert len(list(migration.select(common.Identifier))) == 0
        pk = migration.insert(common.Identifier,
                              id='iso-csw',
                              name='csw',
                              type=common.IdentifierType.iso.value)
        assert migration.pk(common.Identifier, 'iso-csw') == pk
        assert len(list(migration.select(common.Identifier))) == 1

        identifier = DBSession.query(common.Identifier).get(pk)
        assert identifier.active
        assert identifier.version == 1
        assert identifier.created
        assert identifier.updated

        migration.update(common.Identifier, [('name', 'cea')], pk=pk)
        DBSession.refresh(identifier)
        assert identifier.name == 'cea'

        migration.delete(common.Identifier, pk=pk)
        self.assertRaises(InvalidRequestError, DBSession.refresh, identifier)
def upgrade():
    conn = Connection(op.get_bind())

    spk = conn.pk()
    conn.insert()

    source = table(
        'source', column('id', String), column('url', Unicode), column('note', Unicode))
    op.execute(
        source.update()
        .where(source.c.id == op.inline_literal('heathetal2015'))
        .values({
            'url': op.inline_literal(
                'http://cdstar.shh.mpg.de/bitstreams/EAEA0-C97A-A1D2-2E76-0/a.xls'),
            'note': op.inline_literal('')})
    )
Example #6
0
    def test_crud(self):
        from clld.db.migration import Connection

        migration = Connection(DBSession)

        assert len(list(migration.select(common.Identifier))) == 0
        pk = migration.insert(
            common.Identifier,
            id='iso-csw', name='csw', type=common.IdentifierType.iso.value)
        assert migration.pk(common.Identifier, 'iso-csw') == pk
        assert len(list(migration.select(common.Identifier))) == 1

        identifier = DBSession.query(common.Identifier)\
            .options(undefer('*')).get(pk)
        assert identifier.active
        assert identifier.version == 1
        assert identifier.created
        assert identifier.updated

        migration.update(common.Identifier, [('name', 'cea')], pk=pk)
        DBSession.refresh(identifier)
        assert identifier.name == 'cea'

        migration.delete(common.Identifier, pk=pk)
        self.assertRaises(InvalidRequestError, DBSession.refresh, identifier)
Example #7
0
def test_crud(db):
    migration = Connection(DBSession)

    assert len(list(migration.select(common.Identifier))) == 0
    pk = migration.insert(common.Identifier,
                          id='iso-csw',
                          name='csw',
                          type=common.IdentifierType.iso.value)
    assert migration.pk(common.Identifier, 'iso-csw') == pk
    assert len(list(migration.select(common.Identifier))) == 1

    identifier = DBSession.query(common.Identifier)\
        .options(undefer('*')).get(pk)
    assert identifier.active
    assert identifier.version == 1
    assert identifier.created
    assert identifier.updated

    migration.update(common.Identifier, [('name', 'cea')], pk=pk)
    DBSession.refresh(identifier)
    assert identifier.name == 'cea'

    migration.delete(common.Identifier, pk=pk)
    with pytest.raises(InvalidRequestError):
        DBSession.refresh(identifier)
def upgrade():
    conn = Connection(op.get_bind())

    spk = conn.pk(Source, 'heathetal2015')
    conn.insert(
        Source_files,
        jsondata={
            "thumbnail": None,
            "web": None,
            "size": 7531008,
            "objid": "EAEA0-C97A-A1D2-2E76-0",
            "original": "a.xls"},
        id='heathetal2015-1',
        name='Dogon.comp.vocab.UNICODE.xls',
        ord=1,
        mime_type='application/vnd.ms-excel',
        object_pk=spk)
Example #9
0
def upgrade():
    conn = Connection(op.get_bind())
    example_map = {}

    sid = 204
    for example in jsonload(data_file('lingala_examples.json')):
        sid += 1
        kw = {
            'id': '60-%s' % sid,
            'language_pk': conn.pk(Language, '60'),
            'name': example['Text'],
            'description': example['Translation'],
            'gloss': '\t'.join(example['Gloss'].split()),
            'analyzed': '\t'.join(example['Text'].split()),
            'type': example['Type'].strip().lower(),
            'jsondata': {
                'sort': int(example['Order_number']),
                'alt_translation': None
            }
        }
        example_map[example['Example_number']] = conn.insert(Sentence, **kw)

    for ve in jsonload(data_file('lingala_value_examples.json')):
        vspk = conn.pk(ValueSet, '60-%s' % ve['Features::Feature_number'])
        vpk = conn.pk(Value, vspk, attr='valueset_pk')
        conn.insert(ValueSentence,
                    value_pk=vpk,
                    sentence_pk=example_map[ve['Example_number']])

    for i, comment in enumerate(
            reader(data_file('lingala_valueset_comments.tab'),
                   delimiter='\t',
                   dicts=True)):
        vspk = conn.pk(ValueSet, '60-%s' % comment['Features::Feature_number'])
        comment['Comments_on_value_assignment'] = comment[
            'Comments_on_value_assignment'].replace('\x0b', '\n')
        conn.update(ValueSet, {
            'description': comment['Comments_on_value_assignment'],
            'markup_description': None,
        },
                    pk=vspk)
Example #10
0
def test_set_glottocode(db):
    c = Connection(DBSession)
    lpk = c.insert(common.Language, id='l', name='Language')
    c.set_glottocode('l', 'abcd1234')
    c.set_glottocode('l', 'abcd1234')
    l = DBSession.query(common.Language).get(lpk)
    assert l.glottocode == 'abcd1234'

    c.set_glottocode('l', 'dcba1234')
    DBSession.expire_all()
    l = DBSession.query(common.Language).get(lpk)
    assert l.glottocode == 'dcba1234'
    c.set_glottocode('l', 'abcd1234')
Example #11
0
def test_set_glottocode(db):
    c = Connection(DBSession)
    lpk = c.insert(common.Language, id='l', name='Language')
    c.set_glottocode('l', 'abcd1234')
    c.set_glottocode('l', 'abcd1234')
    l = DBSession.query(common.Language).get(lpk)
    assert l.glottocode == 'abcd1234'

    c.set_glottocode('l', 'dcba1234')
    DBSession.expire_all()
    l = DBSession.query(common.Language).get(lpk)
    assert l.glottocode == 'dcba1234'
    c.set_glottocode('l', 'abcd1234')
def upgrade():
    conn = Connection(op.get_bind())
    pk = conn.insert(Contributor, id='gt', name='Güldemann, Tom', jsondata={},
                     polymorphic_type='custom',
                     address='Humboldt University of Berlin')
    pke = conn.insert(Editor, jsondata={}, polymorphic_type='custom',
                      dataset_pk=1, contributor_pk=pk)
    conn.insert(TsammalexEditor, pk=pke)
    conn.insert(TsammalexContributor, pk=pk, sections='', research_project='')
Example #13
0
    def test_set_glottocode(self):
        from clld.db.migration import Connection

        c = Connection(DBSession)
        lpk = c.insert(common.Language, id='l', name='Language')
        c.set_glottocode('l', 'abcd1234')
        c.set_glottocode('l', 'abcd1234')
        l = DBSession.query(common.Language).get(lpk)
        assert l.glottocode == 'abcd1234'

        c.set_glottocode('l', 'dcba1234')
        DBSession.expire_all()
        l = DBSession.query(common.Language).get(lpk)
        assert l.glottocode == 'dcba1234'
        c.set_glottocode('l', 'abcd1234')
Example #14
0
    def test_set_glottocode(self):
        from clld.db.migration import Connection

        c = Connection(DBSession)
        lpk = c.insert(common.Language, id='l', name='Language')
        c.set_glottocode('l', 'abcd1234')
        c.set_glottocode('l', 'abcd1234')
        l = DBSession.query(common.Language).get(lpk)
        assert l.glottocode == 'abcd1234'

        c.set_glottocode('l', 'dcba1234')
        DBSession.expire_all()
        l = DBSession.query(common.Language).get(lpk)
        assert l.glottocode == 'dcba1234'
        c.set_glottocode('l', 'abcd1234')
def upgrade():
    """
    Raji should be taken out
    of the Bodic genus and placed in a new genus Raji-Raute, but still part
    of the Tibeto-Burman subfamily of the Sino-Tibetan family.
    """
    conn = Connection(op.get_bind())
    pk = conn.pk(Family, 'sinotibetan')
    dizoid = conn.insert(Genus,
                         id='rajiraute',
                         name='Raji-Raute',
                         family_pk=pk,
                         subfamily='Tibeto-Burman',
                         icon='tffff00')
    pk = conn.pk(Language, 'rji')
    conn.update(WalsLanguage, [('genus_pk', dizoid)], pk=pk)
def upgrade():
    """
    Raji should be taken out
    of the Bodic genus and placed in a new genus Raji-Raute, but still part
    of the Tibeto-Burman subfamily of the Sino-Tibetan family.
    """
    conn = Connection(op.get_bind())
    pk = conn.pk(Family, 'sinotibetan')
    dizoid = conn.insert(
        Genus,
        id='rajiraute',
        name='Raji-Raute',
        family_pk=pk,
        subfamily='Tibeto-Burman',
        icon='tffff00')
    pk = conn.pk(Language, 'rji')
    conn.update(WalsLanguage, [('genus_pk', dizoid)], pk=pk)
Example #17
0
def upgrade():
    conn = Connection(op.get_bind())

   # We need to change the name of Kaliai-Kove (kkv) to Lusi (which is the Glottolog name).
    pk = conn.pk(Language, 'kkv')
    conn.update(Language, [('name', 'Lusi')], pk=pk)
    conn.update(WalsLanguage, [('ascii_name', 'lusi'), ('iso_codes', 'khl')], pk=pk)
    #wals3=# select li.pk, i.name, i.type, i.description from languageidentifier as li, identifier as i where li.language_pk = 2163 and li.identifier_pk = i.pk;
    #  pk   |     name     |   type    | description
    #-------+--------------+-----------+-------------
    #  1302 | Kove         | name      | ruhlen
    #  2749 | Kove-Kaliai  | name      | routledge
    #  4202 | Kaliai       | name      | other
    #  4406 | Kandoka-Lusi | name      | other
    #  4901 | Kaliai Kove  | name      | other
    #  7797 | khl          | iso639-3  | Lusi
    #  7798 | kvc          | iso639-3  | Kove
    # 10488 | Lusi         | name      | ethnologue
    # 10489 | Kove         | name      | ethnologue
    # 13658 | kali1298     | glottolog |
    conn.update(Identifier, [('name', 'lusi1240')], name='kali1298')
    remove = []
    for row in conn.execute("""
select li.pk, i.name from languageidentifier as li, identifier as i
where li.language_pk = %s and li.identifier_pk = i.pk""" % pk):
        if 'Kove' in row['name'] or row['name'] == 'kvc':
            remove.append(row['pk'])
    for pk in remove:
        conn.delete(LanguageIdentifier, pk=pk)

    # The language Dizi (wals code diz) needs to be removed from North Omotic and placed in a
    # separate (new) genus called Dizoid, within the Omotic subfamily of Afro-Asiatic.
    # (Glottolog actually treats Dizoid as a separate family altogether, which is good reason
    # to conclude that it is at least a separate genus.)
    pk = conn.pk(Family, 'afroasiatic')
    dizoid = conn.insert(
        Genus,
        id='dizoid',
        name='Dizoid',
        family_pk=pk,
        subfamily='Omotic',
        icon='tdd0000')
    pk = conn.pk(Language, 'diz')
    conn.update(WalsLanguage, [('genus_pk', dizoid)], pk=pk)

    # The name for what is now Siraiya (sry) should be changed to Siraya. (Siraya is also the Glottolog name)
    pk = conn.pk(Language, 'sry')
    conn.update(Language, [('name', 'Siraya')], pk=pk)
    conn.update(WalsLanguage, [('ascii_name', 'siraya')], pk=pk)

    # I want to modify the assignment of languages to genera for the Austronesian languages of Taiwan.
    # (This change brings WALS in line with Glottolog.)  Namely, I want to split up the current Paiwanic genus as follows:
    #
    # - Amis and Siraya should be moved into a new genus called East Formosan.
    # - Thao should be moved into a new genus called Western Plains Austronesian.
    #
    paiwanic = conn.first(Genus, id='paiwanic')
    eastformosan = conn.insert(
        Genus,
        id='eastformosan',
        name='East Formosan',
        family_pk=paiwanic['family_pk'],
        icon='fdd0000')
    westernplainsaustronesian = conn.insert(
        Genus,
        id='westernplainsaustronesian',
        name='Western Plains Austronesian',
        family_pk=paiwanic['family_pk'],
        icon='f0000dd')
    for lid in ['ami', 'sry']:
        pk = conn.pk(Language, lid)
        conn.update(WalsLanguage, [('genus_pk', eastformosan)], pk=pk)
    pk = conn.pk(Language, 'thw')
    conn.update(WalsLanguage, [('genus_pk', westernplainsaustronesian)], pk=pk)

    # The sole remaining language in Paiwanic is Paiwan, but since this genus now contains only one language,
    # we should rename the genus Paiwan.
    conn.update(Genus, [('name', 'Paiwan')], id='paiwanic')

    # For similar reasons, the genus Tsouic should just be called Tsou.
    conn.update(Genus, [('name', 'Tsou')], id='tsouic')

    # The genus currently called Southern Atlantic should be renamed Mel.  (This brings it in line with Glottolog.)
    conn.update(Genus, [('name', 'Mel')], id='southernatlantic')


    for id in ['Ashton-1947', 'Ashton-1969']:
        pk = conn.pk(Source, id)
        conn.update(Source, [('author', 'Ethel O. Ashton')], pk=pk)

    pk = conn.pk(Source, 'Poldaufem-1971')
    conn.update(
        Source,
        [
            ('name', 'Poldauf 1971'),
            ('author', 'Poldauf, Ivan'),
            ('description', 'Anglicko-český a česko-anglický slovník'),
            ('title', 'Anglicko-český a česko-anglický slovník'),
        ],
        pk=pk)

    #wals3=# select author, name, pages, title, description from source where id = 'De-Lancey-2003';
    #      author      |      name      |  pages  |       title       |    description
    #------------------+----------------+---------+-------------------+-------------------
    # De Lancey, Scott | De Lancey 2003 | 255-269 | Classical Tibetan | Classical Tibetan
    #(1 row)
    #-> DeLancey                           270-288  Lhasa Tibetan
    pk = conn.pk(Source, 'De-Lancey-2003')
    conn.update(
        Source,
        [
            ('name', 'DeLancey 2003'),
            ('author', 'DeLancey, Scott'),
            ('description', 'Lhasa Tibetan'),
            ('title', 'Lhasa Tibetan'),
        ],
        pk=pk)

    pk = conn.pk(Source, 'Frajzyngier-and-Shay-2002')
    conn.update(Source, [('author', 'Frajzyngier, Zygmunt with Erin Shay')], pk=pk)

    # wals-data #9
    conn.execute("update domainelement set name = 'No voicing contrast' where name = 'No voicing constrast'")

    # wals-data #7
    pk = conn.pk(Source, 'Brown-1990')
    conn.update(
        Source,
        [
            ('description', 'Mai Brat Nominal Phrases'),
            ('title', 'Mai Brat Nominal Phrases'),
            ('booktitle', 'Miscellaneous Studies of Indonesian and Other Languages of Indonesia, Part X'),
        ],
        pk=pk)

    pk = conn.pk(Source, 'Saltarelli-et-al-1988')
    conn.update(
        Source,
        [('author',
          'Saltarelli, Mario with Miren Azkarate,  and Farwell, David and de Urbina, Jon Ortiz and Oñederra, Lourdes')],
        pk=pk)

    #wals3=# select xhtml from sentence where id = '478';
    #replace:
    #'anywhere' -> 'whenever'
    #'where' -> 'when'
    res = conn.first(Sentence, id='478')
    xhtml = res['xhtml']
    for s, r in [("'anywhere'", "'whenever'"), ("'where'", "'when'")]:
        assert s in xhtml
        xhtml = xhtml.replace(s, r)
    conn.update(Sentence, [('xhtml', xhtml)], id='478')
Example #18
0
def upgrade():
    conn = Connection(op.get_bind())

    # We need to change the name of Kaliai-Kove (kkv) to Lusi (which is the Glottolog name).
    pk = conn.pk(Language, 'kkv')
    conn.update(Language, [('name', 'Lusi')], pk=pk)
    conn.update(WalsLanguage, [('ascii_name', 'lusi'), ('iso_codes', 'khl')],
                pk=pk)
    #wals3=# select li.pk, i.name, i.type, i.description from languageidentifier as li, identifier as i where li.language_pk = 2163 and li.identifier_pk = i.pk;
    #  pk   |     name     |   type    | description
    #-------+--------------+-----------+-------------
    #  1302 | Kove         | name      | ruhlen
    #  2749 | Kove-Kaliai  | name      | routledge
    #  4202 | Kaliai       | name      | other
    #  4406 | Kandoka-Lusi | name      | other
    #  4901 | Kaliai Kove  | name      | other
    #  7797 | khl          | iso639-3  | Lusi
    #  7798 | kvc          | iso639-3  | Kove
    # 10488 | Lusi         | name      | ethnologue
    # 10489 | Kove         | name      | ethnologue
    # 13658 | kali1298     | glottolog |
    conn.update(Identifier, [('name', 'lusi1240')], name='kali1298')
    remove = []
    for row in conn.execute("""
select li.pk, i.name from languageidentifier as li, identifier as i
where li.language_pk = %s and li.identifier_pk = i.pk""" % pk):
        if 'Kove' in row['name'] or row['name'] == 'kvc':
            remove.append(row['pk'])
    for pk in remove:
        conn.delete(LanguageIdentifier, pk=pk)

    # The language Dizi (wals code diz) needs to be removed from North Omotic and placed in a
    # separate (new) genus called Dizoid, within the Omotic subfamily of Afro-Asiatic.
    # (Glottolog actually treats Dizoid as a separate family altogether, which is good reason
    # to conclude that it is at least a separate genus.)
    pk = conn.pk(Family, 'afroasiatic')
    dizoid = conn.insert(Genus,
                         id='dizoid',
                         name='Dizoid',
                         family_pk=pk,
                         subfamily='Omotic',
                         icon='tdd0000')
    pk = conn.pk(Language, 'diz')
    conn.update(WalsLanguage, [('genus_pk', dizoid)], pk=pk)

    # The name for what is now Siraiya (sry) should be changed to Siraya. (Siraya is also the Glottolog name)
    pk = conn.pk(Language, 'sry')
    conn.update(Language, [('name', 'Siraya')], pk=pk)
    conn.update(WalsLanguage, [('ascii_name', 'siraya')], pk=pk)

    # I want to modify the assignment of languages to genera for the Austronesian languages of Taiwan.
    # (This change brings WALS in line with Glottolog.)  Namely, I want to split up the current Paiwanic genus as follows:
    #
    # - Amis and Siraya should be moved into a new genus called East Formosan.
    # - Thao should be moved into a new genus called Western Plains Austronesian.
    #
    paiwanic = conn.first(Genus, id='paiwanic')
    eastformosan = conn.insert(Genus,
                               id='eastformosan',
                               name='East Formosan',
                               family_pk=paiwanic['family_pk'],
                               icon='fdd0000')
    westernplainsaustronesian = conn.insert(Genus,
                                            id='westernplainsaustronesian',
                                            name='Western Plains Austronesian',
                                            family_pk=paiwanic['family_pk'],
                                            icon='f0000dd')
    for lid in ['ami', 'sry']:
        pk = conn.pk(Language, lid)
        conn.update(WalsLanguage, [('genus_pk', eastformosan)], pk=pk)
    pk = conn.pk(Language, 'thw')
    conn.update(WalsLanguage, [('genus_pk', westernplainsaustronesian)], pk=pk)

    # The sole remaining language in Paiwanic is Paiwan, but since this genus now contains only one language,
    # we should rename the genus Paiwan.
    conn.update(Genus, [('name', 'Paiwan')], id='paiwanic')

    # For similar reasons, the genus Tsouic should just be called Tsou.
    conn.update(Genus, [('name', 'Tsou')], id='tsouic')

    # The genus currently called Southern Atlantic should be renamed Mel.  (This brings it in line with Glottolog.)
    conn.update(Genus, [('name', 'Mel')], id='southernatlantic')

    for id in ['Ashton-1947', 'Ashton-1969']:
        pk = conn.pk(Source, id)
        conn.update(Source, [('author', 'Ethel O. Ashton')], pk=pk)

    pk = conn.pk(Source, 'Poldaufem-1971')
    conn.update(Source, [
        ('name', 'Poldauf 1971'),
        ('author', 'Poldauf, Ivan'),
        ('description', 'Anglicko-český a česko-anglický slovník'),
        ('title', 'Anglicko-český a česko-anglický slovník'),
    ],
                pk=pk)

    #wals3=# select author, name, pages, title, description from source where id = 'De-Lancey-2003';
    #      author      |      name      |  pages  |       title       |    description
    #------------------+----------------+---------+-------------------+-------------------
    # De Lancey, Scott | De Lancey 2003 | 255-269 | Classical Tibetan | Classical Tibetan
    #(1 row)
    #-> DeLancey                           270-288  Lhasa Tibetan
    pk = conn.pk(Source, 'De-Lancey-2003')
    conn.update(Source, [
        ('name', 'DeLancey 2003'),
        ('author', 'DeLancey, Scott'),
        ('description', 'Lhasa Tibetan'),
        ('title', 'Lhasa Tibetan'),
    ],
                pk=pk)

    pk = conn.pk(Source, 'Frajzyngier-and-Shay-2002')
    conn.update(Source, [('author', 'Frajzyngier, Zygmunt with Erin Shay')],
                pk=pk)

    # wals-data #9
    conn.execute(
        "update domainelement set name = 'No voicing contrast' where name = 'No voicing constrast'"
    )

    # wals-data #7
    pk = conn.pk(Source, 'Brown-1990')
    conn.update(Source, [
        ('description', 'Mai Brat Nominal Phrases'),
        ('title', 'Mai Brat Nominal Phrases'),
        ('booktitle',
         'Miscellaneous Studies of Indonesian and Other Languages of Indonesia, Part X'
         ),
    ],
                pk=pk)

    pk = conn.pk(Source, 'Saltarelli-et-al-1988')
    conn.update(Source, [(
        'author',
        'Saltarelli, Mario with Miren Azkarate,  and Farwell, David and de Urbina, Jon Ortiz and Oñederra, Lourdes'
    )],
                pk=pk)

    #wals3=# select xhtml from sentence where id = '478';
    #replace:
    #'anywhere' -> 'whenever'
    #'where' -> 'when'
    res = conn.first(Sentence, id='478')
    xhtml = res['xhtml']
    for s, r in [("'anywhere'", "'whenever'"), ("'where'", "'when'")]:
        assert s in xhtml
        xhtml = xhtml.replace(s, r)
    conn.update(Sentence, [('xhtml', xhtml)], id='478')
def upgrade():
    conn = Connection(op.get_bind())

    # Khoisan needs to be replaced by four families:
    # Sandawe (no name change)
    # Kxa: two genera: =|Hoan, Ju-Kung (a name change from 'Northern Khoisan')
    # Tu (a name change from Southern Khoisan)
    # Khoe-Kwadi (a name change from Central Khoisan)
    genera = {
        'hoan': ('Kxa', None),
        'sandawe': ('Sandawe', None),
        'centralkhoisan': ('Khoe-Kwadi', 'Khoe-Kwadi'),
        'southernkhoisan': ('Tu', 'Tu'),
        'northernkhoisan': ('Kxa', 'Ju-Kung'),
    }
    families = {}

    for gid, (fname, gname) in genera.items():
        fid = slug(fname)
        fpk = families.get(fid)
        if fpk is None:
            families[fid] = fpk = conn.insert(Family, id=fid, name=fname)
        values = dict(family_pk=fpk)
        if gname:
            values['name'] = gname
        conn.update(Genus, values, id=gid)

    conn.insert(Config,
                key=Config.replacement_key(Family, 'khoisan'),
                value=Config.gone)
    conn.delete(Family, id='khoisan')

    # Nilo-Saharan needs to be removed and replaced by the following families, with
    # constituent genera.
    # The following genera will now be families containing a single genus with the
    # same name:
    # Berta Kunama Songhay Gumuz Koman Shabo Kuliak Maban Fur
    for gname in 'Berta Kunama Songhay Gumuz Koman Shabo Kuliak Maban Fur'.split(
    ):
        gid = gname.lower()
        fpk = conn.insert(Family, id=gid, name=gname)
        gpk = conn.pk(Genus, gid)
        conn.update(Genus, dict(family_pk=fpk), pk=gpk)

    # The following is one family with two genera:
    # Saharan: Eastern Saharan, Western Saharan
    fpk = conn.insert(Family, id='saharan', name='Saharan')
    for gname in ['Eastern Saharan', 'Western Saharan']:
        conn.update(Genus,
                    dict(family_pk=fpk),
                    pk=conn.pk(Genus, gname, attr='name'))

    # What is currently the subfamily Central Sudanic becomes a family with the same name
    # and same constituent genera
    # and what is currently the subfamily Eastern Sudanic becomes a family with the same
    # name and the same constituent genera.
    for sfn in ['Central Sudanic', 'Eastern Sudanic']:
        fpk = conn.insert(Family, id=slug(sfn), name=sfn)
        conn.update(Genus, dict(family_pk=fpk, subfamily=None), subfamily=sfn)

    conn.insert(Config,
                key=Config.replacement_key(Family, 'nilosaharan'),
                value=Config.gone)
    conn.delete(Family, id='nilosaharan')

    # The following groups need to be removed from Niger-Congo and set up as separate
    # families. The last two (Dogon and Ijoid) are families containing one genus.
    # - Mande (currently a subfamily) with the following two genera:
    # Eastern Mande, Western Mande
    # - Kordofanian (currently a subfamily) with the following five genera:
    # Katla-Tima, Rashad, Heiban, Talodi (a name change from Talodi Proper),
    # and Lafofa (renamed from Tegem)
    # - Dogon
    # - Ijoid
    for sfn in ['Mande', 'Kordofanian']:
        fpk = conn.insert(Family, id=slug(sfn), name=sfn)
        conn.update(Genus, dict(family_pk=fpk, subfamily=None), subfamily=sfn)

    for old, new in {'Talodi Proper': 'Talodi', 'Tegem': 'Lafofa'}.items():
        conn.update(Genus, dict(name=new), name=old)

    for sfn in ['Dogon', 'Ijoid']:
        fpk = conn.insert(Family, id=slug(sfn), name=sfn)
        conn.update(Genus, dict(family_pk=fpk), name=sfn)

    # A minor change in the name of the family Kadugli to just Kadu.
    conn.update(Family, dict(name='Kadu'), name='Kadugli')
def upgrade():
    conn = Connection(op.get_bind())

    # Khoisan needs to be replaced by four families:
    # Sandawe (no name change)
    # Kxa: two genera: =|Hoan, Ju-Kung (a name change from 'Northern Khoisan')
    # Tu (a name change from Southern Khoisan)
    # Khoe-Kwadi (a name change from Central Khoisan)
    genera = {
        'hoan': ('Kxa', None),
        'sandawe': ('Sandawe', None),
        'centralkhoisan': ('Khoe-Kwadi', 'Khoe-Kwadi'),
        'southernkhoisan': ('Tu', 'Tu'),
        'northernkhoisan': ('Kxa', 'Ju-Kung'),
    }
    families = {}

    for gid, (fname, gname) in genera.items():
        fid = slug(fname)
        fpk = families.get(fid)
        if fpk is None:
            families[fid] = fpk = conn.insert(Family, id=fid, name=fname)
        values = dict(family_pk=fpk)
        if gname:
            values['name'] = gname
        conn.update(Genus, values, id=gid)

    conn.insert(Config, key=Config.replacement_key(Family, 'khoisan'), value=Config.gone)
    conn.delete(Family, id='khoisan')

    # Nilo-Saharan needs to be removed and replaced by the following families, with
    # constituent genera.
    # The following genera will now be families containing a single genus with the
    # same name:
    # Berta Kunama Songhay Gumuz Koman Shabo Kuliak Maban Fur
    for gname in 'Berta Kunama Songhay Gumuz Koman Shabo Kuliak Maban Fur'.split():
        gid = gname.lower()
        fpk = conn.insert(Family, id=gid, name=gname)
        gpk = conn.pk(Genus, gid)
        conn.update(Genus, dict(family_pk=fpk), pk=gpk)

    # The following is one family with two genera:
    # Saharan: Eastern Saharan, Western Saharan
    fpk = conn.insert(Family, id='saharan', name='Saharan')
    for gname in ['Eastern Saharan', 'Western Saharan']:
        conn.update(Genus, dict(family_pk=fpk), pk=conn.pk(Genus, gname, attr='name'))

    # What is currently the subfamily Central Sudanic becomes a family with the same name
    # and same constituent genera
    # and what is currently the subfamily Eastern Sudanic becomes a family with the same
    # name and the same constituent genera.
    for sfn in ['Central Sudanic', 'Eastern Sudanic']:
        fpk = conn.insert(Family, id=slug(sfn), name=sfn)
        conn.update(Genus, dict(family_pk=fpk, subfamily=None), subfamily=sfn)

    conn.insert(Config, key=Config.replacement_key(Family, 'nilosaharan'), value=Config.gone)
    conn.delete(Family, id='nilosaharan')

    # The following groups need to be removed from Niger-Congo and set up as separate
    # families. The last two (Dogon and Ijoid) are families containing one genus.
    # - Mande (currently a subfamily) with the following two genera:
    # Eastern Mande, Western Mande
    # - Kordofanian (currently a subfamily) with the following five genera:
    # Katla-Tima, Rashad, Heiban, Talodi (a name change from Talodi Proper),
    # and Lafofa (renamed from Tegem)
    # - Dogon
    # - Ijoid
    for sfn in ['Mande', 'Kordofanian']:
        fpk = conn.insert(Family, id=slug(sfn), name=sfn)
        conn.update(Genus, dict(family_pk=fpk, subfamily=None), subfamily=sfn)

    for old, new in {'Talodi Proper': 'Talodi', 'Tegem': 'Lafofa'}.items():
        conn.update(Genus, dict(name=new), name=old)

    for sfn in ['Dogon', 'Ijoid']:
        fpk = conn.insert(Family, id=slug(sfn), name=sfn)
        conn.update(Genus, dict(family_pk=fpk), name=sfn)

    # A minor change in the name of the family Kadugli to just Kadu.
    conn.update(Family, dict(name='Kadu'), name='Kadugli')