span-data 0.1.3__cp311-cp311-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## 0.1.0 - 2026-05-12
6
+
7
+ ### Added
8
+ - Initial public release of `span_data`.
9
+ - Identity graphing library built on Splink and DuckDB.
10
+ - Support for DataFrame, CSV, and Snowflake ingestion.
11
+ - Manual override workflows for merge, split, and assign operations.
12
+
13
+ ### Packaging
14
+ - Added PyPI packaging metadata in `pyproject.toml`.
15
+ - Added BSD 3-Clause `LICENSE`.
16
+ - Added `THIRD_PARTY_NOTICES.md` for direct runtime dependencies.
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Data Loft Technologies Inc
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,35 @@
1
+ ## Third-Party Notices
2
+
3
+ This project depends on third-party Python packages. The following list covers
4
+ the direct runtime dependencies currently declared in `pyproject.toml`.
5
+
6
+ License data was collected from package metadata on PyPI and, where metadata
7
+ was missing, from the corresponding upstream repository license declaration.
8
+
9
+ If dependencies are added or updated, this file should be reviewed and updated.
10
+
11
+ ### Direct Runtime Dependencies
12
+
13
+ - `duckdb` (`MIT`)
14
+ - PyPI: <https://pypi.org/project/duckdb/>
15
+ - `email-validator` (`Unlicense`)
16
+ - PyPI: <https://pypi.org/project/email-validator/>
17
+ - `pandas` (`BSD-3-Clause`)
18
+ - PyPI: <https://pypi.org/project/pandas/>
19
+ - `phonenumbers` (`Apache-2.0`)
20
+ - PyPI: <https://pypi.org/project/phonenumbers/>
21
+ - Upstream license source: <https://github.com/daviddrysdale/python-phonenumbers>
22
+ - `snowflake-connector-python` (`Apache-2.0`)
23
+ - PyPI: <https://pypi.org/project/snowflake-connector-python/>
24
+ - `splink` (`MIT`)
25
+ - PyPI: <https://pypi.org/project/splink/>
26
+ - Upstream license source: <https://github.com/moj-analytical-services/splink>
27
+
28
+ ### Notes
29
+
30
+ - This notice file is informational and does not replace the terms of the
31
+ third-party licenses.
32
+ - The maintainers of this package, acting on behalf of Data Loft Technologies Inc.,
33
+ are responsible for reviewing transitive dependencies and any bundled artifacts
34
+ before each release. Downstream users may still perform their own license and
35
+ compliance reviews as required by their organization or jurisdiction.
@@ -0,0 +1,179 @@
1
+ # Using the ID Grapher with Snowflake
2
+
3
+ This document provides a step-by-step guide on how to use the `id_grapher`
4
+ library to read data from and write data to Snowflake.
5
+
6
+ ## Overview
7
+
8
+ The `id_grapher` library is a tool for identity resolution. It uses the
9
+ `splink` library to identify and cluster records that refer to the same entity.
10
+ This guide focuses on using the `id_grapher` with Snowflake as the data source
11
+ and destination.
12
+
13
+ ## Installation
14
+
15
+ Install the published package from PyPI:
16
+
17
+ ```bash
18
+ pip install span-data
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ Here's a complete example of how to use the `id_grapher` with Snowflake:
24
+
25
+ ```python
26
+ from span_data.id_grapher import IDGrapher, FieldDefinitionMap
27
+ import snowflake.connector
28
+
29
+ # 1. Connect to Snowflake
30
+ # Replace with your Snowflake connection details
31
+ con = snowflake.connector.connect(
32
+ user="<your_user>",
33
+ password="<your_password>",
34
+ account="<your_account>",
35
+ warehouse="<your_warehouse>",
36
+ database="<your_database>",
37
+ schema="<your_schema>"
38
+ )
39
+
40
+ # 2. Define the field map
41
+ # This map tells the ID Grapher how to map the columns in your Snowflake
42
+ # table to the standard fields used by the grapher. The keys of the dictionary
43
+ # are the column names in your Snowflake table, and the values specify the
44
+ # 'type' of data and the 'mapping' to the ID Grapher's internal field name.
45
+ # This example is based on the configuration found in
46
+ # `libs/id_grapher/tests/config/id_graph_map_config.yaml`.
47
+ field_map = FieldDefinitionMap(
48
+ {
49
+ "FIRSTNAME": {
50
+ "type": "text",
51
+ "mapping": "first_name"
52
+ },
53
+ "LASTNAME": {
54
+ "type": "text",
55
+ "mapping": "last_name"
56
+ },
57
+ "USER_EMAIL": {
58
+ "type": "email",
59
+ "mapping": "email"
60
+ },
61
+ "DOB": {
62
+ "type": "text",
63
+ "mapping": "birthdate"
64
+ },
65
+ "PHONE": {
66
+ "type": "phonenumber",
67
+ "mapping": "phone"
68
+ },
69
+ "STREET_ADDRESS": {
70
+ "type": "text",
71
+ "mapping": "street_address"
72
+ },
73
+ "CITY": {
74
+ "type": "text",
75
+ "mapping": "city"
76
+ },
77
+ "STATE": {
78
+ "type": "text",
79
+ "mapping": "state"
80
+ },
81
+ "COUNTRY": {
82
+ "type": "text",
83
+ "mapping": "country"
84
+ },
85
+ "ZIP_CODE": {
86
+ "type": "text",
87
+ "mapping": "zip_code"
88
+ },
89
+ "GENDER": {
90
+ "type": "text",
91
+ "mapping": "gender"
92
+ }
93
+ }
94
+ )
95
+
96
+ # 3. Configure Splink
97
+ # The ID Grapher uses Splink for record linkage. You need to provide a
98
+ # Splink configuration dictionary. This configuration defines how Splink
99
+ # should compare records and which blocking rules to use.
100
+ #
101
+ # For more details on how to configure Splink, please refer to the
102
+ # official Splink documentation: https://moj-analytical-services.github.io/splink/
103
+ splink_config = {
104
+ "linkage_model": "det",
105
+ "blocking_rules": [
106
+ {"columns": ["first_name", "last_name", "birthdate", "state"]},
107
+ {"columns": ["first_name", "last_name", "birthdate", "city"]},
108
+ {"columns": ["first_name", "last_name", "zip_code"]},
109
+ {"columns": ["first_name", "last_name", "street_address"]},
110
+ {"columns": ["first_name", "email"]},
111
+ {"columns": ["email", "phone"]},
112
+ {"columns": ["phone", "gender"]}
113
+ ]
114
+ }
115
+
116
+
117
+ # 4. Instantiate the IDGrapher and process the data
118
+ with IDGrapher() as grapher:
119
+ # Add data from a Snowflake table
120
+ # The 'key' parameter should be the name of the column in your table that
121
+ # represents a unique identifier for each record in that source.
122
+ grapher.add_snowflake(
123
+ con=con,
124
+ object_name="SOURCE_DATABASE.SOURCE_SCHEMA.SOURCE_TABLE",
125
+ key="ACCOUNT_ID",
126
+ field_map=field_map
127
+ )
128
+
129
+ # OPTIONAL: Add more data sources as needed
130
+ # grapher.add_snowflake(...)
131
+
132
+ # OPTIONAL: Add existing ID graph table if available
133
+ """
134
+ grapher.add_snowflake(
135
+ con=con,
136
+ object_name="ID_GRAPH_DATABASE.ID_GRAPH_SCHEMA.ID_GRAPH_TABLE",
137
+ key="PROFILE_ID",
138
+ )
139
+
140
+ """
141
+
142
+ # Process the data to create the ID graph
143
+ graph_result = grapher.process(splink_config)
144
+
145
+ # 5. Write the results back to Snowflake
146
+ graph_result.to_snowflake(
147
+ con=con,
148
+ database="ID_GRAPH_DATABASE",
149
+ schema="ID_GRAPH_SCHEMA",
150
+ table_name="ID_GRAPH_TABLE"
151
+ )
152
+
153
+ # Close the Snowflake connection
154
+ con.close()
155
+ ```
156
+
157
+ ### Explanation
158
+
159
+ 1. **Connect to Snowflake**: We establish a connection to Snowflake using the
160
+ `snowflake-connector-python` library.
161
+
162
+ 2. **Define the Field Map**: The `FieldDefinitionMap` is used to map your
163
+ source table's column names to the standard field names that the
164
+ `id_grapher` expects. This allows the library to understand your data.
165
+
166
+ 3. **Configure Splink**: The `splink_config` dictionary is crucial for the ID
167
+ resolution process. It tells `splink` how to compare records and what rules
168
+ to use for blocking (to reduce the number of comparisons) and matching. The
169
+ example above provides a basic configuration, but you will likely need to
170
+ tune it for your specific data.
171
+
172
+ 4. **Instantiate and Process**: We create an `IDGrapher` instance and use the
173
+ `add_snowflake` method to load data from your Snowflake table. The
174
+ `process` method then runs the identity resolution process.
175
+
176
+ 5. **Write Results to Snowflake**: The `graph_result.to_snowflake()` method
177
+ writes the output of the ID resolution process to a new table in Snowflake.
178
+ The output table will contain the original data enriched with a
179
+ `profile_id` column, which represents the unique entity identifier.
@@ -0,0 +1,52 @@
1
+ Metadata-Version: 2.4
2
+ Name: span_data
3
+ Version: 0.1.3
4
+ Summary: Identity resolution library built on Splink and DuckDB.
5
+ Author: The Data Loft
6
+ License-Expression: BSD-3-Clause
7
+ Project-URL: Community (Slack), https://join.slack.com/t/span-data/shared_invite/zt-3xkirzw8i-w_OcmdVoyAMLSH2V83gGAw
8
+ Project-URL: Documentation, https://span.gitbook.io/span-docs
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Requires-Python: <3.12,>=3.11
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: duckdb<2.0.0,>=1.5.1
15
+ Requires-Dist: email-validator<3.0.0,>=1.3.1
16
+ Requires-Dist: pandas<3.0.0,>=2.3.3
17
+ Requires-Dist: phonenumbers<10.0.0,>=9.0.6
18
+ Requires-Dist: snowflake-connector-python[pandas]==4.4.0
19
+ Requires-Dist: splink<5.0.0,>=4.0.16
20
+ Dynamic: license-file
21
+
22
+ # ID Grapher
23
+
24
+ `span_data` is an identity resolution library built on Splink and DuckDB. It
25
+ links records that refer to the same entity and produces a unified ID graph.
26
+
27
+ ## Core Features
28
+
29
+ - Ingest source data from pandas DataFrames, CSV files, and Snowflake tables or
30
+ views.
31
+ - Clean and normalize source fields using `FieldDefinitionMap`.
32
+ - Resolve entities into profile graphs with Splink-based matching.
33
+ - Export graph results to DataFrames, CSV, Parquet, DuckDB relations, and
34
+ Snowflake.
35
+ - Apply manual override workflows for merge, split, and assign operations.
36
+
37
+ ## Python Support
38
+
39
+ This package currently supports Python `>=3.11,<3.12`.
40
+
41
+ ## Usage
42
+
43
+ See [SPAN Product Documentation](https://span.gitbook.io/span-docs) for usage instructions.
44
+
45
+ ## License
46
+
47
+ This project is licensed under the BSD 3-Clause License. See `LICENSE`.
48
+
49
+ Third-party dependency license information is documented in
50
+ `THIRD_PARTY_NOTICES.md`.
51
+
52
+ Release history is documented in `CHANGELOG.md`.
@@ -0,0 +1,17 @@
1
+ span_data/id_grapher/__init__.cp311-win_amd64.pyd,sha256=8ICY5k670HKLavTYb8_5JPPLRgJQLoZPpuYBthgQx6E,18944
2
+ span_data/id_grapher/clean_data.cp311-win_amd64.pyd,sha256=r5LWWbTyJ-mOJWyl4tuJn5jxvX2WcqlZ3zdCBa1UosY,78848
3
+ span_data/id_grapher/constants.cp311-win_amd64.pyd,sha256=0C-ea7eLMOrw1XJ-qJm_PoXVqSMmaDN9LHdBWcPSOmo,17408
4
+ span_data/id_grapher/field_definition_map.cp311-win_amd64.pyd,sha256=HxfqXrUhWSC5vlLAj2awqDyhqn20xTHM3HXWG8V-Hbc,67072
5
+ span_data/id_grapher/graph_result.cp311-win_amd64.pyd,sha256=YmgCLBvEKMT5ws0EFosmXGkh0o4G7K04L52JXCAB1Ns,70144
6
+ span_data/id_grapher/id_grapher.cp311-win_amd64.pyd,sha256=Rh-H5GE4w3AxUnNjA0zm8TDtlY54dfr5g_tGUNVLEFM,186880
7
+ span_data/id_grapher/overrides.cp311-win_amd64.pyd,sha256=N9hQwtFoOibzOM1BQmyvyeVoojBGRjDGghHb7I2Xpr0,74240
8
+ span_data/id_grapher/profile_assignment_sql.cp311-win_amd64.pyd,sha256=lQZa0-wWkGBMZDGzCcfNW2cho1mB3tc1Gd_lhntcTKE,83456
9
+ span_data-0.1.3.data/data/CHANGELOG.md,sha256=Ars7jCKy7Iv4Hlqd4-X-sTZcYGOX4VoAm4gn3rkbFuo,519
10
+ span_data-0.1.3.data/data/LICENSE,sha256=5N8M-KZZEWyLdn6BhblwvkK4QKFUiAKJIpcjcAdOWRs,1563
11
+ span_data-0.1.3.data/data/THIRD_PARTY_NOTICES.md,sha256=cUEJdSoYg41X7eNuotKsNnOq3A-wYnjyCEhZDbFcin0,1556
12
+ span_data-0.1.3.data/data/USAGE.md,sha256=S_7MJVv_dbwkQdQQDHkNaaa7wP4IZHHeHp4JcYVw5Go,5843
13
+ span_data-0.1.3.dist-info/licenses/LICENSE,sha256=5N8M-KZZEWyLdn6BhblwvkK4QKFUiAKJIpcjcAdOWRs,1563
14
+ span_data-0.1.3.dist-info/METADATA,sha256=oUCMxrgQrNYCgoFHxFQF8MG0XgjAni238c7-nrqsnwU,1841
15
+ span_data-0.1.3.dist-info/WHEEL,sha256=XHXMKJU3yoVh1ZanBXTJ5bDGb67oEYtF1S6bd8a4izI,101
16
+ span_data-0.1.3.dist-info/top_level.txt,sha256=ItfL4WXhvvBw4enCi2zm5Rabby0YIW5Ew9b25-NOmL8,10
17
+ span_data-0.1.3.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: false
4
+ Tag: cp311-cp311-win_amd64
5
+
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Data Loft Technologies Inc
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1 @@
1
+ span_data