From 0424ba9980370462b82ffbda210e9e73dfa9d7d4 Mon Sep 17 00:00:00 2001 From: Raghu Date: Mon, 24 Aug 2026 16:11:31 +0100 Subject: [PATCH 1/2] CONFIG: Fix net8.0 targets paths and add LibPostalAutoDownload opt-out Two changes to NHSISL.LibPostalClient.targets. 1. Release blocker. Commit b3442e9 moved the packed native files from contentFiles/any/net8.0 to contentFiles/any/net10.0, but the targets file still resolved Headers, WindowsNativeFiles and LinuxNativeFiles from the net8.0 paths. Verified against a real consumer project: the unfixed package fails the consumer build outright with MSB3030 ("Could not copy ... contentFiles/any/net8.0/libpostal.h"), and no native library reaches the output directory. 2. Issue #97. Adds a LibPostalAutoDownload MSBuild property, defaulting to true so current behaviour is unchanged. When set to false the LibpostalData.zip download is skipped on both build and publish, and Clean no longer deletes the zip, which is what caused the next build to download it again. Verified with a consumer project referencing the packed package: natives copy to the output directory, and LibPostalAutoDownload=false suppresses the download. Co-Authored-By: Claude Opus 5 --- .../NHSISL.LibPostalClient.targets | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/NHSISL.LibPostalClient/NHSISL.LibPostalClient.targets b/NHSISL.LibPostalClient/NHSISL.LibPostalClient.targets index 039f843..d1fcba9 100644 --- a/NHSISL.LibPostalClient/NHSISL.LibPostalClient.targets +++ b/NHSISL.LibPostalClient/NHSISL.LibPostalClient.targets @@ -1,16 +1,21 @@  - + + Include="$(MSBuildThisFileDirectory)\..\contentFiles\any\net10.0\windows\libpostal-1.dll" /> + Include="$(MSBuildThisFileDirectory)\..\contentFiles\any\net10.0\linux_x86_64\libpostal-1.so" /> + + true + + - + @@ -22,7 +27,7 @@ + Condition="'$(LibPostalAutoDownload)' == 'true' AND !Exists('$(TargetDir)\LibpostalData.zip') == 'True'" /> @@ -44,10 +49,13 @@ + DestinationFolder="$(PublishDir)" + Condition="'$(LibPostalAutoDownload)' == 'true' AND !Exists('$(PublishDir)\LibpostalData.zip') == 'True'" /> - + OverwriteReadOnlyFiles="true" + Condition="Exists('$(PublishDir)\LibpostalData.zip') == 'True'" /> + From 589d32479e6907237fb070e93ff4276c708b324b Mon Sep 17 00:00:00 2001 From: Raghu Date: Mon, 24 Aug 2026 16:13:17 +0100 Subject: [PATCH 2/2] DOCUMENTATION: Add Getting Started section to README Addresses #52, open since September 2024, which asked how to actually use the package. The README had no usage section at all. Adds install, parse and expand examples, a configuration table, the LibPostalAutoDownload option, and a note on the test project DllNotFoundException reported in #58 with its workaround. All code samples and their outputs were run against the package built from this branch, so the parser labels shown are real output rather than illustrative. Co-Authored-By: Claude Opus 5 --- README.md | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/README.md b/README.md index bc675e9..67920fe 100644 --- a/README.md +++ b/README.md @@ -13,3 +13,140 @@ Libpostal can break down an address into its constituent components, such as str ## Address Normalization: It can normalize addresses to a consistent format, reducing variations and inconsistencies that may exist in address data. + +# Getting Started + +## Install + +``` +dotnet add package NHSISL.LibPostalClient +``` + +> **The first build downloads roughly 800MB of libpostal training data** and unzips it into +> your output directory. This is expected, and it only happens when the data is not already +> present. See [Controlling the data download](#controlling-the-data-download) below if you +> need to manage this yourself. + +## Parse an address + +`ParseAddressAsync` breaks an address into labelled components. + +```csharp +using NHSISL.LibPostalClient.Clients; +using NHSISL.LibPostalClient.Models.Brokers.LibPostal; + +var dataDirectory = Path.Combine(AppContext.BaseDirectory, "Data"); + +var config = new LibPostalConfiguration +{ + DataDirectory = dataDirectory, + ParserDataDirectory = dataDirectory, + LanguageClassifierDataDirectory = dataDirectory, + PaserOptions = new ParserOptions + { + Country = "gb", + Language = "en", + } +}; + +var client = new LibPostalClient(config); + +List> parsed = + await client.ParseAddressAsync("12 High Street, Little Houghton, Northamptonshire, AB1 2CD"); + +foreach (var component in parsed) +{ + Console.WriteLine($"{component.Key}: {component.Value}"); +} +``` + +Output: + +``` +house_number: 12 +road: high street +city: little houghton +state_district: northamptonshire +postcode: ab1 2cd +``` + +The component keys are libpostal's parser labels — the full list is in the +[libpostal documentation](https://github.com/openvenues/libpostal#parser-labels). + +## Expand an address + +`ExpandAddressAsync` returns normalised variations of an address, which is useful for +comparing or de-duplicating addresses that are written differently. + +```csharp +string[] expansions = await client.ExpandAddressAsync("12 High St, Northants"); + +foreach (string expansion in expansions) +{ + Console.WriteLine(expansion); +} +``` + +Output: + +``` +12 high saint northants +12 high street northants +``` + +## Configuration + +| Property | Description | +| --- | --- | +| `DataDirectory` | Folder holding the libpostal data files. | +| `ParserDataDirectory` | Folder holding the parser model. Usually the same as `DataDirectory`. | +| `LanguageClassifierDataDirectory` | Folder holding the language classifier model. Usually the same as `DataDirectory`. | +| `PaserOptions.Country` | Two letter country hint, for example `gb`. | +| `PaserOptions.Language` | Two letter language hint, for example `en`. | + +All three directories normally point at the `Data` folder that the package unzips into your +build output, as shown in the example above. + +> `PaserOptions` is spelled that way in the public API. It is a known typo that is kept for +> backwards compatibility. + +## Controlling the data download + +By default the package downloads `LibpostalData.zip` when it is not already present in the +output directory, and removes it on `Clean` so the next build fetches it again. + +If you manage the data yourself — for example in CI, or in an enterprise build where the +files are already on disk — set the following in your project file: + +```xml + + false + +``` + +With this set to `false`: + +- the download is skipped on both build and publish +- `Clean` no longer deletes `LibpostalData.zip` + +You are then responsible for making the libpostal data available in the directories you +point `LibPostalConfiguration` at. + +## Using the client from a test project + +The package copies the native libpostal libraries into the output directory using MSBuild +targets that ship in the package. These targets only run for projects that reference the +package **directly**. + +If your test project reaches the client only through a `ProjectReference` to another +project, the native libraries will not be copied into the test output and you will see: + +``` +System.DllNotFoundException : Unable to load DLL 'libpostal-1' +``` + +Add the package reference to the test project as well: + +```xml + +```