72 lines
4.2 KiB
Python
72 lines
4.2 KiB
Python
"""Stable event identity within a venue/year/track, independent of paper identity."""
|
|
import json
|
|
import re
|
|
|
|
|
|
def has_event_key(c):
|
|
if getattr(c, 'postgres', False):
|
|
return bool(c.execute("SELECT 1 FROM information_schema.columns WHERE table_schema=current_schema() AND table_name='editions' AND column_name='event_key'").fetchone())
|
|
return any(row[1] == 'event_key' for row in c.execute('PRAGMA table_info(editions)'))
|
|
|
|
|
|
def validate_event_key(value):
|
|
if value is not None and (not isinstance(value, str) or
|
|
(value != '' and not re.fullmatch(r'[a-z0-9][a-z0-9._:-]{0,79}', value))):
|
|
raise ValueError('Invalid conference event_key')
|
|
return value
|
|
|
|
|
|
def pinned_www_fall(source, metadata):
|
|
from paper_atlas.collectors.dblp import XML_SHA
|
|
b = metadata.get('bibliography') or {}
|
|
urls = b.get('url') or []
|
|
return (source == 'dblp' and metadata.get('snapshot_sha256') == XML_SHA
|
|
and metadata.get('bibliographic_year') == 1995
|
|
and str(metadata.get('proceedings_key', '')).startswith('conf/www/')
|
|
and b.get('booktitle') == ['WWW (Fall)'] and len(urls) == 1
|
|
and urls[0].split('#')[0] == 'db/conf/www/www1995f.html')
|
|
|
|
|
|
def find_edition(store, venue_id, venue, year, track, record, external_id,
|
|
event_key=None, *, create=True):
|
|
c = store.conn
|
|
validate_event_key(event_key)
|
|
enabled = has_event_key(c) if getattr(store, 'event_identity', None) is None else store.event_identity
|
|
known_multi = venue.upper() == 'WWW' and int(year) in (1994, 1995)
|
|
source = c.execute('SELECT src.name,r.metadata_json FROM source_records r JOIN sources src ON src.id=r.source_id WHERE r.id=?', (record,)).fetchone()
|
|
inferred = ('www-1995-fall' if known_multi and int(year) == 1995 and source
|
|
and pinned_www_fall(source[0], json.loads(source[1])) else None)
|
|
if inferred:
|
|
if event_key is not None and event_key != inferred:
|
|
raise ValueError('event_key conflicts with pinned WWW Fall source evidence')
|
|
event_key = inferred
|
|
if not enabled:
|
|
if event_key or known_multi:
|
|
raise ValueError('Explicit event identity migration required before this conference import')
|
|
row = c.execute('SELECT id FROM editions WHERE venue_id=? AND year=? AND track=?', (venue_id, year, track)).fetchone()
|
|
if row or not create:
|
|
return row[0] if row else None
|
|
c.execute('INSERT INTO editions(venue_id,year,track) VALUES(?,?,?) ON CONFLICT DO NOTHING', (venue_id, year, track))
|
|
return c.execute('SELECT id FROM editions WHERE venue_id=? AND year=? AND track=?', (venue_id, year, track)).fetchone()[0]
|
|
anchored = c.execute('''SELECT DISTINCT e.id,e.event_key FROM editions e JOIN submissions s ON s.edition_id=e.id
|
|
JOIN submission_sources ss ON ss.submission_id=s.id WHERE e.venue_id=? AND e.year=? AND e.track=?
|
|
AND ss.source_record_id=? AND ss.source_submission_id=?''', (venue_id, year, track, record, external_id)).fetchall()
|
|
if len(anchored) > 1:
|
|
raise ValueError('Source record already has ambiguous conference events')
|
|
if anchored:
|
|
if event_key is not None and event_key != anchored[0][1]:
|
|
raise ValueError('Cannot move an existing source to another conference event')
|
|
event_key = anchored[0][1]
|
|
if event_key is None:
|
|
rows = c.execute('SELECT event_key FROM editions WHERE venue_id=? AND year=? AND track=?', (venue_id, year, track)).fetchall()
|
|
if len(rows) > 1 or any(row[0] for row in rows):
|
|
raise ValueError('Explicit event_key required; conference event is ambiguous')
|
|
event_key = ''
|
|
if known_multi and not event_key:
|
|
raise ValueError('Explicit event_key required for same-year WWW events')
|
|
row = c.execute('SELECT id FROM editions WHERE venue_id=? AND year=? AND track=? AND event_key=?', (venue_id, year, track, event_key)).fetchone()
|
|
if row or not create:
|
|
return row[0] if row else None
|
|
c.execute('INSERT INTO editions(venue_id,year,track,event_key) VALUES(?,?,?,?) ON CONFLICT DO NOTHING', (venue_id, year, track, event_key))
|
|
return c.execute('SELECT id FROM editions WHERE venue_id=? AND year=? AND track=? AND event_key=?', (venue_id, year, track, event_key)).fetchone()[0]
|