Changeset 193:bb9d4763dba9
- Timestamp:
- 07/25/09 13:55:18 (13 months ago)
- Author:
- rgrp
- Branch:
- default
- convert_revision:
- svn:0ead1229-0713-0410-96cd-f668dbfad531/trunk@279
- Message:
-
[model][m]: create new Resource object related to Material and remove Resource-related attributes (src_pkg, src_locator) from Material.
- Create associated migrate scripts (though do not do data migration)
- cli.py: support for downgrade as well as upgrade (and upgrade to a version)
- Update all Material/Resource related code (I hope)
- Location:
- shakespeare
- Files:
-
Legend:
- Unmodified
- Added
- Removed
-
|
r190
|
r193
|
|
| 78 | 78 | # Commands |
| 79 | 79 | |
| 80 | | db_actions = [ 'create', 'upgrade', 'clean', 'rebuild', 'init_shksprdata', 'init_miltondata' ] |
| 81 | | def do_db(self, line=None): |
| 82 | | if line is None or line not in self.db_actions: |
| | 80 | db_actions = [ 'create', 'upgrade', 'downgrade', 'clean', 'rebuild', 'init_shksprdata', 'init_miltondata' ] |
| | 81 | def do_db(self, line=''): |
| | 82 | args = line.split() |
| | 83 | action = args[0] |
| | 84 | if not action in self.db_actions: |
| 83 | 85 | self.help_db() |
| 84 | 86 | return 1 |
| … |
… |
|
| 87 | 89 | import shakespeare |
| 88 | 90 | migrate_repository = 'shakespeare/migration/' |
| 89 | | if line == 'create': |
| | 91 | if action == 'create': |
| 90 | 92 | model.repo.create_db() |
| 91 | | elif line == 'clean': |
| | 93 | elif action == 'clean': |
| 92 | 94 | model.repo.clean_db() |
| 93 | | elif line == 'rebuild': |
| | 95 | elif action == 'rebuild': |
| 94 | 96 | model.repo.rebuild_db() |
| 95 | | elif line == 'upgrade': |
| | 97 | elif action == 'upgrade': |
| | 98 | version = None |
| | 99 | if len(args) > 1: |
| | 100 | version = args[1] |
| | 101 | import migrate.versioning.exceptions |
| 96 | 102 | import migrate.versioning.api |
| 97 | 103 | import migrate.versioning.api as mig |
| | 104 | try: |
| | 105 | mig.version_control(model.meta.engine.url, migrate_repository) |
| | 106 | except migrate.versioning.exceptions.DatabaseAlreadyControlledError: |
| | 107 | pass |
| 98 | 108 | mig.upgrade(model.meta.engine.url, migrate_repository, |
| 99 | | version=None) |
| 100 | | elif line == 'downgrade': |
| 101 | | # TODO (need a version argument ...) |
| 102 | | raise NotImplementedError() |
| 103 | | elif line.startswith('init_'): |
| 104 | | modname = line.strip()[5:] |
| | 109 | version=version) |
| | 110 | elif action == 'downgrade': |
| | 111 | if len(args) < 2: |
| | 112 | print 'You need to supply a version to downgrade to' |
| | 113 | return 1 |
| | 114 | version = args[1] |
| | 115 | import migrate.versioning.api |
| | 116 | import migrate.versioning.api as mig |
| | 117 | mig.downgrade(model.meta.engine.url, migrate_repository, |
| | 118 | version=version) |
| | 119 | elif action.startswith('init_'): |
| | 120 | modname = action.strip()[5:] |
| 105 | 121 | mod = __import__(modname+'.cli', fromlist='cli') |
| 106 | 122 | mod.LoadTexts.load_texts() |
-
|
r168
|
r193
|
|
| 51 | 51 | tfileobj = item.get_text() |
| 52 | 52 | # hack for time being ... |
| 53 | | if item.format == 'mkd': |
| | 53 | if item.resources and item.resources[0].format == 'mkd': |
| 54 | 54 | ttext = h.markdown(tfileobj.read()) |
| 55 | 55 | else: |
-
|
r190
|
r193
|
|
| 37 | 37 | version_table = Table('migrate_version', self.metadata, autoload=True) |
| 38 | 38 | version_table.drop() |
| 39 | | except sqlalchemy.exceptions.NoSuchTableError: |
| | 39 | except: # seem to occasionally get other sqlalchemy errors ... |
| | 40 | # except sqlalchemy.exceptions.NoSuchTableError: |
| 40 | 41 | pass |
| 41 | 42 | |
-
|
r192
|
r193
|
|
| 25 | 25 | Column('creator', Unicode(255)), |
| 26 | 26 | Column('notes', UnicodeText), |
| | 27 | ) |
| | 28 | |
| | 29 | resource_table = Table('resource', metadata, |
| | 30 | Column('id', Integer, primary_key=True), |
| | 31 | Column('material_id', Integer, ForeignKey('material.id')), |
| 27 | 32 | Column('format', UnicodeText), |
| 28 | | # python package it lives in, if any |
| 29 | | Column('src_pkg', UnicodeText), |
| 30 | | # url (file or web) or standard (unix) file path |
| 31 | | Column('src_locator', UnicodeText), |
| | 33 | # url or path |
| | 34 | Column('locator', UnicodeText), |
| | 35 | # types: url, cache, package, disk |
| | 36 | Column('locator_type', UnicodeText, default=u'url'), |
| 32 | 37 | ) |
| 33 | 38 | |
| … |
… |
|
| 72 | 77 | # ignore format for time being |
| 73 | 78 | ''' |
| 74 | | import pkg_resources |
| 75 | | # default to plain txt format (TODO: generalise this) |
| 76 | | fileobj = pkg_resources.resource_stream(self.src_pkg, self.src_locator) |
| 77 | | return fileobj |
| | 79 | if self.resources: |
| | 80 | return self.resources[0].get_stream() |
| 78 | 81 | |
| 79 | 82 | def get_ftitle(self): |
| … |
… |
|
| 81 | 84 | |
| 82 | 85 | ftitle = property(get_ftitle) |
| | 86 | |
| | 87 | |
| | 88 | class Resource(object): |
| | 89 | def get_stream(self): |
| | 90 | '''Get text (if any) associated with this material. |
| | 91 | |
| | 92 | # ignore format for time being |
| | 93 | ''' |
| | 94 | if self.locator_type == u'package': |
| | 95 | package, path = self.locator.split('::') |
| | 96 | import pkg_resources |
| | 97 | fileobj = pkg_resources.resource_stream(package, path) |
| | 98 | return fileobj |
| | 99 | else: |
| | 100 | raise NotImplementedError |
| 83 | 101 | |
| 84 | 102 | |
| … |
… |
|
| 99 | 117 | ) |
| 100 | 118 | |
| | 119 | mapper(Resource, resource_table, properties={ |
| | 120 | 'material':relation(Material, backref='resources') |
| | 121 | }, |
| | 122 | order_by=resource_table.c.id |
| | 123 | ) |
| | 124 | |
| 101 | 125 | mapper(Statistic, statistic_table, properties={ |
| 102 | 126 | 'text':relation(Material, backref='statistics') |
-
|
r156
|
r193
|
|
| 22 | 22 | <h3>Metadata</h3> |
| 23 | 23 | <ul> |
| 24 | | <li py:for="attr in ['creator', 'name', 'format', 'notes']"> |
| | 24 | <li py:for="attr in ['creator', 'name', 'notes']"> |
| 25 | 25 | <strong>${attr.capitalize()}:</strong> |
| 26 | 26 | ${getattr(c.material, attr)} |
-
|
r192
|
r193
|
|
| 13 | 13 | title=self.title, |
| 14 | 14 | work=work, |
| 15 | | src_pkg=u'shksprdata', |
| 16 | | src_locator=u'/gutenberg/phoenix_and_the_turtle_gut.txt' |
| | 15 | ) |
| | 16 | resource = model.Resource( |
| | 17 | material=text, |
| | 18 | locator_type=u'package', |
| | 19 | locator=u'shksprdata::/gutenberg/phoenix_and_the_turtle_gut.txt', |
| | 20 | format=u'txt', |
| 17 | 21 | ) |
| 18 | 22 | |
| … |
… |
|
| 20 | 24 | self.workid = work.id |
| 21 | 25 | self.textid = text.id |
| | 26 | self.resourceid = resource.id |
| 22 | 27 | model.Session.clear() |
| 23 | 28 | |
| 24 | 29 | @classmethod |
| 25 | 30 | def teardown_class(self): |
| 26 | | text = model.Material.query.get(self.textid) |
| 27 | | work = model.Material.query.get(self.workid) |
| 28 | | model.Session.delete(text) |
| 29 | | if work: |
| 30 | | model.Session.delete(work) |
| 31 | | model.Session.flush() |
| | 31 | model.repo.rebuild_db() |
| 32 | 32 | |
| 33 | 33 | def test_work(self): |
| … |
… |
|
| 42 | 42 | assert txt2.title == self.title |
| 43 | 43 | assert txt2.work.id == self.workid |
| | 44 | assert txt2.resources |
| 44 | 45 | |
| 45 | 46 | def test_get_text(self): |
| … |
… |
|
| 49 | 50 | assert len(out) > 0 |
| 50 | 51 | assert out[:26] == 'THE PHOENIX AND THE TURTLE' |
| | 52 | |
| | 53 | def test_resource(self): |
| | 54 | res = model.Resource.query.get(self.resourceid) |
| | 55 | assert res.format == u'txt' |
| 51 | 56 | |
| 52 | 57 | |