Changeset 206

Show
Ignore:
Timestamp:
09/14/08 19:39:10 (4 months ago)
Author:
rgrp
Message:

[factlet/new][l]: implement factlet creation from a wikipedia url in WUI.

  • dbpedia:
    • put in tests for to_factlet and fix issues with that.
    • fix up verbose support in Describe
  • factlet: support for factlet creation from a wikipedia url + test.
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/microfacts/controllers/factlet.py

    r202 r206  
     1import logging 
    12import simplejson as sj 
    23import genshi 
     4 
     5logging.getLogger(__name__) 
    36 
    47from microfacts.lib.base import * 
    58from microfacts.modes import * 
    69import microfacts.lib.json 
     10 
     11# not everyone will have the libraries installed for working with dbpedia 
     12dbpedia_enabled = True 
     13try: 
     14    from microfacts.getdata.dbpedia import * 
     15except: 
     16    dbpedia_enabled = False 
    717 
    818class FactletController(BaseController): 
     
    3444 
    3545    def new(self): 
    36         return render('factlet/new') 
     46        c.dbpedia_enabled = dbpedia_enabled 
     47        if not 'commit' in request.params: # no form submitted 
     48            return render('factlet/new') 
    3749 
    38     def create(self): 
    39         if 'title' in request.params: 
     50        title = request.params.getone('title').strip() 
     51        url = request.params.getone('url').strip() 
     52        if title: 
     53            logger.debug('Creating new factlet with title: %s' % title) 
    4054            registry_path = '/factlet' 
    4155            entity_data = { 
     
    5064                h.redirect_to(controller='factlet', action='update', 
    5165                        id=c.factlet.id) 
    52             else: 
     66            else: # this should really tell the user what was wrong 
    5367                abort(self.mode.response_code) 
     68        elif url: 
     69            logger.debug('Creating new factlet from url: %s' % url) 
     70            # TODO: check dbpedia_enabled is True? 
     71            d = microfacts.getdata.dbpedia.Describe() 
     72            d.execute(url) 
     73            try: 
     74                c.factlet = d.to_factlet() 
     75            except Exception, inst: 
     76                c.error = str(inst) 
     77                return render('factlet/new') 
     78            h.redirect_to(controller='factlet', action='update', 
     79                    id=c.factlet.id) 
    5480        else: 
     81            # Error? 
     82            # c.error = 'No title or url supplied' 
    5583            return render('factlet/new') 
     84 
    5685 
    5786    def read_core(self, id): 
  • trunk/microfacts/getdata/dbpedia.py

    r204 r206  
    7575class Describe: 
    7676 
    77     def __init__(self): 
     77    def __init__(self, verbose=False): 
    7878        self.results = [] 
    79         self.verbose = False 
     79        self.verbose = verbose 
    8080        self.language = 'en' 
    8181 
    8282    def execute(self, uri): 
     83        if 'wikipedia.org' in uri: 
     84            uri = self._convert_wikipedia_url(uri) 
    8385        self.uri = uri 
    8486        query2 = PREFIXES + ''' 
     
    9395        # print self.results.all_nodes() 
    9496 
    95     def to_str(self, verbose=False): 
     97    def _convert_wikipedia_url(self, url): 
     98        import urlparse 
     99        path = urlparse.urlparse(url)[2] 
     100        name = path.split('/')[-1] 
     101        dbpedia_uri = 'http://dbpedia.org/resource/' + name 
     102        return dbpedia_uri 
     103 
     104    def to_str(self): 
    96105        output = self.uri + '\n\n' 
    97         if verbose: 
     106        if self.verbose: 
    98107            for s,p,o in self.results: 
    99108                output += u'%s, %s, %s\n' % (s,p,o) 
     
    109118        kwds = { 'title' : None, 
    110119                'description' : None, 
    111                 'start' : None
    112                 'end' : None
     120                'start' : ''
     121                'end' : ''
    113122                'source': None, 
    114123                'place': [], 
    115124                'long': None, 
    116125                'lat': None, 
    117                 'location' : {'type': 'Point', 'coordinates': [None, None]}, 
    118                 'image': [], 
    119                 'license':  'GFDL' 
     126                'image_urls': [], 
     127                'license':  u'GFDL' 
    120128                } 
    121129        for s,p,o in self.results: 
     
    159167                kwds['source'] = unicode(o) 
    160168            elif str(p) == 'http://xmlns.com/foaf/0.1/img': 
    161                 kwds['image'] = kwds['image'] + [unicode(o)] 
     169                kwds['image_urls'] = kwds['image_urls'] + [unicode(o)] 
    162170 
    163171        # get lat/long indirectly ... 
     
    177185                    # once we have one set we don't need any more ... 
    178186                    break 
    179         kwds['location']['coordinates'][0] = kwds['long'] 
    180         kwds['location']['coordinates'][1] = kwds['lat'] 
    181187        return kwds  
    182188 
     
    214220                    raise ValueError('%s is not a useable date object' % o) 
    215221        except Exception, inst: 
    216             print 'Problem with extracting date from: %s' % o 
    217             try: 
    218                 print inst 
    219             except: 
    220                 pass 
     222            if self.verbose: 
     223                print 'Problem with extracting date from: %s' % o 
     224                try: 
     225                    print inst 
     226                except: 
     227                    pass 
    221228        return dates 
    222229 
     
    228235        from microfacts.lib.json import FactletConverter 
    229236        conv = FactletConverter() 
    230         conv.to_domain_object(kwds) 
    231         model.Session.flush() 
     237        # convert kwds dates back to strings ... 
     238        kwds['start'] = str(kwds['start']) 
     239        kwds['end'] = str(kwds['end']) 
     240        # convert lists to non-lists (very crudely) 
     241        if kwds['image_urls']: 
     242            kwds['image'] = kwds['image_urls'][0] 
     243        if kwds['long']: 
     244            kwds['location'] = { 'type': 'Point', coordinates:None } 
     245            kwds['location']['coordinates'] = [ kwds['long'], kwds['lat'] ] 
     246        fct = conv.to_domain_object(kwds) 
     247        return fct  
    232248 
    233249 
    234250def describe(uri, verbose=False): 
    235     d = Describe(
     251    d = Describe(verbose
    236252    d.execute(uri) 
    237     return d.to_str(verbose=verbose
     253    return d.to_str(
    238254 
    239255 
  • trunk/microfacts/lib/cli.py

    r204 r206  
    111111    describe <uri> 
    112112    search <category-name> 
    113     wp <wikipedia-url> 
    114113     
    115114Examples: 
    116115 
    117116    describe http://dbpedia.org/resource/Admiralty_Islands_campaign 
     117    describe http://en.wikipedia.org/wiki/Napoleon_I_of_France 
    118118    search Category:Battles_and_operations_of_World_War_II 
    119     wp http://en.wikipedia.org/wiki/Napoleon_I_of_France 
    120119    ''' 
    121120    summary = __doc__.split('\n')[0] 
     
    141140            category = self.args[1] 
    142141            result = dbp.category_search(category) 
    143         elif cmd == 'wp': 
    144             import urlparse 
    145             url = self.args[1] 
    146             path = urlparse.urlparse(url)[2] 
    147             name = path.split('/')[-1] 
    148             dbpedia_uri = 'http://dbpedia.org/resource/' + name 
    149             result = dbp.describe(dbpedia_uri, verbose=self.verbose) 
    150142        else: 
    151143            msg = 'Command %s not recognized' % cmd 
  • trunk/microfacts/model/__init__.py

    r205 r206  
    186186 
    187187mapper(User, user_table, properties={ 
    188     'factlets':orm.relation(Factlet, secondary=user_2_factlet, backref='owners'), 
    189     'threads':orm.relation(Thread, secondary=user_2_thread, backref='owners'), 
     188    'factlets':orm.relation( 
     189        Factlet, 
     190        secondary=user_2_factlet, 
     191        backref='owners'), 
     192    'threads':orm.relation(Thread, 
     193        secondary=user_2_thread, 
     194        backref='owners'), 
    190195    }) 
  • trunk/microfacts/templates/factlet/layout.html

    r202 r206  
    2323          <li>${h.link_to('Home', h.url_for(controller='factlet', action='index', id=None))}</li> 
    2424          <li>${h.link_to('List', h.url_for(controller='factlet', action='list', id=None))}</li> 
    25           <li>${h.link_to('New', h.url_for(controller='factlet', action='create', id=None))}</li> 
     25          <li>${h.link_to('Create', h.url_for(controller='factlet', action='new', id=None))}</li> 
    2626        </ul> 
    2727      </aside> 
  • trunk/microfacts/templates/factlet/new.html

    r52 r206  
    1 <!DOCTYPE html> 
    21<html 
    32  xmlns="http://www.w3.org/1999/xhtml" 
     
    109 
    1110  <head> 
    12     <title>New</title> 
     11    <title>Create</title> 
    1312  </head> 
    1413 
    1514  <body> 
    16     <h2>Register New Factlet</h2> 
    17     <p>Please choose a title for the factlet.</p> 
    18     <form action="${h.url_for(controller='factlet', action='create')}" method="post"> 
     15    <h2>Create a New Factlet</h2> 
     16    <p py:if="c.error"><strong>There was an error: ${c.error}</strong></p> 
     17    <form action="" method="post"> 
     18      <p>Please choose a title for the factlet.</p> 
    1919      <label for="title">Title:</label> 
    2020      ${XML(h.text_field('title', size=30))} 
    2121      <br /><br /> 
     22 
     23      <div py:strip="True" py:if="c.dbpedia_enabled"> 
     24 
     25      <p><strong>OR</strong> enter a Wikipedia (or DBPedia) url:</p> 
     26      <label for="url">Url:</label> 
     27      ${XML(h.text_field('url', size=30))} 
     28 
     29      <p class="desc">The factlet will be generated from the information in that 
     30      article.</p> 
     31      </div> 
     32 
    2233      ${XML(h.submit('Create new factlet'))} 
    2334    </form> 
  • trunk/microfacts/tests/functional/test_factlet.py

    r202 r206  
    166166        form = response.forms[0] 
    167167        form['title'] = self.title 
    168         response = form.submit(status=[302]) 
     168        # even though only one button if you do not specify name 'commit' is 
     169        # not in post params (which messes up controller function) 
     170        response = form.submit('commit', status=[302]) 
    169171        response = response.follow() 
    170172        assert 'Factlets - Edit' in response, response 
     
    172174        assert self.ft 
    173175 
     176import microfacts.controllers.factlet 
     177class TestFactletCreateViaWikipedia(TestController): 
     178 
     179    # nose attributes 
     180    __test__ = microfacts.controllers.factlet.dbpedia_enabled 
     181    external = True 
     182    tags = [ 'dbpedia' ] 
     183 
     184    title = u'Philip II of Spain' 
     185    url = u'http://en.wikipedia.org/wiki/Philip_II_of_Spain' 
     186 
     187    def tearDown(self): 
     188        ft = model.Factlet.query.filter_by(source=self.url).one() 
     189        ft.delete() 
     190        model.Session.flush() 
     191        model.Session.remove() 
     192 
     193    def test_create(self): 
     194        path = url_for(controller='factlet', action='new') 
     195        response = self.app.get(path) 
     196        assert 'enter a Wikipedia (or DBPedia resouce) url:' 
     197        form = response.forms[0] 
     198        form['url'] = self.url 
     199        response = form.submit('commit', status=[302]) 
     200        response = response.follow() 
     201        assert 'Factlets - Edit' in response, response 
     202        self.ft = model.Factlet.query.filter_by(source=self.url).one() 
     203        assert self.ft.title == self.title 
     204        # May 21, 1527 (1527-05-21) 
     205        assert self.ft.start.year == 1527 
     206 
  • trunk/microfacts/tests/getdata/test_dbpedia.py

    r204 r206  
    11# not everyone will have the libraries installed for working with dbpedia 
     2dotest = True 
    23try: 
    34    from microfacts.getdata.dbpedia import * 
    45except: 
    5     pass 
     6    dotest = False 
    67 
    7 class TestDescribe: 
    8     __test__ = False 
     8class DbpediaBase(object): 
     9    __test__ = dotest 
     10    external = True 
     11    tags = [ 'dbpedia' ] 
     12 
     13class TestDescribe(DbpediaBase): 
    914 
    1015    def test_extract_1(self): 
     
    3035        assert kwds['title'] == u'Invasion of Normandy' 
    3136 
    32 class TestDescribe2(object): 
    33     __test__ = False 
     37class TestDescribe2(DbpediaBase): 
    3438 
    3539    @classmethod 
    3640    def setup_class(self): 
    3741        uri3 = 'http://dbpedia.org/resource/Battle_of_Austerlitz' 
    38         d = Describe() 
    39         d.execute(uri3) 
    40         self.kwds = d.extract(recurse_for_location=True) 
     42        self.d = Describe() 
     43        self.d.execute(uri3) 
     44        self.kwds = self.d.extract(recurse_for_location=True) 
     45        self.fct = None 
     46        self.start = datetime.datetime(1805, 12, 2) 
     47 
     48    @classmethod 
     49    def teardown_class(self): 
     50        import microfacts.model as model 
     51        if self.fct: 
     52            self.fct.delete() 
     53        model.Session.flush() 
     54        model.Session.remove() 
    4155 
    4256    def test_date(self): 
    43         assert self.kwds['start'] == datetime.datetime(1805, 12, 2) 
     57        assert self.kwds['start'] == self.start  
    4458 
    4559    def test_source(self): 
     
    5064        assert self.kwds['long'] == 16.76361083984375 
    5165 
     66    def test_to_factlet(self): 
     67        self.fct = self.d.to_factlet() 
     68        assert self.fct.id 
     69        long = round(self.fct.location.x,1) 
     70        assert long == 16.8, long 
     71        assert self.fct.start == self.start 
     72 
     73 
     74class TestDescribeWikipedia(DbpediaBase): 
     75 
     76    uri = 'http://en.wikipedia.org/wiki/Battle_of_Austerlitz' 
     77 
     78    def test__convert_wikipedia_url(self): 
     79        d = Describe() 
     80        out = d._convert_wikipedia_url(self.uri) 
     81        assert out == 'http://dbpedia.org/resource/Battle_of_Austerlitz', out 
     82     
     83    def test_1(self): 
     84        d = Describe() 
     85        d.execute(self.uri) 
     86        self.kwds = d.extract() 
     87        assert self.kwds['title'] == 'Battle of Austerlitz' 
     88        assert self.kwds['source'] == self.uri 
     89