Constants
gllm_docproc.utils.id_regulation.constants
Shared constants for Indonesian regulation document processing.
Centralises all regex patterns, lookup tables, and enum types used by both the IDRegulationParser and the IDRegulationChunker so neither stage needs to import from the other. IDRegulationParser annotates each parsed element with structure metadata; IDRegulationChunker groups those pre-tagged elements into per-article output chunks.
AMENDMENT_CONTAINER_CITATION_RE = re.compile('(?:Undang\\s*-\\s*Undang|Peraturan|Instruksi|Keputusan)[^:]*?Nomor\\s+\\S+\\s+Tahun\\s+\\d{4}', re.IGNORECASE)
module-attribute
AMENDMENT_CONTAINER_LEAD_RE = re.compile('^(?:Pasal|Bagian|BAB|Bab|Paragraf|Di\\s*antara|Setelah|Judul|Penjelasan|Lampiran)\\b|\\b(?:Beberapa\\s+ketentuan|Ketentuan)\\b', re.IGNORECASE)
module-attribute
AMENDMENT_CONTAINER_TAIL_RE = re.compile('\\b(?:diubah|dihapus|disisipkan|ditambahkan)\\b(?:[^:]*?\\bsebagai\\s+berikut\\b)?\\s*:\\s*$', re.IGNORECASE)
module-attribute
AMENDMENT_DECLARATION_RE = re.compile(f'(?P<opener>beberapa\s+ketentuan\s+dalam)|(?P<verb>(?m:^)[ \t]*mengubah\s+(?={_CITED_REGULATION_TYPE}))', re.IGNORECASE)
module-attribute
AMENDMENT_DIRECTIVE_LEAD_RE = re.compile(f'^\d+\.[\s.]*{_AMENDMENT_DIRECTIVE_LEAD_WORDS}\b')
module-attribute
AMENDMENT_DIRECTIVE_LEAD_UNNUMBERED_RE = re.compile(f'^{_AMENDMENT_DIRECTIVE_LEAD_WORDS}\b')
module-attribute
AMENDMENT_DIRECTIVE_SUBJECT_RE = re.compile('\\bPasal\\s+(?:\\d+[A-Z]?|[IVXLCDM]+)\\b|\\bBAB\\s+[IVXLCDM]+\\b|\\b(?:Bagian|Subbagian)\\s+(?:Ke\\w+|[IVXLCDM]+|\\d+)\\b|\\b(?:Paragraf|Subparagraf)\\s+\\d+\\b', re.IGNORECASE)
module-attribute
AMENDMENT_GROUP_EXTRAS_KEYS = tuple(AMENDMENT_GROUP_EXTRAS_KEY_MAP)
module-attribute
AMENDMENT_GROUP_EXTRAS_KEY_MAP = {'amendment_group_level': RegulationParserMetadataKey.AMENDMENT_GROUP_LEVEL, 'amendment_group_number': RegulationParserMetadataKey.AMENDMENT_GROUP_NUMBER, 'amendment_group_title': RegulationParserMetadataKey.AMENDMENT_GROUP_TITLE, 'amendment_group_parent_chapter_number': RegulationParserMetadataKey.AMENDMENT_GROUP_PARENT_CHAPTER_NUMBER, 'amendment_group_parent_part_number': RegulationParserMetadataKey.AMENDMENT_GROUP_PARENT_PART_NUMBER, 'amendment_group_parent_paragraph_number': RegulationParserMetadataKey.AMENDMENT_GROUP_PARENT_PARAGRAPH_NUMBER}
module-attribute
AMENDMENT_GROUP_LOCATIVE_RE = re.compile(f'\bdalam\s+(?:BAB\s+(?P<chapter>[IVXLCDM]+)|Bagian\s+(?P<part>{_ORDINAL_WORD})|Subparagraf\s+(?P<subparagraph>\d+)|Paragraf\s+(?P<paragraph>\d+))\b', re.IGNORECASE)
module-attribute
AMENDMENT_GROUP_SUBJECT_RE = re.compile(f'^\d+\.[\s.]*Judul\s+(?:BAB\s+(?P<chapter>[IVXLCDM]+)|Bagian\s+(?P<part>{_ORDINAL_WORD})|Subparagraf\s+(?P<subparagraph>\d+)|Paragraf\s+(?P<paragraph>\d+))\b', re.IGNORECASE)
module-attribute
AMENDMENT_GROUP_SUBJECT_UNNUMBERED_RE = re.compile(f'^Judul\s+(?:BAB\s+(?P<chapter>[IVXLCDM]+)|Bagian\s+(?P<part>{_ORDINAL_WORD})|Subparagraf\s+(?P<subparagraph>\d+)|Paragraf\s+(?P<paragraph>\d+))\b', re.IGNORECASE)
module-attribute
AMENDMENT_INDICATOR_RE = re.compile('PERUBAHAN', re.IGNORECASE)
module-attribute
AMENDMENT_ITEM_NUMBER_KEY = 'amendment_item_number'
module-attribute
AMENDMENT_ITEM_RE = re.compile('^(\\d+)\\.')
module-attribute
AMENDMENT_OPERATION_RE = re.compile('\\b(diubah|disisipkan|ditambahkan|dihapus)\\b', re.IGNORECASE)
module-attribute
AMENDMENT_QUOTED_ITEM_RE = re.compile('(?m)^\\s*\\d+\\.\\s')
module-attribute
AMENDMENT_ROMAN_ARTICLE_BOUND_RE = re.compile(f'(?m)^{ARTICLE_ROMAN_CORE}\s*$')
module-attribute
AMENDMENT_SUBJECT_RE = re.compile('^\\s*PERUBAHAN(?:\\s+\\w+){0,2}?\\s+ATAS\\b', re.IGNORECASE)
module-attribute
ANNEX_BARE_HEADING_LINE_RE = re.compile(f'^(?:SALINAN\s+)?LAMPIRAN(?:\s+{ANNEX_NUMBER_PATTERN})?\s*$')
module-attribute
ANNEX_HEADING_RE = re.compile(f'^(?:SALINAN\s+)?LAMPIRAN(?:\s+{ANNEX_NUMBER_PATTERN})?\s*$', re.IGNORECASE)
module-attribute
ANNEX_LOOSE_HEADING_RE = re.compile(f'^(?:SALINAN\s+)?LAMPIRAN\b(?:\s+{ANNEX_NUMBER_PATTERN})?+(?!\s+(?:{ANNEX_NON_HEADING_FOLLOWER_PATTERN})\b)(?!$)', re.IGNORECASE)
module-attribute
ANNEX_NON_HEADING_FOLLOWER_PATTERN = 'INI|YANG|SEBAGAIMANA|MERUPAKAN'
module-attribute
ANNEX_NUMBER_PATTERN = '(?P<number>(?:[IVXLCDM]+|\\d+)(?:\\.[A-Za-z0-9]+)?)\\b'
module-attribute
ANNEX_REFERENCE_HEADING_RE = re.compile(f'^(?:SALINAN\s+)?LAMPIRAN(?:\s+{ANNEX_NUMBER_PATTERN})?\s+(?:PERATURAN|UNDANG-UNDANG|KEPUTUSAN|INSTRUKSI|SURAT\s+EDARAN|KETETAPAN)\b.*\bNOMOR\b', re.IGNORECASE | re.DOTALL)
module-attribute
ANNEX_SALINAN_ONLY_RE = re.compile('^SALINAN\\s*$', re.IGNORECASE)
module-attribute
ARTICLE_HEADER_CORE = 'Pasal\\s*(\\d+[A-Z]?)'
module-attribute
ARTICLE_HEADER_LEAD_RE = re.compile(f'^{ARTICLE_HEADER_CORE}\b')
module-attribute
ARTICLE_HEADER_PREFIX_RE = re.compile(f'^{ARTICLE_HEADER_CORE}\b(?!\s+(?:ayat|huruf|angka)\b|[.;,…]|\s+[.;,…]|\s+\.{2,}|\s+[a-z])')
module-attribute
ARTICLE_HEADER_RE = re.compile(f'^{ARTICLE_HEADER_CORE}$')
module-attribute
ARTICLE_KEYWORD_RE = re.compile('\\bPasal\\b', re.IGNORECASE)
module-attribute
ARTICLE_ROMAN_CORE = 'Pasal\\s+([IVXLCDM]+)'
module-attribute
ARTICLE_ROMAN_RE = re.compile(f'^{ARTICLE_ROMAN_CORE}$')
module-attribute
ARTICLE_SPLIT_RE = re.compile('(?m)(?=^Pasal\\s+\\d+[A-Z]?(?!\\s+ayat)\\b)')
module-attribute
ARTICLE_STRUCTURAL_TRAILING_RE = re.compile(f'(?P<title>{_STRUCTURAL_KEYWORD_PATTERN}(?P<title_body>(?:\s.*?\S)?))\s+(?P<pasal>Pasal[ \t]+\d+[A-Z]?)', re.IGNORECASE | re.DOTALL)
module-attribute
CHAPTER_RE = re.compile('^BAB\\s+([IVXLCDM]+)(?:\\s+(.+))?')
module-attribute
CHUNK_ELEMENT_JSON_KEY = 'element_json'
module-attribute
CHUNK_ORDER_KEY = 'order'
module-attribute
CITATION_ARTICLE_CLAUSE_RE = re.compile('\\bPasal\\s+(\\d+[A-Z]?)\\s+ayat\\s+\\((\\d+[a-z]?)\\)', re.IGNORECASE)
module-attribute
CITATION_ARTICLE_RE = re.compile('\\bPasal\\s+(\\d+[A-Z]?)(?!\\s+ayat\\b)', re.IGNORECASE)
module-attribute
CITATION_CLAUSE_ONLY_RE = re.compile('\\bayat\\s+\\((\\d+[a-z]?)\\)', re.IGNORECASE)
module-attribute
CITATION_COORDINATED_CLAUSE_RE = re.compile('(?:dan|,|atau|serta)\\s+ayat\\s+\\((\\d+[a-z]?)\\)', re.IGNORECASE)
module-attribute
CITATION_TAX_TERM_PREFIX_RE = re.compile('\\b(?:PPh|Pajak\\s+Penghasilan)\\s+$', re.IGNORECASE)
module-attribute
CLAUSE_SPLIT_RE = re.compile('(?m)^(\\(\\d+[a-z]?\\))\\s*')
module-attribute
CLOSING_START_RE = re.compile('^Agar setiap orang mengetahuinya', re.IGNORECASE)
module-attribute
COURT_CONTEXT_RE = re.compile('\\b(Putusan|Mahkamah)\\b', re.IGNORECASE)
module-attribute
DECISION_CLAUSE_HEADER_RE = re.compile(f'^(?:Menetapkan\s*:\s*)?(?P<clause_number>{_ORDINAL_WORD})(?:\s*:.*)?$', re.IGNORECASE | re.DOTALL)
module-attribute
DECISION_DECLARATION_RE = re.compile('^MEMUTUSKAN[\\s:]*$', re.IGNORECASE)
module-attribute
DIRECTIVE_GROUP_SUBJECT_RE = re.compile('^\\s*(?:\\d+\\.\\s*)?(?:Ketentuan\\s+)?(?:Bagian|BAB|Bab|Paragraf|Judul)\\b')
module-attribute
DISAHKAN_RE = re.compile('(?m)(?:^|[.;][ \\t]+)[ \\t]*Disahkan[ \\t]+di[ \\t]+(?!dalam\\b)[^\\r\\n]+?(?:\\r?\\n[ \\t]*){0,2}pada[ \\t]+tanggal (\\d{1,2}) (\\w+) (\\d{4})', re.IGNORECASE)
module-attribute
DISTRIBUTION_LIST_RE = re.compile('^Tembusan\\b', re.IGNORECASE)
module-attribute
DITETAPKAN_RE = re.compile('(?m)(?:^|[.;][ \\t]+)[ \\t]*Ditetapkan[ \\t]+di[ \\t]+(?!dalam\\b)[^\\r\\n]+?(?:\\r?\\n[ \\t]*){0,2}pada[ \\t]+tanggal (\\d{1,2}) (\\w+) (\\d{4})', re.IGNORECASE)
module-attribute
DIUNDANGKAN_RE = re.compile('(?m)(?:^|[.;][ \\t]+)[ \\t]*Diundangkan[ \\t]+di[ \\t]+(?!dalam\\b)[^\\r\\n]+?(?:\\r?\\n[ \\t]*){0,2}pada[ \\t]+tanggal (\\d{1,2}) (\\w+) (\\d{4})', re.IGNORECASE)
module-attribute
DOCUMENT_TAIL_STRUCTURES = frozenset({RegulationStructure.ENACTMENT_TAIL, RegulationStructure.ANNEX_HEADER, RegulationStructure.ANNEX})
module-attribute
EFFECTIVE_DATE_ESTABLISHED_INDEX = 4
module-attribute
EFFECTIVE_DATE_RE = re.compile('(?:mulai|ini) berlaku pada tanggal (?:(\\d{1,2}) (\\w+) (\\d{4})|(diundangkan)|(ditetapkan|dikeluarkan))', re.IGNORECASE)
module-attribute
ELEMENT_COORDINATE_COUNT = 4
module-attribute
ENACTMENT_START_RE = re.compile('^(Agar setiap orang mengetahuinya|Ditetapkan di|Dikeluarkan di|Diundangkan di)', re.IGNORECASE)
module-attribute
EXPLANATION_AMENDMENT_ITEM_RE = re.compile('^Pasal\\s+([IVXLCDM]+)\\s+Angka\\s+(\\d+)$', re.IGNORECASE)
module-attribute
EXPLANATION_NUMBER_PREFIX_RE = re.compile('^Angka\\s+(\\d+)[\\s.]*([^\\s.].*)$', re.DOTALL)
module-attribute
EXPLANATION_NUMBER_RE = re.compile('^Angka\\s+(\\d+)[\\s.]*$')
module-attribute
EXPLANATION_RE = re.compile('^PENJELASAN\\b')
module-attribute
FIRST_ORDINAL_WORD = 'pertama'
module-attribute
GAZETTE_HEADER_START_RE = re.compile('^LEMBARAN NEGARA')
module-attribute
GROUP_INSERT_KIND_RE = re.compile('^\\s*\\d+\\s*(?:\\([^)]*\\)\\s*)?(?:Bagian|BAB|Paragraf)\\b', re.IGNORECASE)
module-attribute
GROUP_LEVEL_DEPTH = {level: depth for depth, level in (enumerate(AmendmentGroupLevel))}
module-attribute
IMAGE_PLACEHOLDER_ELEMENT_RE = re.compile('^\\[image_[^\\]]+\\]$')
module-attribute
INDONESIAN_NUMBER_MAP = {'satu': 1, 'dua': 2, 'tiga': 3, 'empat': 4, 'lima': 5, 'enam': 6, 'tujuh': 7, 'delapan': 8, 'sembilan': 9, 'sepuluh': 10, 'sebelas': 11, 'duabelas': 12, 'tigabelas': 13, 'empatbelas': 14, 'limabelas': 15, 'enambelas': 16, 'tujuhbelas': 17, 'delapanbelas': 18, 'sembilanbelas': 19}
module-attribute
INSERT_SECTION_HEADER_RES = (re.compile('^Bagian\\s+(?:Ke\\w+|Pertama)\\b'), re.compile('^BAB\\s+[IVXLCDM]+[A-Z]?\\b'), re.compile('^Paragraf\\s+\\d+[A-Z]?\\b'))
module-attribute
INSTRUCTION_DECLARATION_RE = re.compile('(?:meng|di)instruksikan\\s*:\\s*$', re.IGNORECASE)
module-attribute
INSTRUCTION_HEADER_RE = re.compile(f'^(?:UNTUK\s+)?(?P<instruction_number>{_ORDINAL_WORD})(?:\s*:.*)?$', re.IGNORECASE | re.DOTALL)
module-attribute
ISSUANCE_RE = re.compile('(?m)(?:^|[.;][ \\t]+)[ \\t]*Dikeluarkan[ \\t]+di[ \\t]+(?!dalam\\b)[^\\r\\n]+?(?:\\r?\\n[ \\t]*){0,2}pada[ \\t]+tanggal (\\d{1,2}) (\\w+) (\\d{4})', re.IGNORECASE)
module-attribute
LEADING_PAGE_NUMBER_RE = re.compile(f'^{PAGE_NUMBER_BOILERPLATE_PATTERN}\s*')
module-attribute
LEGAL_BASIS_BLOCK_RE = re.compile('(?i)Mengingat\\s*:\\s*((?:(?!MEMUTUSKAN)[\\s\\S])+)')
module-attribute
LEGAL_BASIS_ITEM_SPLIT_RE = re.compile('(?m)(?=^\\d+\\.\\s)')
module-attribute
LEGISLATION_TYPE_FROM_NUMBER_RE = re.compile('/([A-Z]+)\\.', re.IGNORECASE)
module-attribute
MAX_MARKER_GAP = 2
module-attribute
MIN_LIST_RUN = 3
module-attribute
MONTH_ID = {'januari': 1, 'februari': 2, 'maret': 3, 'april': 4, 'mei': 5, 'juni': 6, 'juli': 7, 'agustus': 8, 'september': 9, 'oktober': 10, 'november': 11, 'desember': 12}
module-attribute
NEXT_PAGE_PREVIEW_BOILERPLATE_RE = re.compile(f'{_NEXT_PAGE_PREVIEW_MARKER}?(?:{_NEXT_PAGE_PREVIEW_WORD}|{_NEXT_PAGE_PREVIEW_NUMBER})(?: [^\W_][\w/-]*| ?{_NEXT_PAGE_PREVIEW_BRACKETED_NUMBER})? ?:? ?(?:\. ?\. ?\.|…)')
module-attribute
NOMOR_TAHUN_ALPHA_RE = re.compile('NOMOR\\s+(?-i:([A-Z]{1,5}\\.?\\s+\\d+[A-Z]?))\\s+TAHUN\\s+(\\d{4})', re.IGNORECASE)
module-attribute
NOMOR_TAHUN_RE = re.compile('NOMOR\\s+(\\d+)' + _NOMOR_TAHUN_QUALIFIER + '\\s+TAHUN\\s+(\\d{4})', re.IGNORECASE)
module-attribute
NOMOR_TAHUN_ROMAN_RE = re.compile('NOMOR\\s+(?-i:([IVXLCDM]+))\\s+TAHUN\\s+(\\d{4})', re.IGNORECASE)
module-attribute
OFFICIAL_MEMORANDUM_CLOSING_RE = re.compile('^Demikian\\b', re.IGNORECASE)
module-attribute
OFFICIAL_MEMORANDUM_INLINE_SUB_POINT_SPLIT_RE = re.compile(f';\s*(?:dan|atau)\s+(?={_OFFICIAL_MEMORANDUM_SUB_POINT_MARKER}\s)', re.IGNORECASE)
module-attribute
OFFICIAL_MEMORANDUM_POINT_HEADER_RE = re.compile('^(\\d+)\\.\\s')
module-attribute
OFFICIAL_MEMORANDUM_SUB_POINT_HEADER_RE = re.compile(f'^{_OFFICIAL_MEMORANDUM_SUB_POINT_MARKER}\s')
module-attribute
OFFICIAL_MEMORANDUM_TITLE_RE = re.compile('^SURAT EDARAN\\b.*NOMOR', re.IGNORECASE | re.DOTALL)
module-attribute
OPERATION_KEY = 'operation'
module-attribute
OPERATION_MAP = {'diubah': AmendmentOperation.UPDATE, 'disisipkan': AmendmentOperation.INSERT, 'ditambahkan': AmendmentOperation.INSERT, 'dihapus': AmendmentOperation.DELETE}
module-attribute
ORDINAL_MARKER_KIND = 'ordinal'
module-attribute
OWNED_RELATION_TYPES = frozenset({RelationType.CITES, RelationType.MENTIONS_CONCEPT, RelationType.CONTAINS_OBLIGATION})
module-attribute
PAGE_FURNITURE_DIGIT_RUN_RE = re.compile('\\d+')
module-attribute
PAGE_FURNITURE_EXCLUDED_RE = re.compile('^(?:SALINAN\\s+)?(?:LAMPIRAN|PENJELASAN|BAB|Pasal|Bagian|Paragraf|Subparagraf|Angka|Ayat|Huruf)\\b', re.IGNORECASE)
module-attribute
PAGE_FURNITURE_IMAGE_SIZE_BUCKET = 10
module-attribute
PAGE_FURNITURE_MAX_OCCURRENCES_PER_PAGE = 1.5
module-attribute
PAGE_FURNITURE_MAX_TEXT_LENGTH = 200
module-attribute
PAGE_FURNITURE_METADATA_KEY = '_regulation_page_furniture'
module-attribute
PAGE_FURNITURE_MIN_PAGES = 3
module-attribute
PAGE_FURNITURE_MIN_PAGE_SHARE = 0.5
module-attribute
PAGE_FURNITURE_POSITION_TOLERANCE = 0.03
module-attribute
PAGE_NUMBER_BOILERPLATE_PATTERN = f'[{PAGE_NUMBER_DASHES}]\s*\d+\s*[{PAGE_NUMBER_DASHES}]'
module-attribute
PAGE_NUMBER_BOILERPLATE_RE = re.compile(PAGE_NUMBER_BOILERPLATE_PATTERN)
module-attribute
PAGE_NUMBER_DASHES = '-–—−'
module-attribute
PAGE_SK_STAMP_RE = re.compile('^SK No \\d+ A$', re.IGNORECASE)
module-attribute
PARAGRAPH_RE = re.compile('^Paragraf\\s+(\\d+)(?:\\s+(\\S.*))?$')
module-attribute
PART_RE = re.compile(f'^Bagian\s+(?P<part_number>{_ORDINAL_WORD})(?:\s+(?!(?-i:[a-z]))(?P<title>.+))?$', re.IGNORECASE)
module-attribute
PASAL_DEMI_PASAL_RE = re.compile('PASAL\\s+DEMI\\s+PASAL', re.IGNORECASE)
module-attribute
POINT_MARKER_KIND = 'point'
module-attribute
PREAMBLE_LIST_RE = re.compile('^(?:Kepada(?:\\s+Yth\\.?)?|Yth\\.|Mengingat)\\s*:?\\s*(?=\\d+\\.\\s|$)', re.IGNORECASE)
module-attribute
PRESIDENTIAL_MASTHEAD_BOILERPLATE_RE = re.compile(f'PRESIDEN\s+REPUBLIK\s+INDONESIA(?:\s+{PAGE_NUMBER_BOILERPLATE_PATTERN})?')
module-attribute
RATIFICATION_RE = re.compile('^\\s*PENETAPAN\\b.*MENJADI\\s+UNDANG', re.IGNORECASE)
module-attribute
REGULATION_CITATION_RE = re.compile(f'\b(?P<type>{_CITED_REGULATION_TYPE}[\w\s-]{0,120}?)\s+Nomor\s+(?P<number>{_CITED_REGULATION_NUMBER}){_NOMOR_TAHUN_QUALIFIER}(?:\s+Tahun\s+(?P<year>\d{4}))?', re.IGNORECASE)
module-attribute
REGULATION_NUMBER_RE = re.compile('NOMOR(?:\\s*:\\s*|\\s+)((?:[A-Z]+\\s*-\\s*)?\\d+(?:\\s*/\\s*[\\w.]+)*)', re.IGNORECASE)
module-attribute
REGULATION_TITLE_RE = re.compile(f'(?:{_REGULATION_TITLE_START})(?:(?!{_REGULATION_TITLE_STOP}).)+', re.IGNORECASE | re.DOTALL)
module-attribute
REVOCATION_ARBITRARY_SCOPE_RE = re.compile('Pasal\\s+(?:\\d+[A-Z]?|[IVXLCDM]+)\\b.*\\bsepanjang\\b|,\\s*sepanjang\\b', re.IGNORECASE)
module-attribute
REVOCATION_INDICATOR_RE = re.compile('dicabut\\s+dan\\s+dinyatakan\\s+tidak\\s+berlaku', re.IGNORECASE)
module-attribute
REVOCATION_ITEM_SPLIT_RE = re.compile(f'(?m)(?:^|(?<=[:;])\s*)([a-z]+)[.)]\s+{_REVOCATION_ITEM_OPENER}\b', re.IGNORECASE)
module-attribute
REVOCATION_SCOPE_CONNECTOR_RE = re.compile('(?:sampai\\s+dengan|dan\\s*/\\s*atau|serta|\\bdan\\b|,|;)$', re.IGNORECASE)
module-attribute
REVOCATION_SCOPE_UNIT_LEADING_RE = re.compile(_REVOCATION_SCOPE_UNIT_CORE, re.IGNORECASE)
module-attribute
REVOCATION_SCOPE_UNIT_RE = re.compile(_REVOCATION_SCOPE_UNIT_CORE + '$', re.IGNORECASE)
module-attribute
SCANNER_WATERMARK_BOILERPLATE_RE = re.compile('(?:Scanned|Digitised|Digitized|Dipindai)\\s+(?:by|with|using|dengan|oleh)\\s+[a-z][\\w.\\- ]{0,24}', re.IGNORECASE)
module-attribute
SK_NUMBER_BOILERPLATE_RE = re.compile('SK ?No\\.? ?\\d+ ?[A-Z]?\\.?', re.IGNORECASE)
module-attribute
STATE_GAZETTE_CONTEXT_RE = re.compile('(LEMBARAN NEGARA|TAMBAHAN LEMBARAN NEGARA)', re.IGNORECASE)
module-attribute
STATE_GAZETTE_DECLARATION_RE = re.compile('LEMBARAN\\s*NEGARA\\s*REPUBLIK\\s*INDONESIA\\s*TAHUN\\s*[0-9]{4}\\s*NOMOR\\s*[0-9]+\\b|TAMBAHAN\\s*LEMBARAN\\s*NEGARA\\s*REPUBLIK\\s*INDONESIA\\s*NOMOR\\s*[0-9]+\\b')
module-attribute
STRUCTURAL_ANCHOR_STRUCTURES = frozenset({RegulationStructure.ARTICLE_HEADER, RegulationStructure.POINT_HEADER, RegulationStructure.DECISION_CLAUSE_HEADER, RegulationStructure.INSTRUCTION_HEADER, RegulationStructure.CHAPTER_HEADER, RegulationStructure.ANNEX_HEADER, RegulationStructure.EXPLANATION_ARTICLE_HEADER, RegulationStructure.EXPLANATION_AMENDMENT_TARGET_ARTICLE_HEADER})
module-attribute
STRUCTURAL_METADATA_KEYS = RegulationParserMetadataKey.structural_keys()
module-attribute
SUBPARAGRAPH_RE = re.compile('^Subparagraf\\s+(\\d+)(?:\\s+(\\S.*))?$')
module-attribute
TARGET_ARTICLE_NUMBER_KEY = 'target_article_number'
module-attribute
TARGET_ARTICLE_RE = re.compile('\\bPasal\\s+(\\d+[A-Z]?)\\b')
module-attribute
TENTANG_RE = re.compile('(?i)TENTANG\\s+((?:(?!DENGAN RAHMAT|MENIMBANG|MENGINGAT|MEMUTUSKAN|PRESIDEN REPUBLIK INDONESIA,)[\\s\\S])+)')
module-attribute
TETAP_ONLY_ITEM_RE = re.compile('^(\\d+)\\.[^.]*\\btetap\\b', re.IGNORECASE)
module-attribute
YEAR_RE = re.compile('\\b(20\\d{2}|19\\d{2})\\b')
module-attribute
_AMENDMENT_DIRECTIVE_LEAD_WORDS = '(?:Ketentuan|Pasal|Bagian|BAB|Bab|Paragraf|Di\\s*antara|Setelah|Judul|Penjelasan|Lampiran)'
module-attribute
_CITED_REGULATION_NUMBER = '(?:[A-Z]+[-.])?\\d+(?:\\s*/\\s*[\\w.]+)*'
module-attribute
_CITED_REGULATION_TYPE = '(?:Peraturan|Undang-Undang|Keputusan|Instruksi|Surat\\s+Edaran|Ketetapan)'
module-attribute
_NEXT_PAGE_PREVIEW_BRACKETED_NUMBER = '\\(\\d+[a-z]?\\)?'
module-attribute
_NEXT_PAGE_PREVIEW_MARKER = '(?:\\(\\d+[a-z]?(?:\\) ?| )|(?:\\d+\\.|[IVXLCDM]+\\.|[A-Za-z]\\.) ?)'
module-attribute
_NEXT_PAGE_PREVIEW_NUMBER = '(?:Rp ?)?\\d+(?:[.,]\\d+)*(?: \\([^\\W\\d_]+(?: [^\\W\\d_]+){0,3}\\))?'
module-attribute
_NEXT_PAGE_PREVIEW_WORD = '[^\\W\\d_][\\w/-]*'
module-attribute
_NOMOR_TAHUN_QUALIFIER = '(?:\\s+[A-Za-z]{2,4}\\.)?'
module-attribute
_NUMBER_VOCAB = '|'.join(list(INDONESIAN_NUMBER_MAP.keys()) + ['belas', 'puluh'])
module-attribute
_OFFICIAL_MEMORANDUM_SUB_POINT_MARKER = '(?:[a-z]+[.)]|\\d+\\))'
module-attribute
_ORDINAL_NUMBER_WORD = f'(?:ke)?(?:{_NUMBER_VOCAB})(?:\s+(?:{_NUMBER_VOCAB})\b)*+'
module-attribute
_ORDINAL_WORD = f'(?:{FIRST_ORDINAL_WORD}|{_ORDINAL_NUMBER_WORD})'
module-attribute
_REGULATION_TITLE_START = 'UNDANG-UNDANG|PERATURAN|SURAT EDARAN|KEPUTUSAN|INSTRUKSI MENTERI|INSTRUKSI PRESIDEN'
module-attribute
_REGULATION_TITLE_STOP = 'DENGAN RAHMAT|MENIMBANG|MENGINGAT|MEMUTUSKAN|PRESIDEN REPUBLIK INDONESIA,'
module-attribute
_REVOCATION_ITEM_OPENER = f'(?:{_CITED_REGULATION_TYPE}|Paragraf|Subparagraf|Lampiran|Bab|Bagian|Pasal)'
module-attribute
_REVOCATION_SCOPE_UNIT_CORE = '(?:Pasal\\s+(?P<pasal_num>\\d+[A-Z]?|[IVXLCDM]+)|ayat\\s*\\(\\s*\\d+\\s*\\)|huruf\\s+[A-Za-z]{1,3}|angka\\s+(?:\\d+|[IVXLCDM]+)|(?P<scope_anchor>Subbagian|Subparagraf|Bagian|Bab|Paragraf|Lampiran)(?:\\s+(?:Ke\\w+|[IVXLCDM]+|\\d+))?)'
module-attribute
_STRUCTURAL_KEYWORD_PATTERN = f'(?:BAB\s+[IVXLCDM]+(?-i:[A-Z])?|Bagian\s+{_ORDINAL_WORD}(?:\s+(?-i:[A-Z]))?|Subparagraf(?:\s+(?-i:[A-Z]))?|Paragraf\s+\d+(?-i:[A-Z])?)'
module-attribute
AmendmentExtrasKeys
Bases: StrEnum
Keys of an ArticleGroup.amendment_extras dict, set by a grouper and read by the chunker.
Grouped here rather than left as loose constants because a grouper and the chunker have to
agree on every one of them. StrEnum members double as dict keys and compare equal to the
plain strings already in committed fixtures.
AMENDS_REGULATION_ID = 'amends_regulation_id'
class-attribute
instance-attribute
ITEM_NUMBER = 'amendment_item_number'
class-attribute
instance-attribute
OPERATION = 'operation'
class-attribute
instance-attribute
TARGET_ARTICLE_NUMBER = 'target_article_number'
class-attribute
instance-attribute
AmendmentGroupLevel
Bases: StrEnum
Structural level of a BAB/Bagian/Paragraf/Subparagraf group an amendment item targets.
Distinguishes a targeted group's own hierarchy level (see IDRegulationParser's regulation_amendment_group_level metadata field) from the article-level AmendmentOperation -- a single INSERT item can introduce a whole new chapter/part/paragraph, and this is the vocabulary for which level it is.
Members are declared outermost-first; GROUP_LEVEL_DEPTH below reads that nesting order.
CHAPTER = 'chapter'
class-attribute
instance-attribute
PARAGRAPH = 'paragraph'
class-attribute
instance-attribute
PART = 'part'
class-attribute
instance-attribute
SUBPARAGRAPH = 'subparagraph'
class-attribute
instance-attribute
AmendmentOperation
Bases: StrEnum
Amendment operation types for Indonesian regulations.
DELETE = 'delete'
class-attribute
instance-attribute
INSERT = 'insert'
class-attribute
instance-attribute
UPDATE = 'update'
class-attribute
instance-attribute
CitationType
Bases: StrEnum
Citation types for regulation cross-references.
INTRA = 'intra'
class-attribute
instance-attribute
NodeLabel
Bases: StrEnum
Neo4j node labels for the Indonesian regulation graph. See ONTOLOGY.md.
ARTICLE = 'Article'
class-attribute
instance-attribute
ARTICLE_VERSION = 'ArticleVersion'
class-attribute
instance-attribute
CHAPTER = 'Chapter'
class-attribute
instance-attribute
CHUNK = 'Chunk'
class-attribute
instance-attribute
CLAUSE = 'Clause'
class-attribute
instance-attribute
CONCEPT = 'Concept'
class-attribute
instance-attribute
EXPLANATION = 'Explanation'
class-attribute
instance-attribute
OBLIGATION = 'Obligation'
class-attribute
instance-attribute
PARAGRAPH = 'Paragraph'
class-attribute
instance-attribute
PART = 'Part'
class-attribute
instance-attribute
REGULATION = 'Regulation'
class-attribute
instance-attribute
SUBPARAGRAPH = 'Subparagraph'
class-attribute
instance-attribute
RegulationParserMetadataKey
Bases: StrEnum
Keys IDRegulationParser writes into each element's metadata dict.
structural_keys() returns members after STRUCTURE and before TITLE.
TITLE through VERSION_TAG are document-level identity keys. AMENDS_REGULATION is
the legacy singular key kept for older persisted metadata.
ABOUT = 'regulation_about'
class-attribute
instance-attribute
AMENDMENT_GROUP_LEVEL = 'regulation_amendment_group_level'
class-attribute
instance-attribute
AMENDMENT_GROUP_NUMBER = 'regulation_amendment_group_number'
class-attribute
instance-attribute
AMENDMENT_GROUP_PARENT_CHAPTER_NUMBER = 'regulation_amendment_group_parent_chapter_number'
class-attribute
instance-attribute
AMENDMENT_GROUP_PARENT_PARAGRAPH_NUMBER = 'regulation_amendment_group_parent_paragraph_number'
class-attribute
instance-attribute
AMENDMENT_GROUP_PARENT_PART_NUMBER = 'regulation_amendment_group_parent_part_number'
class-attribute
instance-attribute
AMENDMENT_GROUP_TITLE = 'regulation_amendment_group_title'
class-attribute
instance-attribute
AMENDMENT_ITEM_INLINE_BODY = 'regulation_amendment_item_inline_body'
class-attribute
instance-attribute
AMENDMENT_ITEM_NUMBER = 'regulation_amendment_item_number'
class-attribute
instance-attribute
AMENDMENT_OPERATION = 'regulation_amendment_operation'
class-attribute
instance-attribute
AMENDMENT_REGULATION_ID = 'regulation_amendment_regulation_id'
class-attribute
instance-attribute
AMENDMENT_TARGET = 'regulation_amendment_target'
class-attribute
instance-attribute
AMENDS_REGULATION = 'regulation_amends_regulation'
class-attribute
instance-attribute
AMENDS_REGULATIONS = 'regulation_amends_regulations'
class-attribute
instance-attribute
ANNEX_NUMBER = 'regulation_annex_number'
class-attribute
instance-attribute
ARTICLE_NUMBER = 'regulation_article_number'
class-attribute
instance-attribute
CHAPTER_NUMBER = 'regulation_chapter_number'
class-attribute
instance-attribute
CHAPTER_TITLE = 'regulation_chapter_title'
class-attribute
instance-attribute
DATE = 'regulation_date'
class-attribute
instance-attribute
DECISION_CLAUSE_NUMBER = 'regulation_decision_clause_number'
class-attribute
instance-attribute
EFFECTIVE_DATE = 'regulation_effective_date'
class-attribute
instance-attribute
ENACTED_ON = 'regulation_enacted_on'
class-attribute
instance-attribute
ID = 'regulation_id'
class-attribute
instance-attribute
INSTRUCTION_NUMBER = 'regulation_instruction_number'
class-attribute
instance-attribute
IS_AMENDMENT = 'regulation_is_amendment'
class-attribute
instance-attribute
LEGAL_BASES = 'regulation_legal_bases'
class-attribute
instance-attribute
LEGISLATION_SUB_TYPE = 'regulation_legislation_sub_type'
class-attribute
instance-attribute
LEGISLATION_TYPE = 'regulation_legislation_type'
class-attribute
instance-attribute
NUMBER = 'regulation_number'
class-attribute
instance-attribute
PARAGRAPH_NUMBER = 'regulation_paragraph_number'
class-attribute
instance-attribute
PARAGRAPH_TITLE = 'regulation_paragraph_title'
class-attribute
instance-attribute
PART_NUMBER = 'regulation_part_number'
class-attribute
instance-attribute
PART_TITLE = 'regulation_part_title'
class-attribute
instance-attribute
POINT_NUMBER = 'regulation_point_number'
class-attribute
instance-attribute
REVOKES_REGULATIONS = 'regulation_revokes_regulations'
class-attribute
instance-attribute
STRUCTURE = 'regulation_structure'
class-attribute
instance-attribute
SUBPARAGRAPH_NUMBER = 'regulation_subparagraph_number'
class-attribute
instance-attribute
SUBPARAGRAPH_TITLE = 'regulation_subparagraph_title'
class-attribute
instance-attribute
TITLE = 'regulation_title'
class-attribute
instance-attribute
VERSION_TAG = 'version_tag'
class-attribute
instance-attribute
YEAR = 'regulation_year'
class-attribute
instance-attribute
structural_keys()
classmethod
Per-element structural keys: every member after STRUCTURE and before TITLE.
STRUCTURE is written separately by each tagger. Document-level identity keys
(TITLE through VERSION_TAG) are stamped identically on every element and are
not cleared with the per-element structural fields.
Returns:
| Type | Description |
|---|---|
tuple[RegulationParserMetadataKey, ...]
|
tuple[RegulationParserMetadataKey, ...]: The structural metadata keys, in enum order. |
RegulationStructure
Bases: StrEnum
Structural element types within an Indonesian regulation document.
Used to tag each parsed element with its role in the document hierarchy, from front matter through chapters, parts, paragraphs, articles, body text, amendment directives, explanations, and the enactment tail.
AMENDMENT_GROUP_HEADER = 'amendment_group_header'
class-attribute
instance-attribute
AMENDMENT_GROUP_TITLE = 'amendment_group_title'
class-attribute
instance-attribute
AMENDMENT_ITEM_DIRECTIVE = 'amendment_item_directive'
class-attribute
instance-attribute
AMENDMENT_ITEM_SKIPPED = 'amendment_item_skipped'
class-attribute
instance-attribute
AMENDMENT_TARGET_ARTICLE_HEADER = 'amendment_target_article_header'
class-attribute
instance-attribute
ANNEX = 'annex'
class-attribute
instance-attribute
ANNEX_HEADER = 'annex_header'
class-attribute
instance-attribute
ARTICLE_HEADER = 'article_header'
class-attribute
instance-attribute
BODY = 'body'
class-attribute
instance-attribute
CHAPTER_HEADER = 'chapter_header'
class-attribute
instance-attribute
CHAPTER_TITLE = 'chapter_title'
class-attribute
instance-attribute
DECISION_CLAUSE_HEADER = 'decision_clause_header'
class-attribute
instance-attribute
ENACTMENT_TAIL = 'enactment_tail'
class-attribute
instance-attribute
EXPLANATION = 'explanation'
class-attribute
instance-attribute
EXPLANATION_AMENDMENT_ITEM = 'explanation_amendment_item'
class-attribute
instance-attribute
EXPLANATION_AMENDMENT_TARGET_ARTICLE_HEADER = 'explanation_amendment_target_article_header'
class-attribute
instance-attribute
EXPLANATION_ARTICLE_HEADER = 'explanation_article_header'
class-attribute
instance-attribute
EXPLANATION_BODY = 'explanation_body'
class-attribute
instance-attribute
FRONT_MATTER = 'front_matter'
class-attribute
instance-attribute
INSTRUCTION_HEADER = 'instruction_header'
class-attribute
instance-attribute
PARAGRAPH_HEADER = 'paragraph_header'
class-attribute
instance-attribute
PARAGRAPH_TITLE = 'paragraph_title'
class-attribute
instance-attribute
PART_HEADER = 'part_header'
class-attribute
instance-attribute
PART_TITLE = 'part_title'
class-attribute
instance-attribute
POINT_HEADER = 'point_header'
class-attribute
instance-attribute
SUBPARAGRAPH_HEADER = 'subparagraph_header'
class-attribute
instance-attribute
SUBPARAGRAPH_TITLE = 'subparagraph_title'
class-attribute
instance-attribute
UNKNOWN = 'unknown'
class-attribute
instance-attribute
RelationType
Bases: StrEnum
Neo4j relationship (edge) types for the Indonesian regulation graph. See ONTOLOGY.md.
AMENDS = 'AMENDS'
class-attribute
instance-attribute
CITES = 'CITES'
class-attribute
instance-attribute
CONTAINS_OBLIGATION = 'CONTAINS_OBLIGATION'
class-attribute
instance-attribute
HAS_ARTICLE = 'HAS_ARTICLE'
class-attribute
instance-attribute
HAS_CHAPTER = 'HAS_CHAPTER'
class-attribute
instance-attribute
HAS_CLAUSE = 'HAS_CLAUSE'
class-attribute
instance-attribute
HAS_EXPLANATION = 'HAS_EXPLANATION'
class-attribute
instance-attribute
HAS_PARAGRAPH = 'HAS_PARAGRAPH'
class-attribute
instance-attribute
HAS_PART = 'HAS_PART'
class-attribute
instance-attribute
HAS_SUBPARAGRAPH = 'HAS_SUBPARAGRAPH'
class-attribute
instance-attribute
HAS_VERSION = 'HAS_VERSION'
class-attribute
instance-attribute
IMPLEMENTS = 'IMPLEMENTS'
class-attribute
instance-attribute
MENTIONS = 'MENTIONS'
class-attribute
instance-attribute
MENTIONS_CONCEPT = 'MENTIONS_CONCEPT'
class-attribute
instance-attribute
REVOKES = 'REVOKES'
class-attribute
instance-attribute
VersionType
Bases: StrEnum
Article version types for Indonesian regulation graph nodes.