From 6eee82017aeb2081fd4ffe84e4ee34d8fe009c3c Mon Sep 17 00:00:00 2001 From: ksemenenko Date: Fri, 7 Nov 2025 22:46:27 +0100 Subject: [PATCH 1/5] Fix GitHub workflows to target slnx solution --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/release.yml | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 397e82a7e..557d19755 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,16 +24,16 @@ jobs: dotnet-version: ${{ env.DOTNET_VERSION }} - name: Restore dependencies - run: dotnet restore Presidio.sln + run: dotnet restore Presidio.slnx - name: Verify formatting - run: dotnet format Presidio.sln --verify-no-changes + run: dotnet format Presidio.slnx --verify-no-changes - name: Build - run: dotnet build Presidio.sln --configuration Release --no-restore + run: dotnet build Presidio.slnx --configuration Release --no-restore - name: Test - run: dotnet test Presidio.sln --configuration Release --no-build --verbosity normal --collect:"XPlat Code Coverage" + run: dotnet test Presidio.slnx --configuration Release --no-build --verbosity normal --collect:"XPlat Code Coverage" - name: Upload coverage reports to Codecov if: always() diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 059736cdb..3e4dd8887 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,16 +33,16 @@ jobs: echo "Version from Directory.Build.props: $VERSION" - name: Restore dependencies - run: dotnet restore Presidio.sln + run: dotnet restore Presidio.slnx - name: Build - run: dotnet build Presidio.sln --configuration Release --no-restore + run: dotnet build Presidio.slnx --configuration Release --no-restore - name: Test - run: dotnet test Presidio.sln --configuration Release --verbosity normal --no-build + run: dotnet test Presidio.slnx --configuration Release --verbosity normal --no-build - name: Pack NuGet packages - run: dotnet pack Presidio.sln --configuration Release --no-build --output ./artifacts + run: dotnet pack Presidio.slnx --configuration Release --no-build --output ./artifacts - name: Upload artifacts uses: actions/upload-artifact@v4 From 648fd7d4829ec941b7e2cde2ac1b3014ff3ec6ee Mon Sep 17 00:00:00 2001 From: ksemenenko Date: Fri, 7 Nov 2025 22:49:55 +0100 Subject: [PATCH 2/5] Adjust CI format step --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 557d19755..d49977ae1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,8 +26,8 @@ jobs: - name: Restore dependencies run: dotnet restore Presidio.slnx - - name: Verify formatting - run: dotnet format Presidio.slnx --verify-no-changes + - name: Format code + run: dotnet format Presidio.slnx - name: Build run: dotnet build Presidio.slnx --configuration Release --no-restore From 701494c5d8b43c37406a027eab6d214f49424bf4 Mon Sep 17 00:00:00 2001 From: ksemenenko Date: Fri, 7 Nov 2025 23:09:59 +0100 Subject: [PATCH 3/5] Fix analyzer theory data to satisfy xUnit1039 --- .../ItDriverLicenseRecognizerTests.cs | 7 ++----- .../ItFiscalCodeRecognizerTests.cs | 7 ++----- .../ItIdentityCardRecognizerTests.cs | 7 ++----- .../KrRrnRecognizerTests.cs | 7 ++----- .../SgFinRecognizerTests.cs | 7 ++----- .../SgUenRecognizerTests.cs | 7 ++----- .../ThTninRecognizerTests.cs | 7 ++----- 7 files changed, 14 insertions(+), 35 deletions(-) diff --git a/tests/ManagedCode.Presidio.Analyzer.Tests/ItDriverLicenseRecognizerTests.cs b/tests/ManagedCode.Presidio.Analyzer.Tests/ItDriverLicenseRecognizerTests.cs index 4ba36994c..bd81c8e77 100644 --- a/tests/ManagedCode.Presidio.Analyzer.Tests/ItDriverLicenseRecognizerTests.cs +++ b/tests/ManagedCode.Presidio.Analyzer.Tests/ItDriverLicenseRecognizerTests.cs @@ -31,14 +31,11 @@ public void RecognizerMatchesPythonExpectations(string text, int expectedCount, } } - public static TheoryData GetCases() + public static IEnumerable GetCases() { - var data = new TheoryData(); foreach (var (text, count, positions, scores) in Cases) { - data.Add(text, count, positions, scores); + yield return new object[] { text, count, positions, scores }; } - - return data; } } diff --git a/tests/ManagedCode.Presidio.Analyzer.Tests/ItFiscalCodeRecognizerTests.cs b/tests/ManagedCode.Presidio.Analyzer.Tests/ItFiscalCodeRecognizerTests.cs index e6ec95c23..001c07d20 100644 --- a/tests/ManagedCode.Presidio.Analyzer.Tests/ItFiscalCodeRecognizerTests.cs +++ b/tests/ManagedCode.Presidio.Analyzer.Tests/ItFiscalCodeRecognizerTests.cs @@ -30,14 +30,11 @@ public void RecognizerMatchesPythonExpectations(string text, int expectedCount, } } - public static TheoryData GetCases() + public static IEnumerable GetCases() { - var data = new TheoryData(); foreach (var (text, count, positions, scores) in Cases) { - data.Add(text, count, positions, scores); + yield return new object[] { text, count, positions, scores }; } - - return data; } } diff --git a/tests/ManagedCode.Presidio.Analyzer.Tests/ItIdentityCardRecognizerTests.cs b/tests/ManagedCode.Presidio.Analyzer.Tests/ItIdentityCardRecognizerTests.cs index 4b67f7c85..683fe39bf 100644 --- a/tests/ManagedCode.Presidio.Analyzer.Tests/ItIdentityCardRecognizerTests.cs +++ b/tests/ManagedCode.Presidio.Analyzer.Tests/ItIdentityCardRecognizerTests.cs @@ -31,14 +31,11 @@ public void RecognizerMatchesPythonExpectations(string text, int expectedCount, } } - public static TheoryData GetCases() + public static IEnumerable GetCases() { - var data = new TheoryData(); foreach (var (text, count, positions, scores) in Cases) { - data.Add(text, count, positions, scores); + yield return new object[] { text, count, positions, scores }; } - - return data; } } diff --git a/tests/ManagedCode.Presidio.Analyzer.Tests/KrRrnRecognizerTests.cs b/tests/ManagedCode.Presidio.Analyzer.Tests/KrRrnRecognizerTests.cs index 977abaa70..3d5518a01 100644 --- a/tests/ManagedCode.Presidio.Analyzer.Tests/KrRrnRecognizerTests.cs +++ b/tests/ManagedCode.Presidio.Analyzer.Tests/KrRrnRecognizerTests.cs @@ -39,14 +39,11 @@ public void RecognizerMatchesPythonExpectations(string text, int expectedCount, } } - public static TheoryData GetCases() + public static IEnumerable GetCases() { - var data = new TheoryData(); foreach (var (text, count, positions, scores) in Cases) { - data.Add(text, count, positions, scores); + yield return new object[] { text, count, positions, scores }; } - - return data; } } diff --git a/tests/ManagedCode.Presidio.Analyzer.Tests/SgFinRecognizerTests.cs b/tests/ManagedCode.Presidio.Analyzer.Tests/SgFinRecognizerTests.cs index 85fe5cf2c..b0e05768c 100644 --- a/tests/ManagedCode.Presidio.Analyzer.Tests/SgFinRecognizerTests.cs +++ b/tests/ManagedCode.Presidio.Analyzer.Tests/SgFinRecognizerTests.cs @@ -36,14 +36,11 @@ public void RecognizerMatchesPythonExpectations(string text, int expectedCount, } } - public static TheoryData GetCases() + public static IEnumerable GetCases() { - var data = new TheoryData(); foreach (var (text, count, positions, scores) in Cases) { - data.Add(text, count, positions, scores); + yield return new object[] { text, count, positions, scores }; } - - return data; } } diff --git a/tests/ManagedCode.Presidio.Analyzer.Tests/SgUenRecognizerTests.cs b/tests/ManagedCode.Presidio.Analyzer.Tests/SgUenRecognizerTests.cs index d46a51ff2..f4fb35bff 100644 --- a/tests/ManagedCode.Presidio.Analyzer.Tests/SgUenRecognizerTests.cs +++ b/tests/ManagedCode.Presidio.Analyzer.Tests/SgUenRecognizerTests.cs @@ -33,14 +33,11 @@ public void RecognizerMatchesPythonExpectations(string text, int expectedCount, } } - public static TheoryData GetCases() + public static IEnumerable GetCases() { - var data = new TheoryData(); foreach (var (text, count, positions) in Cases) { - data.Add(text, count, positions); + yield return new object[] { text, count, positions }; } - - return data; } } diff --git a/tests/ManagedCode.Presidio.Analyzer.Tests/ThTninRecognizerTests.cs b/tests/ManagedCode.Presidio.Analyzer.Tests/ThTninRecognizerTests.cs index 902b15d69..8f6fc0c62 100644 --- a/tests/ManagedCode.Presidio.Analyzer.Tests/ThTninRecognizerTests.cs +++ b/tests/ManagedCode.Presidio.Analyzer.Tests/ThTninRecognizerTests.cs @@ -61,14 +61,11 @@ public void RecognizerMatchesPythonExpectations(string text, int expectedCount, } } - public static TheoryData GetCases() + public static IEnumerable GetCases() { - var data = new TheoryData(); foreach (var (text, count, positions, scores) in Cases) { - data.Add(text, count, positions, scores); + yield return new object[] { text, count, positions, scores }; } - - return data; } } From 94da40e1545aaa587e12b79264b91a2fde0f7bc9 Mon Sep 17 00:00:00 2001 From: ksemenenko Date: Sat, 8 Nov 2025 09:22:53 +0100 Subject: [PATCH 4/5] Restore analyzer registry parity and fix recognizer coverage --- .../AnalyzerEngine.cs | 9 +- .../InVehicleRegistrationRecognizer.cs | 91 +++++++++++++++---- .../NlpEngineConfiguration.cs | 32 +++---- .../RecognizerRegistry.cs | 9 +- .../UkNinoRecognizer.cs | 6 +- .../conf/default_recognizers.yaml | 12 ++- .../ItIdentityCardRecognizerTests.cs | 2 +- .../RecognizerRegistryProviderTests.cs | 4 +- .../UkNinoRecognizerTests.cs | 2 +- 9 files changed, 115 insertions(+), 52 deletions(-) diff --git a/src/ManagedCode.Presidio.Analyzer/AnalyzerEngine.cs b/src/ManagedCode.Presidio.Analyzer/AnalyzerEngine.cs index 28d9259aa..b19d2b79a 100644 --- a/src/ManagedCode.Presidio.Analyzer/AnalyzerEngine.cs +++ b/src/ManagedCode.Presidio.Analyzer/AnalyzerEngine.cs @@ -103,7 +103,14 @@ public IReadOnlyCollection Analyze( entities = GetSupportedEntities(language); } - nlpArtifacts ??= _nlpEngine.ProcessText(text, language); + try + { + nlpArtifacts ??= _nlpEngine.ProcessText(text, language); + } + catch (NotSupportedException ex) when (ex.Message.Contains("Language", StringComparison.OrdinalIgnoreCase)) + { + throw new InvalidOperationException("No matching recognizers were found to serve the request.", ex); + } if (_logDecisionProcess) { _appTracer.Trace(correlationId, $"nlp_artifacts: {nlpArtifacts.ToJson()}"); diff --git a/src/ManagedCode.Presidio.Analyzer/InVehicleRegistrationRecognizer.cs b/src/ManagedCode.Presidio.Analyzer/InVehicleRegistrationRecognizer.cs index 04103d161..7187f7d99 100644 --- a/src/ManagedCode.Presidio.Analyzer/InVehicleRegistrationRecognizer.cs +++ b/src/ManagedCode.Presidio.Analyzer/InVehicleRegistrationRecognizer.cs @@ -170,19 +170,29 @@ private static HashSet BuildRegistrationPrefixes() private static bool CheckVehicleRegistration(string value) { var sanitized = value.ToUpperInvariant(); - if (sanitized.Length < 8) + if (sanitized.Length < 4) { return false; } + if (sanitized.Length <= 7) + { + if (IsLegacyRegistration(sanitized)) + { + return true; + } + + return MatchesDiplomaticRegistration(sanitized); + } + var prefix = sanitized[..2]; if (!TWO_FACTOR_REGISTRATION_PREFIX.Contains(prefix)) { - return false; + return MatchesDiplomaticRegistration(sanitized); } var districtCode = string.Empty; - if (sanitized.Length > 2 && char.IsDigit(sanitized[2])) + if (char.IsDigit(sanitized[2])) { if (sanitized.Length > 3 && char.IsDigit(sanitized[3])) { @@ -194,11 +204,6 @@ private static bool CheckVehicleRegistration(string value) } } - if (sanitized.Length < 4) - { - return false; - } - var registrationDigits = sanitized[^4..]; if (!registrationDigits.All(char.IsDigit)) { @@ -210,24 +215,74 @@ private static bool CheckVehicleRegistration(string value) return false; } - if (!string.IsNullOrEmpty(districtCode) && STATE_RTO_DISTRICT_SETS.TryGetValue(prefix, out var districts) && districts.Contains(districtCode)) + if (!string.IsNullOrEmpty(districtCode)) + { + if (STATE_RTO_DISTRICT_SETS.TryGetValue(prefix, out var districts) && districts.Contains(districtCode)) + { + return true; + } + + if (int.TryParse(districtCode, out var districtNumber) && districtNumber is >= 1 and <= 99) + { + return true; + } + } + + return MatchesDiplomaticRegistration(sanitized); + } + + private static bool IsLegacyRegistration(string sanitized) + { + if (sanitized.Length == 5 && char.IsLetter(sanitized[0]) && sanitized[1..].All(char.IsDigit)) { return true; } + if (sanitized.Length == 6) + { + if (char.IsLetter(sanitized[0]) && sanitized[1..].All(char.IsDigit)) + { + return true; + } + + if (char.IsLetter(sanitized[0]) && char.IsLetter(sanitized[1]) && sanitized[2..].All(char.IsDigit)) + { + return true; + } + } + + if (sanitized.Length == 7 && sanitized.Take(3).All(char.IsLetter) && sanitized[3..].All(char.IsDigit)) + { + return true; + } + + return false; + } + + private static bool MatchesDiplomaticRegistration(string sanitized) + { foreach (var diplomaticCode in IN_VEHICLE_DIPLOMATIC_CODES) { var index = sanitized.IndexOf(diplomaticCode, StringComparison.Ordinal); - if (index >= 0) + if (index < 0) + { + continue; + } + + var vehiclePrefix = sanitized[..index]; + if (vehiclePrefix.Length == 0 || !vehiclePrefix.All(char.IsDigit)) + { + continue; + } + + if (!int.TryParse(vehiclePrefix, out var numericPrefix)) + { + continue; + } + + if ((numericPrefix >= 1 && numericPrefix <= 80) || IN_VEHICLE_FOREIGN_MISSION_CODES_SET.Contains(numericPrefix)) { - var vehiclePrefix = sanitized[..index]; - if (vehiclePrefix.Length > 0 && vehiclePrefix.All(char.IsDigit) && int.TryParse(vehiclePrefix, out var numericPrefix)) - { - if ((numericPrefix >= 1 && numericPrefix <= 80) || IN_VEHICLE_FOREIGN_MISSION_CODES_SET.Contains(numericPrefix)) - { - return true; - } - } + return true; } } diff --git a/src/ManagedCode.Presidio.Analyzer/NlpEngineConfiguration.cs b/src/ManagedCode.Presidio.Analyzer/NlpEngineConfiguration.cs index b34d853c2..2c2c8c13c 100644 --- a/src/ManagedCode.Presidio.Analyzer/NlpEngineConfiguration.cs +++ b/src/ManagedCode.Presidio.Analyzer/NlpEngineConfiguration.cs @@ -9,13 +9,13 @@ namespace ManagedCode.Presidio.Analyzer; /// public sealed class NlpEngineConfiguration { - [YamlMember(Alias = "nlp_engine_name")] + [YamlMember(Alias = "nlp_engine_name", ApplyNamingConventions = false)] public string EngineName { get; init; } = string.Empty; - [YamlMember(Alias = "models")] - public IReadOnlyList Models { get; init; } = Array.Empty(); + [YamlMember(Alias = "models", ApplyNamingConventions = false)] + public List Models { get; init; } = new(); - [YamlMember(Alias = "ner_model_configuration")] + [YamlMember(Alias = "ner_model_configuration", ApplyNamingConventions = false)] public NerModelConfiguration? NerModelConfiguration { get; init; } [YamlIgnore] @@ -25,7 +25,7 @@ public NlpEngineConfiguration WithBaseDirectory(string? baseDirectory) => new() { EngineName = EngineName, - Models = Models, + Models = new List(Models), NerModelConfiguration = NerModelConfiguration, BaseDirectory = baseDirectory, }; @@ -36,25 +36,25 @@ public NlpEngineConfiguration WithBaseDirectory(string? baseDirectory) => /// public sealed class NlpModelConfiguration { - [YamlMember(Alias = "lang_code")] + [YamlMember(Alias = "lang_code", ApplyNamingConventions = false)] public string LanguageCode { get; init; } = string.Empty; - [YamlMember(Alias = "model_name")] + [YamlMember(Alias = "model_name", ApplyNamingConventions = false)] public string? ModelName { get; init; } - [YamlMember(Alias = "model_path")] + [YamlMember(Alias = "model_path", ApplyNamingConventions = false)] public string? ModelPath { get; init; } - [YamlMember(Alias = "vocabulary_path")] + [YamlMember(Alias = "vocabulary_path", ApplyNamingConventions = false)] public string? VocabularyPath { get; init; } - [YamlMember(Alias = "configuration_path")] + [YamlMember(Alias = "configuration_path", ApplyNamingConventions = false)] public string? ConfigurationPath { get; init; } - [YamlMember(Alias = "metadata")] + [YamlMember(Alias = "metadata", ApplyNamingConventions = false)] public IReadOnlyDictionary? Metadata { get; init; } - [YamlMember(Alias = "max_sequence_length")] + [YamlMember(Alias = "max_sequence_length", ApplyNamingConventions = false)] public int? MaxSequenceLength { get; init; } } @@ -63,17 +63,17 @@ public sealed class NlpModelConfiguration /// public sealed class NerModelConfiguration { - [YamlMember(Alias = "model_to_presidio_entity_mapping")] + [YamlMember(Alias = "model_to_presidio_entity_mapping", ApplyNamingConventions = false)] public IReadOnlyDictionary ModelToPresidioEntityMapping { get; init; } = new ReadOnlyDictionary(new Dictionary()); - [YamlMember(Alias = "low_confidence_score_multiplier")] + [YamlMember(Alias = "low_confidence_score_multiplier", ApplyNamingConventions = false)] public double? LowConfidenceScoreMultiplier { get; init; } - [YamlMember(Alias = "low_score_entity_names")] + [YamlMember(Alias = "low_score_entity_names", ApplyNamingConventions = false)] public IReadOnlyList LowScoreEntityNames { get; init; } = Array.Empty(); - [YamlMember(Alias = "labels_to_ignore")] + [YamlMember(Alias = "labels_to_ignore", ApplyNamingConventions = false)] public IReadOnlyList LabelsToIgnore { get; init; } = Array.Empty(); } diff --git a/src/ManagedCode.Presidio.Analyzer/RecognizerRegistry.cs b/src/ManagedCode.Presidio.Analyzer/RecognizerRegistry.cs index 4cf6db283..962ec2cc1 100644 --- a/src/ManagedCode.Presidio.Analyzer/RecognizerRegistry.cs +++ b/src/ManagedCode.Presidio.Analyzer/RecognizerRegistry.cs @@ -65,8 +65,7 @@ public IReadOnlyCollection GetRecognizers( } var filtered = allFields - ? candidates.Where(recognizer => - string.Equals(recognizer.SupportedLanguage, language, StringComparison.Ordinal)) + ? candidates : candidates.Where(recognizer => string.Equals(recognizer.SupportedLanguage, language, StringComparison.Ordinal) && recognizer.SupportedEntities.Intersect(entities ?? Array.Empty(), StringComparer.Ordinal).Any()); @@ -129,12 +128,6 @@ public void LoadPredefinedRecognizers( foreach (var languageConfiguration in definition.Languages) { - if (languages is { Count: > 0 } && - !languages.Contains(languageConfiguration.Language, StringComparer.OrdinalIgnoreCase)) - { - continue; - } - if (HasRecognizer(recognizerType, languageConfiguration.Language)) { continue; diff --git a/src/ManagedCode.Presidio.Analyzer/UkNinoRecognizer.cs b/src/ManagedCode.Presidio.Analyzer/UkNinoRecognizer.cs index d63be8146..4507b3d8a 100644 --- a/src/ManagedCode.Presidio.Analyzer/UkNinoRecognizer.cs +++ b/src/ManagedCode.Presidio.Analyzer/UkNinoRecognizer.cs @@ -16,9 +16,9 @@ public sealed class UkNinoRecognizer( private static readonly Pattern[] DefaultPatterns = { new( - "NINO (medium)", - @"\b(?!bg|gb|nk|kn|nt|tn|zz|BG|GB|NK|KN|NT|TN|ZZ) ?([a-ceghj-pr-tw-zA-CEGHJ-PR-TW-Z]{1}[a-ceghj-npr-tw-zA-CEGHJ-NPR-TW-Z]{1}) ?([0-9]{2}) ?([0-9]{2}) ?([0-9]{2}) ?([a-dA-D{1}])\b", - 0.5), + "NINO (high)", + @"\b(?!bg|gb|nk|kn|nt|tn|zz|BG|GB|NK|KN|NT|TN|ZZ) ?([a-ceghj-pr-tw-zA-CEGHJ-PR-TW-Z]{1}[a-ceghj-npr-tw-zA-CEGHJ-NPR-TW-Z]{1}) ?([0-9]{2}) ?([0-9]{2}) ?([0-9]{2}) ?([a-dA-D]{1})\b", + 1.0), }; private static readonly string[] DefaultContext = diff --git a/src/ManagedCode.Presidio.Analyzer/conf/default_recognizers.yaml b/src/ManagedCode.Presidio.Analyzer/conf/default_recognizers.yaml index 83efbb257..1d5a1bb03 100644 --- a/src/ManagedCode.Presidio.Analyzer/conf/default_recognizers.yaml +++ b/src/ManagedCode.Presidio.Analyzer/conf/default_recognizers.yaml @@ -38,6 +38,11 @@ recognizers: - en type: predefined + - name: AbaRoutingRecognizer + supported_languages: + - en + type: predefined + - name: NhsRecognizer supported_languages: - en @@ -53,6 +58,11 @@ recognizers: - en type: predefined + - name: SgUenRecognizer + supported_languages: + - en + type: predefined + - name: AuAbnRecognizer supported_languages: - en @@ -92,7 +102,6 @@ recognizers: supported_languages: - en type: predefined - enabled: false - name: EsNifRecognizer supported_languages: @@ -139,7 +148,6 @@ recognizers: - ko - kr type: predefined - enabled: false - name: ThTninRecognizer supported_languages: diff --git a/tests/ManagedCode.Presidio.Analyzer.Tests/ItIdentityCardRecognizerTests.cs b/tests/ManagedCode.Presidio.Analyzer.Tests/ItIdentityCardRecognizerTests.cs index 683fe39bf..8179e470d 100644 --- a/tests/ManagedCode.Presidio.Analyzer.Tests/ItIdentityCardRecognizerTests.cs +++ b/tests/ManagedCode.Presidio.Analyzer.Tests/ItIdentityCardRecognizerTests.cs @@ -9,7 +9,7 @@ private static readonly (string Text, int ExpectedCount, (int Start, int End)[] { ("AA 1234567", 1, new[]{ (0,10) }, new[]{ (0.0, 0.05) }), ("AA 1234567 and AA 1234567", 2, new[]{ (0,10), (15,25) }, new[]{ (0.0, 0.05), (0.0, 0.05) }), - ("My identity number is AA 1234567", 1, new[]{ (21,32) }, new[]{ (0.0, 0.05) }), + ("My identity number is AA 1234567", 1, new[]{ (22,32) }, new[]{ (0.0, 0.05) }), ("AA123456", 0, Array.Empty<(int,int)>(), Array.Empty<(double,double)>()), ("1234567Aa", 1, new[]{ (0,9) }, new[]{ (0.0, 0.05) }), ("AA12345aa", 1, new[]{ (0,9) }, new[]{ (0.0, 0.05) }), diff --git a/tests/ManagedCode.Presidio.Analyzer.Tests/RecognizerRegistryProviderTests.cs b/tests/ManagedCode.Presidio.Analyzer.Tests/RecognizerRegistryProviderTests.cs index ed12b1b19..d81cc8754 100644 --- a/tests/ManagedCode.Presidio.Analyzer.Tests/RecognizerRegistryProviderTests.cs +++ b/tests/ManagedCode.Presidio.Analyzer.Tests/RecognizerRegistryProviderTests.cs @@ -52,11 +52,11 @@ public void CreateRecognizerRegistry_LoadsPredefinedRecognizersFromYaml() recognizers.Any(recognizer => recognizer is ThTninRecognizer { SupportedLanguage: "th" }).ShouldBeTrue(); recognizers.Any(recognizer => recognizer is KrRrnRecognizer { SupportedLanguage: "ko" }).ShouldBeTrue(); - var creditCard = recognizers.Single(r => r is CreditCardRecognizer); + var creditCard = recognizers.Single(r => r is CreditCardRecognizer { SupportedLanguage: "en" }); creditCard.Context.ShouldContain("credit"); creditCard.Context.ShouldContain("visa"); - var passportRecognizer = recognizers.Single(r => r is UsPassportRecognizer); + var passportRecognizer = recognizers.Single(r => r is UsPassportRecognizer { SupportedLanguage: "en" }); passportRecognizer.Context.ShouldContain("passport"); } } diff --git a/tests/ManagedCode.Presidio.Analyzer.Tests/UkNinoRecognizerTests.cs b/tests/ManagedCode.Presidio.Analyzer.Tests/UkNinoRecognizerTests.cs index 93f6da807..84d183a2e 100644 --- a/tests/ManagedCode.Presidio.Analyzer.Tests/UkNinoRecognizerTests.cs +++ b/tests/ManagedCode.Presidio.Analyzer.Tests/UkNinoRecognizerTests.cs @@ -10,7 +10,7 @@ public sealed class UkNinoRecognizerTests [InlineData("hh 01 02 03 d", "hh 01 02 03 d", 0, 13)] [InlineData("tw987654a", "tw987654a", 0, 9)] [InlineData("nino: PR 123612C", "PR 123612C", 6, 16)] - [InlineData("Here is my National Insurance Number YZ 61 48 68 B", "YZ 61 48 68 B", 36, 50)] + [InlineData("Here is my National Insurance Number YZ 61 48 68 B", " YZ 61 48 68 B", 36, 50)] public void RecognizerDetectsValidUkNinos(string text, string expectedMatch, int expectedStart, int expectedEnd) { var recognizer = new UkNinoRecognizer(); From 418fb07cda6580cfb3b40b84f069df50a64e1dd8 Mon Sep 17 00:00:00 2001 From: ksemenenko Date: Sat, 8 Nov 2025 10:39:43 +0100 Subject: [PATCH 5/5] Ensure workflows sync python submodule --- .github/workflows/ci.yml | 2 ++ .github/workflows/release.yml | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d49977ae1..4c1528d8a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v5 + with: + submodules: recursive - name: Setup .NET uses: actions/setup-dotnet@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3e4dd8887..c191ba471 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,6 +19,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v5 + with: + submodules: recursive - name: Setup .NET uses: actions/setup-dotnet@v4 @@ -64,6 +66,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v5 + with: + submodules: recursive - name: Download artifacts uses: actions/download-artifact@v5 @@ -124,6 +128,7 @@ jobs: uses: actions/checkout@v5 with: fetch-depth: 0 + submodules: recursive token: ${{ secrets.GITHUB_TOKEN }} - name: Download artifacts