def test_extract_pair(self): """Sequences of EXTRACT nodes should get joined""" with XMLBuilder("ROOT") as ctx: ctx.TAG1() ctx.EXTRACT("contents1") with ctx.EXTRACT("contents2"): ctx.TAG2() ctx.TAG3() ctx.EXTRACT("contents3") ctx.TAG4() ctx.EXTRACT("contents4") contents = "contents1\ncontents2<TAG2/><TAG3/>" with XMLBuilder("ROOT") as ctx2: ctx2.TAG1() ctx2.child_from_string('<EXTRACT>{}</EXTRACT>'.format(contents)) ctx2.EXTRACT("contents3") # First pass will only merge one ctx2.TAG4() ctx2.EXTRACT("contents4") self.assertTrue(self.et.extract_pair(ctx.xml[1])) self.assertEqual(ctx2.xml_str, ctx.xml_str) contents += "\ncontents3" with XMLBuilder("ROOT") as ctx3: ctx3.TAG1() ctx3.child_from_string('<EXTRACT>{}</EXTRACT>'.format(contents)) ctx3.TAG4() ctx3.EXTRACT("contents4") self.assertTrue(self.et.extract_pair(ctx.xml[1])) self.assertEqual(ctx3.xml_str, ctx.xml_str)
def test_extract_pair(): """Sequences of EXTRACT nodes should get joined""" with XMLBuilder("ROOT") as ctx: ctx.TAG1() ctx.EXTRACT("contents1") with ctx.EXTRACT("contents2"): ctx.TAG2() ctx.TAG3() ctx.EXTRACT("contents3") ctx.TAG4() ctx.EXTRACT("contents4") contents = "contents1\ncontents2<TAG2/><TAG3/>" with XMLBuilder("ROOT") as ctx2: ctx2.TAG1() ctx2.child_from_string('<EXTRACT>{0}</EXTRACT>'.format(contents)) ctx2.EXTRACT("contents3") # First pass will only merge one ctx2.TAG4() ctx2.EXTRACT("contents4") assert preprocessors.ExtractTags().extract_pair(ctx.xml[1]) assert ctx2.xml_str == ctx.xml_str contents += "\ncontents3" with XMLBuilder("ROOT") as ctx3: ctx3.TAG1() ctx3.child_from_string('<EXTRACT>{0}</EXTRACT>'.format(contents)) ctx3.TAG4() ctx3.EXTRACT("contents4") assert preprocessors.ExtractTags().extract_pair(ctx.xml[1]) assert ctx3.xml_str == ctx.xml_str
def test_rins(self): def rinstest(rins, expected, xml=None): if not xml: xml = self._dummy_notice() rins = rins or xml.derive_rins() xml.rins = rins self.assertEquals(expected, xml.rins) # From the metadata: rinstest(["2050-AG67"], ["2050-AG67"]) # From the XML: with XMLBuilder("ROOT") as root: root.RIN("RIN 2050-AG68") xml = notice_xml.NoticeXML(root.xml) rinstest([], ["2050-AG68"], xml=xml) # From the XML, no prefix: with XMLBuilder("ROOT") as root: root.RIN(" 2050-AG69") xml = notice_xml.NoticeXML(root.xml) rinstest([], ["2050-AG69"], xml=xml) # Two numbers: rinstest(["2050-AG60", "2050-AG61"], ["2050-AG60", "2050-AG61"]) # Two numbers XML: with XMLBuilder("ROOT") as root: root.RIN("RIN 2050-AG60") root.RIN("RIN 2050-AG61") xml = notice_xml.NoticeXML(root.xml) rinstest([], ["2050-AG60", "2050-AG61"], xml=xml)
def test_docket_ids(self): def ditest(dis, expected, xml=None): if not xml: xml = self._dummy_notice() dis = dis or xml.derive_docket_ids() xml.docket_ids = dis self.assertEquals(expected, xml.docket_ids) # From the metadata: ditest(["EPA-HQ-SFUND-2010-1086"], ["EPA-HQ-SFUND-2010-1086"]) # From the XML: with XMLBuilder("ROOT") as root: root.DEPDOC("[EPA-HQ-SFUND-2010-1086]") xml = notice_xml.NoticeXML(root.xml) ditest([], ["EPA-HQ-SFUND-2010-1086"], xml=xml) # From the XML, two docket ids: with XMLBuilder("ROOT") as root: root.DEPDOC("[EPA-HQ-SFUND-2010-1086; FRL-9925-69-OLEM]") xml = notice_xml.NoticeXML(root.xml) ditest([], ["EPA-HQ-SFUND-2010-1086", "FRL-9925-69-OLEM"], xml=xml) # Two docket ids, metadata: ditest(["EPA-HQ-SFUND-2010-1086", "FRL-9925-69-OLEM"], ["EPA-HQ-SFUND-2010-1086", "FRL-9925-69-OLEM"])
def ftnt_compare(original, expected): with XMLBuilder("ROOT") as ctx: ctx.child_from_string("<P>{}</P>".format(original)) with XMLBuilder("ROOT") as ctx2: ctx2.child_from_string("<P>{}</P>".format(expected)) self.fn.split_comma_footnotes(ctx.xml) self.assertEqual(ctx.xml_str, ctx2.xml_str)
def test_split_comma_footnotes(original, expected): """The XML will sometimes merge multiple references to footnotes into a single tag. Verify that they get split""" with XMLBuilder("ROOT") as ctx: ctx.child_from_string("<P>{0}</P>".format(original)) with XMLBuilder("ROOT") as ctx2: ctx2.child_from_string("<P>{0}</P>".format(expected)) preprocessors.Footnotes().split_comma_footnotes(ctx.xml) assert ctx.xml_str == ctx2.xml_str
def test_parse_interp(monkeypatch): interp_lib = Mock() monkeypatch.setattr(amendments, 'gpo_cfr', interp_lib) xmls = [] with XMLBuilder("REGTEXT") as ctx: with ctx.EXTRACT(): ctx.P("Something") ctx.STARS() ctx.HD("Supplement I") ctx.HD("A") ctx.T1("a") ctx.P("b") xmls.append(ctx.xml) with XMLBuilder("REGTEXT") as ctx: ctx.P("Something") ctx.STARS() with ctx.SUBSECT(): ctx.HD("Supplement I") ctx.HD("A") ctx.T1("a") ctx.P("b") xmls.append(ctx.xml) with XMLBuilder("REGTEXT") as ctx: ctx.AMDPAR("1. In Supplement I to part 111, under...") ctx.P("Something") ctx.STARS() ctx.HD("SUPPLEMENT I") ctx.HD("A") ctx.T1("a") ctx.P("b") xmls.append(ctx.xml) with XMLBuilder("REGTEXT") as ctx: ctx.AMDPAR("1. In Supplement I to part 111, under...") ctx.P("Something") ctx.STARS() with ctx.APPENDIX(): ctx.HD("SUPPLEMENT I") ctx.HD("A") ctx.T1("a") ctx.P("b") ctx.PRTPAGE() xmls.append(ctx.xml) for xml in xmls: amendments.parse_interp('111', xml) root, nodes = interp_lib.parse_from_xml.call_args[0] assert root.label == ['111', 'Interp'] assert [n.tag for n in nodes] == ['HD', 'T1', 'P']
def test_parse_interp(self, interpretations): xmls = [] with XMLBuilder("REGTEXT") as ctx: with ctx.EXTRACT(): ctx.P("Something") ctx.STARS() ctx.HD("Supplement I") ctx.HD("A") ctx.T1("a") ctx.P("b") xmls.append(ctx.xml) with XMLBuilder("REGTEXT") as ctx: ctx.P("Something") ctx.STARS() with ctx.SUBSECT(): ctx.HD("Supplement I") ctx.HD("A") ctx.T1("a") ctx.P("b") xmls.append(ctx.xml) with XMLBuilder("REGTEXT") as ctx: ctx.AMDPAR("1. In Supplement I to part 111, under...") ctx.P("Something") ctx.STARS() ctx.HD("SUPPLEMENT I") ctx.HD("A") ctx.T1("a") ctx.P("b") xmls.append(ctx.xml) with XMLBuilder("REGTEXT") as ctx: ctx.AMDPAR("1. In Supplement I to part 111, under...") ctx.P("Something") ctx.STARS() with ctx.APPENDIX(): ctx.HD("SUPPLEMENT I") ctx.HD("A") ctx.T1("a") ctx.P("b") ctx.PRTPAGE() xmls.append(ctx.xml) for xml in xmls: amendments.parse_interp('111', xml) root, nodes = interpretations.parse_from_xml.call_args[0] self.assertEqual(root.label, ['111', 'Interp']) self.assertEqual(['HD', 'T1', 'P'], [n.tag for n in nodes])
def test_process_amendments_restart_new_section(self): with XMLBuilder("ROOT") as ctx: with ctx.REGTEXT(PART="104", TITLE="12"): ctx.AMDPAR("1. In Supplement I to Part 104, comment " "22(a) is added") ctx.P("Content") with ctx.REGTEXT(PART="105", TITLE="12"): ctx.AMDPAR(u"3. In § 105.1, revise paragraph (b) to read as " u"follows:") with ctx.SECTION(): ctx.SECTNO(u"§ 105.1") ctx.SUBJECT("Purpose.") ctx.STARS() ctx.P("(b) This part carries out.") ParseAMDPARs().transform(ctx.xml) notice = {'cfr_parts': ['105']} build.process_amendments(notice, ctx.xml) self.assertEqual(2, len(notice['amendments'])) c22a, b = notice['amendments'] self.assertEqual(c22a.action, 'POST') self.assertEqual(b.action, 'PUT') self.assertEqual(c22a.label, ['104', '22', 'a', 'Interp']) self.assertEqual(b.label, ['105', '1', 'b'])
def setUp(self): super(CommandsFetchSxSTests, self).setUp() self.cli = CliRunner() with XMLBuilder("ROOT") as ctx: ctx.PRTPAGE(P="1234") ctx.CFR('12 CFR 1000') self.notice_xml = NoticeXML(ctx.xml)
def new_subpart_xml(self): with XMLBuilder("RULE") as ctx: with ctx.REGTEXT(PART="105", TITLE="12"): ctx.AMDPAR(u"3. In § 105.1, revise paragraph (b) to read as" u"follows:") with ctx.SECTION(): ctx.SECTNO(u"§ 105.1") ctx.SUBJECT("Purpose.") ctx.STARS() ctx.P("(b) This part carries out.") with ctx.REGTEXT(PART="105", TITLE="12"): ctx.AMDPAR("6. Add subpart B to read as follows:") with ctx.CONTENTS(): with ctx.SUBPART(): ctx.SECHD("Sec.") ctx.SECTNO("105.30") ctx.SUBJECT("First In New Subpart.") with ctx.SUBPART(): ctx.HD(u"Subpart B—Requirements", SOURCE="HED") with ctx.SECTION(): ctx.SECTNO("105.30") ctx.SUBJECT("First In New Subpart") ctx.P("For purposes of this subpart, the follow " "apply:") ctx.P('(a) "Agent" means agent.') ParseAMDPARs().transform(ctx.xml) return ctx.xml
def test_process_amendments_mix_regs(self): """Some notices apply to multiple regs. For now, just ignore the sections not associated with the reg we're focused on""" with XMLBuilder("ROOT") as ctx: with ctx.REGTEXT(PART="105", TITLE="12"): ctx.AMDPAR(u"3. In § 105.1, revise paragraph (a) to read as " u"follows:") with ctx.SECTION(): ctx.SECTNO(u"§ 105.1") ctx.SUBJECT("105Purpose.") ctx.P("(a) 105Content") with ctx.REGTEXT(PART="106", TITLE="12"): ctx.AMDPAR(u"3. In § 106.3, revise paragraph (b) to read as " u"follows:") with ctx.SECTION(): ctx.SECTNO(u"§ 106.3") ctx.SUBJECT("106Purpose.") ctx.P("(b) Content") ParseAMDPARs().transform(ctx.xml) notice = {'cfr_parts': ['105', '106']} build.process_amendments(notice, ctx.xml) self.assertEqual(2, len(notice['changes'])) self.assertTrue('105-1-a' in notice['changes']) self.assertTrue('106-3-b' in notice['changes'])
def test_incorrect_ps(self): """Supplement I AMDPARs are not always labeled as should be""" with XMLBuilder("PART") as ctx: with ctx.REGTEXT(): ctx.AMDPAR(u"1. In § 105.1, revise paragraph (b):") with ctx.SECTION(): ctx.STARS() ctx.P("(b) Content") ctx.P("2. In Supplement I to Part 105,") ctx.P("A. Under Section 105.1, 1(b), paragraph 2 is revised") ctx.P("The revisions are as follows") ctx.HD("Supplement I to Part 105", SOURCE="HD1") ctx.STARS() with ctx.P(): ctx.E("1(b) Heading", T="03") ctx.STARS() ctx.P("2. New Context") preprocessors.SupplementAMDPar().transform(ctx.xml) # Note that the SECTION paragraphs were not converted self.assertEqual([amd.text for amd in ctx.xml.xpath("//AMDPAR")], [ u"1. In § 105.1, revise paragraph (b):", "2. In Supplement I to Part 105,", "A. Under Section 105.1, 1(b), paragraph 2 is revised", "The revisions are as follows" ])
def test_build_from_4_section_reserved_range(self): with XMLBuilder("SECTION") as ctx: ctx.SECTNO(u"§§ 8675.309-8675.312") ctx.RESERVED("[Reserved]") n309 = reg_text.build_from_section('8675', ctx.xml)[0] self.assertEqual(n309.label, ['8675', '309']) self.assertEqual(u'§§ 8675.309-312 [Reserved]', n309.title)
def test_has_requirments(): """Validate that certain attributes are required""" root_attrs = { "eregs-version-id": "vvv", "fr-volume": 124, "fr-start-page": 44, "fr-end-page": 55 } with XMLBuilder("ROOT", **root_attrs) as ctx: ctx.DATES(**{"eregs-published-date": "2005-05-05"}) notice_xml = NoticeXML(ctx.xml_copy()) assert import_notice.has_requirements(notice_xml) notice_xml = NoticeXML(ctx.xml_copy()) del notice_xml.xml.attrib['eregs-version-id'] assert not import_notice.has_requirements(notice_xml) notice_xml = NoticeXML(ctx.xml_copy()) del notice_xml.xml.attrib['fr-volume'] assert not import_notice.has_requirements(notice_xml) notice_xml = NoticeXML(ctx.xml_copy()) del notice_xml.xml.attrib['fr-start-page'] assert not import_notice.has_requirements(notice_xml) notice_xml = NoticeXML(ctx.xml_copy()) del notice_xml.xml.xpath('//DATES')[0].attrib['eregs-published-date'] assert not import_notice.has_requirements(notice_xml)
def test_process_amendments_multiple_sections(): """Regression test verifying multiple SECTIONs in the same REGTEXT""" amdpar1 = "1. Modify § 111.22 by revising paragraph (b)" amdpar2 = "2. Modify § 111.33 by revising paragraph (c)" with XMLBuilder("REGTEXT", PART="111") as ctx: ctx.AMDPAR(amdpar1) with ctx.SECTION(): ctx.SECTNO("§ 111.22") ctx.SUBJECT("Subject Here.") ctx.STARS() ctx.P("(b) Revised second paragraph") ctx.AMDPAR(amdpar2) with ctx.SECTION(): ctx.SECTNO("§ 111.33") ctx.SUBJECT("Another Subject") ctx.STARS() ctx.P("(c) Revised third paragraph") preprocess_amdpars(ctx.xml) amd1, amd2 = fetch.fetch_amendments(ctx.xml) assert amd1['instruction'] == amdpar1 assert amd1['cfr_part'] == '111' assert ['111-22-b'] == [c[0] for c in amd1['changes']] assert amd2['instruction'] == amdpar2 assert amd2['cfr_part'] == '111' assert ['111-33-c'] == [c[0] for c in amd2['changes']]
def test_process_same_sub_level(): with XMLBuilder('APPENDIX') as ctx: ctx.HD("Appendix A to Part 1111-Awesome", SOURCE='HED') ctx.P("1. 1 1 1") ctx.P("a. 1a 1a 1a") ctx.P("b. 1b 1b 1b") ctx.P("c. 1c 1c 1c") ctx.P("d. 1d 1d 1d") ctx.P("e. 1e 1e 1e") ctx.P("f. 1f 1f 1f") ctx.P("2. 2 2 2") ctx.P("a. 2a 2a 2a") ctx.P("i. 2ai 2ai 2ai") ctx.P("ii. 2aii 2aii 2aii") ctx.P("a. 2aiia 2aiia 2aiia") ctx.P("b. 2aiib 2aiib 2aiib") ctx.P("c. 2aiic 2aiic 2aiic") ctx.P("d. 2aiid 2aiid 2aiid") ctx.P("b. 2b 2b 2b") appendix = appendices.process_appendix(ctx.xml, 1111) appendix = NodeAccessor(appendix) assert appendix.child_labels == ['1', '2'] assert appendix['1'].child_labels == ['a', 'b', 'c', 'd', 'e', 'f'] assert appendix['2'].child_labels == ['a', 'b'] assert appendix['2']['a'].child_labels == ['i', 'ii'] assert appendix['2']['a']['i'].children == [] assert appendix['2']['a']['ii'].child_labels == ['a', 'b', 'c', 'd'] assert appendix['2']['b'].children == []
def test_process_amendments_multiple_in_same_parent(): amdpar1 = "1. In § 105.1, revise paragraph (b) to read as follows:" amdpar2 = "2. Also, revise paragraph (c):" with XMLBuilder("REGTEXT", PART="105", TITLE="12") as ctx: ctx.AMDPAR(amdpar1) ctx.AMDPAR(amdpar2) with ctx.SECTION(): ctx.SECTNO("§ 105.1") ctx.SUBJECT("Purpose.") ctx.STARS() ctx.P("(b) This part carries out.") ctx.P("(c) More stuff") preprocess_amdpars(ctx.xml) amd1, amd2 = fetch.fetch_amendments(ctx.xml) changes1, changes2 = dict(amd1['changes']), dict(amd2['changes']) assert amd1['instruction'] == amdpar1 assert amd1['cfr_part'] == '105' assert amd2['instruction'] == amdpar2 assert amd2['cfr_part'] == '105' assert ['105-1-b'] == list(changes1.keys()) assert ['105-1-c'] == list(changes2.keys()) changes = changes1['105-1-b'][0] assert changes['action'] == 'PUT' assert changes['node']['text'] == '(b) This part carries out.' changes = changes2['105-1-c'][0] assert changes['action'] == 'PUT' assert changes['node']['text'] == '(c) More stuff'
def test_content_for_appendix_regression_369(): """Regression test for modifications to a top-level element""" with XMLBuilder('EREGS_INSTRUCTIONS', final_context='2-?-201') as ctx: ctx.POST(label='2[title]') ctx.POST(label='2-?-200') ctx.POST(label='2-?-201') assert appendix.content_for_appendix(ctx.xml) is None
def test_set_agencies_unrelated(self): """ Test that we can properly derive agency info from the metadata and add it to the XML if there is an agency and a non-child subagency. """ agencies_info = [{ u'name': u'Treasury Department', u'parent_id': None, u'url': u'%s%s' % (u'https://www.federalregister.gov/', u'agencies/treasury-department'), u'raw_name': u'DEPARTMENT OF THE TREASURY', u'json_url': u'%s%s' % (u'https://www.federalregister.gov/', u'api/v1/agencies/497.json'), u'id': 497 }, { u'name': u'Alcohol, Tobacco, Firearms, and Explosives Bureau', u'parent_id': 268, u'url': '%s%s%s' % (u'https://www.federalregister.gov/', u'agencies/alcohol-tobacco-firearms', u'-and-explosives-bureau'), u'raw_name': '%s%s' % (u'Bureau of Alcohol, Tobacco, Firearms', u' and Explosives'), u'json_url': '%s%s' % (u'https://www.federalregister.gov/', u'api/v1/agencies/19.json'), u'id': 19 }] with XMLBuilder("ROOT") as ctx: with ctx.DATES(): ctx.P("Effective on May 4, 2004") xml = notice_xml.NoticeXML(ctx.xml) xml.set_agencies(agencies=agencies_info) self.assertEquals(len(xml.xpath("//EREGS_AGENCIES")), 1) eregs_agencies = xml.xpath("//EREGS_AGENCIES")[0] self.assertEquals(len(eregs_agencies.xpath("//EREGS_AGENCY")), 1) treas = eregs_agencies.xpath("//EREGS_AGENCY")[0] self.assertEquals(treas.attrib["name"], "Treasury Department") self.assertEquals(treas.attrib["raw-name"], "DEPARTMENT OF THE TREASURY") self.assertEquals(treas.attrib["agency-id"], "497") self.assertEquals(len(eregs_agencies.xpath("//EREGS_SUBAGENCY")), 1) atf = eregs_agencies.xpath("//EREGS_SUBAGENCY")[0] self.assertEquals( atf.attrib["name"], u'Alcohol, Tobacco, Firearms, and Explosives Bureau') self.assertEquals( atf.attrib["raw-name"], u"Bureau of Alcohol, Tobacco, Firearms and Explosives") self.assertEquals(atf.attrib["agency-id"], "19")
def test_set_agencies_simple(self): """ Test that we can properly derive agency info from the metadata or the XML itself, and that it's added to the XML. """ agencies_info = [{ u'name': u'Environmental Protection Agency', u'parent_id': None, u'raw_name': u'ENVIRONMENTAL PROTECTION AGENCY', u'url': u'%s%s' % (u'https://www.federalregister.gov/', u'agencies/environmental-protection-agency'), u'json_url': u'%s%s' % ('https://www.federalregister.gov/', 'api/v1/agencies/145.json'), u'id': 145 }] with XMLBuilder("ROOT") as ctx: with ctx.DATES(): ctx.P("Effective on May 4, 2004") xml = notice_xml.NoticeXML(ctx.xml) xml.set_agencies(agencies=agencies_info) self.assertEquals(len(xml.xpath("//EREGS_AGENCIES")), 1) eregs_agencies = xml.xpath("//EREGS_AGENCIES")[0] self.assertEquals(len(eregs_agencies.xpath("//EREGS_AGENCY")), 1) epa = eregs_agencies.xpath("//EREGS_AGENCY")[0] self.assertEquals(epa.attrib["name"], "Environmental Protection Agency") self.assertEquals(epa.attrib["raw-name"], "ENVIRONMENTAL PROTECTION AGENCY") self.assertEquals(epa.attrib["agency-id"], "145")
def test_create_xml_changes_child_stars(): labels_amended = [Amendment('PUT', '200-?-2-a')] with XMLBuilder("ROOT") as ctx: ctx.P("(a) Content") ctx.STARS() n2a = Node('(a) Content', label=['200', '2', 'a'], source_xml=ctx.xml.xpath('//P')[0]) n2b = Node('(b) Content', label=['200', '2', 'b']) n2 = Node('n2', label=['200', '2'], children=[n2a, n2b]) root = Node('root', label=['200'], children=[n2]) notice_changes = changes.NoticeChanges() fetch.create_xml_changes(labels_amended, root, notice_changes) data = notice_changes[None] assert '200-2-a' in data assert len(data['200-2-a']) == 1 change = data['200-2-a'][0] assert change['action'] == 'PUT' assert 'field' not in change n2a.text = n2a.text + ":" n2a.source_xml.text = n2a.source_xml.text + ":" notice_changes = changes.NoticeChanges() fetch.create_xml_changes(labels_amended, root, notice_changes) data = notice_changes[None] assert '200-2-a' in data assert len(data['200-2-a']) == 1 change = data['200-2-a'][0] assert change['action'] == 'PUT' assert change.get('field') == '[text]'
def test_parentheses_cleanup(original, new_text): """Helper function to verify that the XML is transformed as expected""" with XMLBuilder("PART") as ctx: ctx.child_from_string(u"<P>{0}</P>".format(original)) preprocessors.parentheses_cleanup(ctx.xml) assert etree.tounicode(ctx.xml[0]) == "<P>{0}</P>".format(new_text)
def assert_transformed(self, input_xml, expected_xml): self.setUp() with XMLBuilder("SECTION") as ctx: ctx.child_from_string(u"<P>{}</P>".format(input_xml)) preprocessors.MoveAdjoiningChars().transform(ctx.xml) self.assertEqual(etree.tounicode(ctx.xml.xpath('./P/E')[0]), expected_xml)
def test_next_marker_none(self): """If no marker is present, return None""" with XMLBuilder("ROOT") as ctx: ctx.P("(1) 111") ctx.P("Content") ctx.P("(i) iii") self.assertIsNone(reg_text.next_marker(ctx.xml[0]))
def test_process_amendments_mix_regs(): """Some notices apply to multiple regs. For now, just ignore the sections not associated with the reg we're focused on""" amdpar1 = "3. In § 105.1, revise paragraph (a) to read as follows:" amdpar2 = "3. In § 106.3, revise paragraph (b) to read as follows:" with XMLBuilder("ROOT") as ctx: with ctx.REGTEXT(PART="105", TITLE="12"): ctx.AMDPAR(amdpar1) with ctx.SECTION(): ctx.SECTNO("§ 105.1") ctx.SUBJECT("105Purpose.") ctx.P("(a) 105Content") with ctx.REGTEXT(PART="106", TITLE="12"): ctx.AMDPAR(amdpar2) with ctx.SECTION(): ctx.SECTNO("§ 106.3") ctx.SUBJECT("106Purpose.") ctx.P("(b) Content") preprocess_amdpars(ctx.xml) amd1, amd2 = fetch.fetch_amendments(ctx.xml) assert amd1['instruction'] == amdpar1 assert amd1['cfr_part'] == '105' assert amd2['instruction'] == amdpar2 assert amd2['cfr_part'] == '106' assert ['105-1-a'] == [c[0] for c in amd1['changes']] assert ['106-3-b'] == [c[0] for c in amd2['changes']]
def test_process_amendments_context(monkeypatch): """Context should carry over between REGTEXTs""" # turn on the interpretations plugin monkeypatch.setattr( fetch, 'instantiate_if_possible', Mock(return_value=[ appendix.content_for_appendix, section.content_for_regtext ])) amdpar1 = "3. In § 106.1, revise paragraph (a) to read as follows:" amdpar2 = "3. Add appendix C" with XMLBuilder("ROOT") as ctx: with ctx.REGTEXT(TITLE="12"): ctx.AMDPAR(amdpar1) with ctx.SECTION(): ctx.SECTNO("§ 106.1") ctx.SUBJECT("Some Subject.") ctx.P("(a) Something new") with ctx.REGTEXT(TITLE="12"): ctx.AMDPAR(amdpar2) ctx.HD("Appendix C to Part 106", SOURCE="HD1") with ctx.EXTRACT(): ctx.P("Text") preprocess_amdpars(ctx.xml) amd1, amd2 = fetch.fetch_amendments(ctx.xml) assert amd1['instruction'] == amdpar1 assert amd1['cfr_part'] == '106' assert amd2['instruction'] == amdpar2 assert amd2['cfr_part'] == '106' assert ['106-1-a'] == [c[0] for c in amd1['changes']] assert ['106-C', '106-C-p1'] == list(sorted(c[0] for c in amd2['changes']))
def add_notices(): """Adds an uneven assortment of notices""" root_attrs = { "eregs-version-id": "v0", "fr-volume": 1, "fr-start-page": 2, "fr-end-page": 3 } with XMLBuilder("ROOT", **root_attrs) as ctx: ctx.AGENCY("Agency") ctx.SUBJECT("Subj") ctx.DATES(**{'eregs-published-date': '2001-01-01'}) with ctx.EREGS_CFR_REFS(): ctx.EREGS_CFR_TITLE_REF(title=11) xml = ctx.xml entry.Notice('v0').write(NoticeXML(xml)) etree.SubElement(xml.xpath('//EREGS_CFR_TITLE_REF')[0], 'EREGS_CFR_PART_REF', part='1000') xml.attrib['eregs-version-id'] = 'v1' entry.Notice('v1').write(NoticeXML(xml)) xml.xpath('//EREGS_CFR_TITLE_REF')[0].attrib['title'] = '12' xml.attrib['eregs-version-id'] = 'v2' entry.Notice('v2').write(NoticeXML(xml)) xml.attrib['eregs-version-id'] = 'v3' entry.Notice('v3').write(NoticeXML(xml))
def test_set_agencies_simple(): """ Test that we can properly derive agency info from the metadata or the XML itself, and that it's added to the XML. """ agencies_info = [{ 'name': 'Environmental Protection Agency', 'parent_id': None, 'raw_name': 'ENVIRONMENTAL PROTECTION AGENCY', 'url': ('https://www.federalregister.gov/agencies/' 'environmental-protection-agency'), 'json_url': 'https://www.federalregister.gov/api/v1/agencies/145.json', 'id': 145 }] with XMLBuilder("ROOT") as ctx: with ctx.DATES(): ctx.P("Effective on May 4, 2004") xml = notice_xml.NoticeXML(ctx.xml) xml.set_agencies(agencies=agencies_info) assert len(xml.xpath("//EREGS_AGENCIES")) == 1 eregs_agencies = xml.xpath("//EREGS_AGENCIES")[0] assert len(eregs_agencies.xpath("//EREGS_AGENCY")) == 1 epa = eregs_agencies.xpath("//EREGS_AGENCY")[0] assert epa.attrib["name"] == "Environmental Protection Agency" assert epa.attrib["raw-name"] == "ENVIRONMENTAL PROTECTION AGENCY" assert epa.attrib["agency-id"] == "145"
def test_process_appendix_header_is_paragraph(): with XMLBuilder('APPENDIX') as ctx: ctx.EAR("Pt. 1111, App. A") ctx.HD("Appendix A to Part 1111-Awesome", SOURCE='HED') ctx.HD("A-1 - First kind of awesome", SOURCE='HD2') ctx.HD("(A) First Subkind", SOURCE='HD3') ctx.P("1. Content") ctx.HD("(B) Next Subkind", SOURCE='HD3') ctx.P("1. Moar Contents") ctx.HD("I. Remains Header", SOURCE='HD3') ctx.P("1. Content tent") appendix = appendices.process_appendix(ctx.xml, 1111) appendix = NodeAccessor(appendix) assert appendix.label == ['1111', 'A'] assert appendix.child_labels == ['1'] assert appendix['1'].child_labels == ['A', 'B'] assert appendix['1'].title == 'A-1 - First kind of awesome' assert appendix['1']['A'].child_labels == ['1'] assert appendix['1']['A'].text == '(A) First Subkind' assert appendix['1']['A']['1'].text == '1. Content' assert appendix['1']['B'].child_labels == ['1'] assert appendix['1']['B'].text == '(B) Next Subkind' assert appendix['1']['B']['1'].text == '1. Moar Contents' assert appendix['1']['B']['1'].child_labels == ['h1'] assert appendix['1']['B']['1']['h1'].title == 'I. Remains Header' assert appendix['1']['B']['1']['h1'].child_labels == ['1'] assert appendix['1']['B']['1']['h1']['1'].text == '1. Content tent'