Skip to content

Commit

Permalink
Use a shared data type for FR citations.
Browse files Browse the repository at this point in the history
  • Loading branch information
cmc333333 committed Feb 5, 2017
1 parent e2505af commit 8c551b5
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 29 deletions.
3 changes: 2 additions & 1 deletion regparser/commands/annual_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from regparser.history.annual import find_volume
from regparser.history.versions import Version
from regparser.index import dependency, entry
from regparser.notice.citation import Citation
from regparser.notice.fake import build as build_fake_notice
from regparser.tree.gpo_cfr import builder

Expand Down Expand Up @@ -40,7 +41,7 @@ def create_version_entry_if_needed(volume, cfr_part):
if version_id not in [c.path[-1] for c in version_dir.sub_entries()]:
(version_dir / version_id).write(
Version(version_id, effective=volume.publication_date,
fr_volume=volume.vol_num, fr_page=1))
fr_citation=Citation(volume.vol_num, 1)))


@click.command()
Expand Down
2 changes: 1 addition & 1 deletion regparser/commands/full_issuance.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def process_version_if_needed(cfr_title, cfr_part, version_id):
if deps.is_stale(version_entry):
notice_xml = notice_entry.read()
version = Version(version_id, notice_xml.effective,
notice_xml.fr_volume, notice_xml.start_page)
notice_xml.fr_citation)
version_entry.write(version)


Expand Down
4 changes: 2 additions & 2 deletions regparser/commands/proposal_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ def proposal_versions(doc_number):
raise dependency.Missing(str(notice), str(notice))

notice = notice.read()
version = Version(doc_number, effective=None, fr_volume=notice.fr_volume,
fr_page=notice.start_page)
version = Version(doc_number, effective=None,
fr_citation=notice.fr_citation)

for cfr_title, cfr_part in notice.cfr_ref_pairs:
version_entry = entry.Version(cfr_title, cfr_part, doc_number)
Expand Down
3 changes: 1 addition & 2 deletions regparser/commands/versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ def write_to_disk(xml, version_entry, delay=None):
"""Serialize a Version instance to disk"""
effective = xml.effective if delay is None else delay.until
if effective:
version = Version(xml.version_id, effective, xml.fr_volume,
xml.start_page)
version = Version(xml.version_id, effective, xml.fr_citation)
version_entry.write(version)
else:
logger.warning("No effective date for this rule: %s. Skipping",
Expand Down
9 changes: 2 additions & 7 deletions regparser/grammar/delays.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from six.moves import reduce

from regparser.grammar import utils
from regparser.notice.citation import Citation as NoticeCitation


@attr.attrs(slots=True, frozen=True)
Expand All @@ -20,12 +21,6 @@ class Delayed(object):
"""Placeholder token"""


@attr.attrs(slots=True, frozen=True)
class Notice(object):
volume = attr.attrib()
page = attr.attrib()


effective_date = (
utils.Marker("effective") + utils.Marker("date")
).setParseAction(EffectiveDate)
Expand All @@ -35,7 +30,7 @@ class Notice(object):
Word(string.digits) +
utils.Marker('FR') +
Word(string.digits)
).setParseAction(lambda m: Notice(int(m[0]), int(m[1])))
).setParseAction(lambda m: NoticeCitation(m[0], m[1]))


delayed = utils.Marker("delayed").setParseAction(Delayed)
Expand Down
5 changes: 3 additions & 2 deletions regparser/history/delays.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
from itertools import dropwhile, takewhile

from regparser.grammar.delays import tokenizer as delay_tokenizer
from regparser.grammar.delays import Delayed, EffectiveDate, Notice
from regparser.grammar.delays import Delayed, EffectiveDate
from regparser.notice.citation import Citation as NoticeCitation


class FRDelay(namedtuple('FRDelay', ['volume', 'page', 'delayed_until'])):
Expand All @@ -29,7 +30,7 @@ def delays_in_sentence(sent):

frs = list(takewhile(lambda t: not isinstance(t, Delayed), tokens))
tokens = tokens[len(frs):]
frs = [t for t in frs if isinstance(t, Notice)]
frs = [t for t in frs if isinstance(t, NoticeCitation)]

if not frs or not tokens:
return []
Expand Down
24 changes: 12 additions & 12 deletions regparser/history/versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
from collections import namedtuple
from datetime import datetime

from regparser.notice.citation import Citation


class Version(namedtuple('Version',
['identifier', 'effective', 'fr_volume', 'fr_page'])):
['identifier', 'effective', 'fr_citation'])):
@property
def is_final(self):
return bool(self.effective)
Expand All @@ -13,11 +16,10 @@ def is_proposal(self):
return not self.is_final

def json(self):
result = self._asdict()
result = {'identifier': self.identifier,
'fr_citation': self.fr_citation.asdict()}
if self.is_final:
result['effective'] = self.effective.isoformat()
else:
del result['effective']

return json.dumps(result)

Expand All @@ -27,22 +29,20 @@ def from_json(json_str):
effective = json_dict.get('effective')
if effective:
effective = datetime.strptime(effective, '%Y-%m-%d').date()
json_dict['effective'] = effective
return Version(**json_dict)
return Version(json_dict['identifier'], effective,
Citation(**json_dict['fr_citation']))

def __lt__(self, other):
"""Linearizing versions requires knowing not only relevant dates and
identifiers, but also which versions are from final rules and which
are just proposals"""
if self.is_final and other.is_final:
left = (self.effective, self.fr_volume, self.fr_page,
self.identifier)
right = (other.effective, other.fr_volume, other.fr_page,
other.identifier)
left = (self.effective, self.fr_citation, self.identifier)
right = (other.effective, other.fr_citation, other.identifier)
return left < right
else: # at least one of the two is a proposal
left = (self.fr_volume, self.fr_page, self.identifier)
right = (other.fr_volume, other.fr_page, other.identifier)
left = (self.fr_citation, self.identifier)
right = (other.fr_citation, other.identifier)
return left < right

@staticmethod
Expand Down
13 changes: 13 additions & 0 deletions regparser/notice/citation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import attr


@attr.attrs(slots=True, frozen=True)
class Citation(object):
volume = attr.attrib(convert=int)
page = attr.attrib(convert=int)

def formatted(self):
return '{0} FR {1}'.format(self.volume, self.page)

def asdict(self):
return attr.asdict(self)
5 changes: 3 additions & 2 deletions regparser/notice/xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from regparser.history.delays import delays_in_sentence
from regparser.index.http_cache import http_client
from regparser.notice.amendments.fetch import fetch_amendments
from regparser.notice.citation import Citation
from regparser.notice.dates import fetch_dates
from regparser.tree.xml_parser.xml_wrapper import XMLWrapper

Expand Down Expand Up @@ -339,7 +340,7 @@ def amendments(self):

@property
def fr_citation(self):
return '{0} FR {1}'.format(self.fr_volume, self.start_page)
return Citation(self.fr_volume, self.start_page)

@property
def title(self):
Expand Down Expand Up @@ -397,7 +398,7 @@ def as_dict(self):
'cfr_title': cfr_ref.title,
'dockets': self.docket_ids,
'document_number': self.version_id,
'fr_citation': self.fr_citation,
'fr_citation': self.fr_citation.formatted(),
'fr_url': self.fr_html_url,
'fr_volume': self.fr_volume,
# @todo - SxS depends on this; we should remove soon
Expand Down

0 comments on commit 8c551b5

Please sign in to comment.