Skip to content

Commit da78082

Browse files
committed
Extract metadata from plain ascii file. Fixes ietf-tools#586
- Legacy-Id: 2821
1 parent 020e7f8 commit da78082

2 files changed

Lines changed: 88 additions & 9 deletions

File tree

ietf/submit/parsers/base.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import datetime
21
import re
32

43

@@ -9,9 +8,13 @@ class MetaDataDraft(object):
98
revision = None
109
filename = None
1110
group = None
11+
filesize = None
12+
first_two_pages = None
13+
page_count = None
14+
submission_date = None
15+
creation_date = None
1216
authors = None
1317

14-
1518
class ParseInfo(object):
1619

1720
def __init__(self):
@@ -50,8 +53,6 @@ def parse(self):
5053
method = getattr(self, attr, None)
5154
if callable(method):
5255
method()
53-
if self.parsed_info.errors:
54-
return self.parsed_info
5556
return self.parsed_info
5657

5758
def parse_critical_000_invalid_chars_in_filename(self):

ietf/submit/parsers/plain_parser.py

Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import datetime
12
import re
23

3-
from ietf.idtracker.models import InternetDraft
4+
from ietf.idtracker.models import InternetDraft, IETFWG
45
from ietf.submit.error_manager import MainErrorManager
56
from ietf.submit.parsers.base import FileParser
67

@@ -10,9 +11,24 @@
1011

1112
class PlainParser(FileParser):
1213

13-
def parse_critical_max_size(self):
14+
def __init__(self, fd):
15+
super(PlainParser, self).__init__(fd)
16+
self.lines = fd.file.readlines()
17+
fd.file.seek(0)
18+
self.full_text= self.normalize_text(''.join(self.lines))
19+
20+
def normalize_text(self, text):
21+
text = re.sub(".\x08", "", text) # Get rid of inkribbon backspace-emphasis
22+
text = text.replace("\r\n", "\n") # Convert DOS to unix
23+
text = text.replace("\r", "\n") # Convert MAC to unix
24+
text = text.strip()
25+
return text
26+
27+
def parse_critical_000_max_size(self):
1428
if self.fd.size > MAX_PLAIN_FILE_SIZE:
1529
self.parsed_info.add_error(MainErrorManager.get_error_str('EXCEEDED_SIZE'))
30+
self.parsed_info.metadraft.filesize = self.fd.size
31+
self.parsed_info.metadraft.submission_date = datetime.date.today()
1632

1733
def parse_critical_001_file_charset(self):
1834
import magic
@@ -34,7 +50,7 @@ def parse_critical_002_filename(self):
3450
match = draftre.search(line)
3551
if not match:
3652
continue
37-
filename = match.group(0)
53+
filename = match.group(1)
3854
filename = re.sub('^[^\w]+', '', filename)
3955
filename = re.sub('[^\w]+$', '', filename)
4056
filename = re.sub('\.txt$', '', filename)
@@ -43,7 +59,7 @@ def parse_critical_002_filename(self):
4359
self.parsed_info.add_error('Filename contains non alpha-numeric character: %s' % ', '.join(set(extra_chars)))
4460
match_revision = revisionre.match(filename)
4561
if match_revision:
46-
self.parsed_info.metadraft.revision = match_revision.group(0)
62+
self.parsed_info.metadraft.revision = match_revision.group(1)
4763
filename = re.sub('-\d+$', '', filename)
4864
self.parsed_info.metadraft.filename = filename
4965
return
@@ -69,7 +85,65 @@ def parse_critical_003_wg(self):
6985
else:
7086
self.parsed_info.metadraft.wg = IETFWG.objects.get(pk=NONE_WG_PK)
7187

72-
def parse_critical_authors(self):
88+
def parse_normal_000_first_two_pages(self):
89+
first_pages = ''
90+
for line in self.lines:
91+
first_pages += line
92+
if re.search('\[[Pp]age 2', line):
93+
break
94+
self.parsed_info.metadraft.first_two_pages = self.normalize_text(first_pages)
95+
96+
def parse_normal_001_title(self):
97+
pages = self.parsed_info.metadraft.first_two_pages or self.full_text
98+
title_re = re.compile('(.+\n){1,3}(\s+<?draft-\S+\s*\n)')
99+
match = title_re.search(pages)
100+
if match:
101+
title = match.group(1)
102+
title = title.strip()
103+
self.parsed_info.metadraft.title = title
104+
return
105+
# unusual title extract
106+
unusual_title_re = re.compile('(.+\n|.+\n.+\n)(\s*status of this memo\s*\n)', re.I)
107+
match = unusual_title_re.search(pages)
108+
if match:
109+
title = match.group(1)
110+
title = title.strip()
111+
self.parsed_info.metadraft.title = title
112+
113+
def parse_normal_002_num_pages(self):
114+
pagecount = len(re.findall("\[[Pp]age [0-9ixldv]+\]", self.full_text)) or len(self.lines)/58
115+
self.parsed_info.metadraft.pagecount = pagecount
116+
117+
def parse_normal_003_creation_date(self):
118+
month_names = [ 'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec' ]
119+
date_regexes = [
120+
r'\s{3,}(?P<month>\w+)\s+(?P<day>\d{1,2}),?\s+(?P<year>\d{4})',
121+
r'\s{3,}(?P<day>\d{1,2}),?\s+(?P<month>\w+)\s+(?P<year>\d{4})',
122+
r'\s{3,}(?P<day>\d{1,2})-(?P<month>\w+)-(?P<year>\d{4})',
123+
# 'October 2008' - default day to today's.
124+
r'\s{3,}(?P<month>\w+)\s+(?P<year>\d{4})',
125+
]
126+
127+
first = self.parsed_info.metadraft.first_two_pages or self.full_text
128+
for regex in date_regexes:
129+
match = re.search(regex, first)
130+
if match:
131+
md = match.groupdict()
132+
mon = md['month'][0:3].lower()
133+
day = int( md.get( 'day', datetime.date.today().day ) )
134+
year = int( md['year'] )
135+
try:
136+
month = month_names.index( mon ) + 1
137+
self.parsed_info.metadraft.creation_date = datetime.date(year, month, day)
138+
return
139+
except ValueError:
140+
# mon abbreviation not in _MONTH_NAMES
141+
# or month or day out of range
142+
continue
143+
self.parsed_info.add_warning('creation_date', 'Creation Date field is empty or the creation date is not in a proper format.')
144+
145+
146+
def parse_normal_004_authors(self):
73147
"""
74148
comes from http://svn.tools.ietf.org/svn/tools/ietfdb/branch/idsubmit/ietf/utils/draft.py
75149
"""
@@ -333,3 +407,7 @@ def begpage(pages, page, line=None):
333407
self.parsed_info.errors.append("Draft authors could not be found.")
334408

335409
return authors
410+
411+
412+
def parse_normal_005_abstract(self):
413+
pass

0 commit comments

Comments
 (0)