Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/supported_entities.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,12 @@ For more information, refer to the [adding new recognizers documentation](analyz
| TR_NATIONAL_ID | The Turkish National Identification Number (TCKN) is a unique 11-digit number issued to all Turkish citizens. | Pattern match, context and checksum. |
| TR_LICENSE_PLATE | Turkish vehicle license plate (plaka): 2-digit province code (01–81), 1–3 letters (A–Z, excluding Q, W, X), and 2–4 digits. Standard civilian format only. Legal basis: KTK Madde 23. | Pattern match, context and province code validation. |

### Philippines

| FieldType | Description | Detection Method |
|------------|---------------------------------------------------------------------------------------------------------|------------------------------------------|
| PH_UMID | Philippine Unified Multi-Purpose ID (UMID) / Common Reference Number (CRN). 12-digit format (e.g., 0111-1234567-8). Acts as a master ID connecting SSS, GSIS, PhilHealth, and Pag-IBIG. Disabled by default. | Pattern match and context |

### Germany

| Entity Type | Description | Detection Method |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,13 @@ recognizers:
enabled: false
country_code: tr

- name: PhUmidRecognizer
supported_languages:
- en
type: predefined
enabled: false
country_code: ph

- name: HuggingFaceNerRecognizer
supported_languages:
- en
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@

# Philippines recognizers
from .country_specific.philippines.ph_tin_recognizer import PhTinRecognizer
from .country_specific.philippines.ph_umid_recognizer import PhUmidRecognizer

# Poland recognizers
from .country_specific.poland.pl_pesel_recognizer import PlPeselRecognizer
Expand Down Expand Up @@ -223,6 +224,7 @@
"HuggingFaceNerRecognizer",
"PhTinRecognizer",
"PlPeselRecognizer",
"PhUmidRecognizer",
"AzureAILanguageRecognizer",
"InAadhaarRecognizer",
"InGstinRecognizer",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
"""Philippines-specific recognizers package."""

from .ph_tin_recognizer import PhTinRecognizer
from .ph_umid_recognizer import PhUmidRecognizer

__all__ = ["PhTinRecognizer"]
__all__ = [
"PhTinRecognizer",
"PhUmidRecognizer",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from typing import List, Optional

from presidio_analyzer import Pattern, PatternRecognizer


class PhUmidRecognizer(PatternRecognizer):
"""
Recognize PH UMID number using regex.

:param patterns: List of patterns to be used by this recognizer
:param context: List of context words to increase confidence in detection
:param supported_language: Language this recognizer supports
:param supported_entity: The entity this recognizer can detect
"""

COUNTRY_CODE = "ph"

PATTERNS = [
Pattern("UMID (with dashes)", r"\b\d{4}-\d{7}-\d\b", 0.5),
Pattern("UMID (without dashes)", r"\b\d{12}\b", 0.3),
]

CONTEXT = [
"umid",
"unified multi-purpose id",
"crn",
"common reference number",
"sss",
"gsis",
"philhealth",
"pag-ibig",
"umid number",
"umid card",
"unified multipurpose id",
]

def __init__(
self,
patterns: Optional[List[Pattern]] = None,
context: Optional[List[str]] = None,
supported_language: str = "en",
supported_entity: str = "PH_UMID",
name: Optional[str] = None,
):
patterns = patterns if patterns else self.PATTERNS
context = context if context else self.CONTEXT
super().__init__(
supported_entity=supported_entity,
patterns=patterns,
context=context,
supported_language=supported_language,
name=name,
)
98 changes: 98 additions & 0 deletions presidio-analyzer/tests/test_ph_umid_recognizer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
"""Tests for Philippine UMID (PH_UMID) recognizer."""

import pytest
from presidio_analyzer.predefined_recognizers import PhUmidRecognizer

from tests import assert_result_within_score_range


@pytest.fixture(scope="module")
def recognizer():
"""Return an instance of PhUmidRecognizer."""
return PhUmidRecognizer()


@pytest.fixture(scope="module")
def entities():
"""Return the supported entities for PhUmidRecognizer."""
return ["PH_UMID"]


@pytest.mark.parametrize(
"text, expected_len, expected_positions, expected_score_ranges",
[
# VALID
("0111-1234567-8", 1, ((0, 14),), ((0.4, 1.0),)),
("0000-0000000-0", 1, ((0, 14),), ((0.4, 1.0),)),
("001112345678", 1, ((0, 12),), ((0.2, 1.0),)),
("My UMID number is 0111-1234567-8", 1, ((18, 32),), ((0.4, 1.0),)),
("UMID: 001112345678", 1, ((6, 18),), ((0.2, 1.0),)),
("CRN: 0111-1234567-8", 1, ((5, 19),), ((0.4, 1.0),)),
("philhealth 001112345678", 1, ((11, 23),), ((0.2, 1.0),)),
("gsis 0111-1234567-8", 1, ((5, 19),), ((0.4, 1.0),)),
("sss: 0111-1234567-8", 1, ((5, 19),), ((0.4, 1.0),)),
("pag-ibig 0111-1234567-8", 1, ((9, 23),), ((0.4, 1.0),)),
("umid card 0111-1234567-8", 1, ((10, 24),), ((0.4, 1.0),)),
("unified multi-purpose id 0111-1234567-8", 1, ((25, 39),), ((0.4, 1.0),)),
("unified multipurpose id 0111-1234567-8", 1, ((24, 38),), ((0.4, 1.0),)),
("common reference number 0111-1234567-8", 1, ((24, 38),), ((0.4, 1.0),)),
("1234-1234567-8", 1, ((0, 14),), ((0.4, 1.0),)),
("9999-9999999-9", 1, ((0, 14),), ((0.4, 1.0),)),
# INVALID
("123456789012", 1, ((0, 12),), ((0.2, 1.0),)),
("987654321098", 1, ((0, 12),), ((0.2, 1.0),)),
("12345", 0, (), ()),
("1234567890123", 0, (), ()),
("hello world", 0, (), ()),
("0111-123456-8", 0, (), ()),
("0111-12345678-8", 0, (), ()),
("011-1234567-8", 0, (), ()),
("01111-1234567-8", 0, (), ()),
("0111-1234567-89", 0, (), ()),
("0111-1234567-", 0, (), ()),
("-1234567-8", 0, (), ()),
("0111 1234567 8", 0, (), ()),
("0111.1234567.8", 0, (), ()),
# MULTIPLE
(
"First: 0111-1234567-8, Second: 001112345678",
2,
((7, 21), (31, 43)),
((0.4, 1.0), (0.2, 1.0)),
),
(
"0000-0000000-0 and 1111-1111111-1",
2,
((0, 14), (19, 33)),
((0.4, 1.0), (0.4, 1.0)),
),
],
)
def test_when_umid_in_text_then_all_umids_found(
text,
expected_len,
expected_positions,
expected_score_ranges,
recognizer,
entities,
):
"""Test that PH UMID recognizer correctly identifies numbers."""
results = recognizer.analyze(text, entities)
assert len(results) == expected_len

for res, (st_pos, fn_pos), (st_score, fn_score) in zip(
results, expected_positions, expected_score_ranges
):
assert_result_within_score_range(
res, entities[0], st_pos, fn_pos, st_score, fn_score
)


def test_supported_entity(recognizer):
"""Test that supported entity is correctly set."""
assert recognizer.supported_entities == ["PH_UMID"]


def test_supported_language(recognizer):
"""Test that supported language is correctly set."""
assert recognizer.supported_language == "en"
Loading