valentine


Namevalentine JSON
Version 0.2.0 PyPI version JSON
download
home_pagehttps://delftdata.github.io/valentine/
SummaryValentine Matcher
upload_time2024-02-14 12:43:07
maintainerDelft Data
docs_urlNone
authorDelft Data
requires_python>=3.8,<3.13
license
keywords matching valentine schema matching dataset discovery coma cupid similarity flooding
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Valentine: (Schema-) Matching DataFrames Made Easy

[![build](https://github.com/delftdata/valentine/actions/workflows/build.yml/badge.svg)](https://github.com/delftdata/valentine/actions/workflows/build.yml)
[![codecov](https://codecov.io/gh/delftdata/valentine/branch/master/graph/badge.svg?token=4QR0X315CL)](https://codecov.io/gh/delftdata/valentine)
[![PyPI version](https://badge.fury.io/py/valentine.svg)](https://badge.fury.io/py/valentine)
![PyPI - Downloads](https://img.shields.io/pypi/dm/valentine)
[![Python 3.8+](https://img.shields.io/badge/python-3.8|3.9|3.10|3.11|3.12-blue.svg)](https://www.python.org/downloads/release/python-380/)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/85cfebfc9c6a43359c5b2e56a5fdf3a3)](https://app.codacy.com/gh/delftdata/valentine/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)

A python package for capturing potential relationships among columns of different tabular datasets, which are given in the form of pandas DataFrames. Valentine is based on [Valentine: Evaluating Matching Techniques for Dataset Discovery](https://ieeexplore.ieee.org/abstract/document/9458921)

You can find more information about the research supporting Valentine [here](https://delftdata.github.io/valentine/).

## Experimental suite version

The original experimental suite version of Valentine, as first published for the needs of the research paper, can be still found [here](https://github.com/delftdata/valentine/tree/v1.1).

## Installation instructions
### Requirements

*   *Python* >=3.8,<3.13
*   *Java*: For the Coma matcher it is required to have java (jre) installed

To install Valentine simply run:

```shell
pip install valentine
```


## Usage
Valentine can be used to find matches among columns of a given pair of pandas DataFrames. 

### Matching methods
In order to do so, the user can choose one of the following 5 matching methods:

1.   `Coma(int: max_n, bool: use_instances, str: java_xmx)` is a python wrapper around [COMA 3.0 Comunity edition](https://sourceforge.net/projects/coma-ce/)
     *    **Parameters**: 
           *    **max_n**(*int*) - Accept similarity threshold, (default: 0).
           *    **use_instances**(*bool*) - Wheather Coma will make use of the data instances or just the schema information, (default: False).
           *    **java_xmx**(*str*) - The amount of RAM that Coma is allowed to use, (default: "1024m") .

2.   `Cupid(float: w_struct, float: leaf_w_struct, float: th_accept)` is the python implementation of the paper [Generic Schema Matching with Cupid](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.79.4079&rep=rep1&type=pdf)
     *    **Parameters**:
          *    **w_struct**(*float*) - Structural similarity threshold, default is 0.2.
          *    **leaf_w_struct**(*float*) - Structural similarity threshold, leaf level, default is 0.2.
          *    **th_accept**(*float*) - Accept similarity threshold, default is 0.7.

3.   `DistributionBased(float: threshold1, float: threshold2)` is the python implementation of the paper [Automatic Discovery of Attributes in Relational Databases](https://dl-acm-org.tudelft.idm.oclc.org/doi/pdf/10.1145/1989323.1989336)
     *    **Parameters**: 
          *    **threshold1**(*float*) - The threshold for phase 1 of the method, default is 0.15.
          *    **threshold2**(*float*) - The threshold for phase 2 of the method, default is 0.15.

4.   `JaccardDistanceMatcher(float: threshold_dist)` is a baseline method that uses Jaccard Similarity between columns to assess their correspondence score, optionally enhanced by a string similarity measure of choice.
     *    **Parameters**: 
          *    **threshold_dist**(*float*) - Acceptance threshold for assessing two strings as equal, default is 0.8.
     
          *    **distance_fun**(*StringDistanceFunction*) - String similarity function used to assess whether two strings are equal. The enumeration class type `StringDistanceFunction` can be imported from `valentine.algorithms.jaccard_distance`. Functions currently supported are:  
   		       * `StringDistanceFunction.Levenshtein`: [Levenshtein distance](https://en.wikipedia.org/wiki/Levenshtein_distance)
               * `StringDistanceFunction.DamerauLevenshtein`: [Damerau-Levenshtein distance](https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance)
               * `StringDistanceFunction.Hamming`: [Hamming distance](https://en.wikipedia.org/wiki/Hamming_distance)
               * `StringDistanceFunction.Jaro`: [Jaro distance](https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance)
               * `StringDistanceFunction.JaroWinkler`: [Jaro-Winkler distance](https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance)
              * `StringDistanceFunction.Exact`: String equality `==`

5.   `SimilarityFlooding(str: coeff_policy, str: formula)` is the python implementation of the paper [Similarity Flooding: A Versatile Graph Matching Algorithmand its Application to Schema Matching](http://p8090-ilpubs.stanford.edu.tudelft.idm.oclc.org/730/1/2002-1.pdf)
     * **Parameters**: 
        *    **coeff_policy**(*str*) - Policy for deciding the weight coefficients of the propagation graph. Choice of "inverse\_product" or "inverse\_average" (default).
        *    **formula**(*str*) - Formula on which iterative fixpoint computation is based. Choice of "basic", "formula\_a", "formula\_b" and "formula\_c" (default).

### Matching DataFrame Pair

After selecting one of the 5 matching methods, the user can initiate the pairwise matching process in the following way:

```python
matches = valentine_match(df1, df2, matcher, df1_name, df2_name)
```

where df1 and df2 are the two pandas DataFrames for which we want to find matches and matcher is one of Coma, Cupid, DistributionBased, JaccardLevenMatcher or SimilarityFlooding. The user can also input a name for each DataFrame (defaults are "table\_1" and "table\_2"). Function ```valentine_match``` returns a MatcherResults object, which is a dictionary with additional convenience methods, such as `one_to_one`, `take_top_percent`, `get_metrics` and more. It stores as keys column pairs from the two DataFrames and as values the corresponding similarity scores.

### Matching DataFrame Batch

After selecting one of the 5 matching methods, the user can initiate the batch matching process in the following way:

```python
matches = valentine_match_batch(df_iter_1, df_iter_2, matcher, df_iter_1_names, df_iter_2_names)
```

where df_iter_1 and df_iter_2 are the two iterable structures containing pandas DataFrames for which we want to find matches and matcher is one of Coma, Cupid, DistributionBased, JaccardLevenMatcher or SimilarityFlooding. The user can also input an iterable with names for each DataFrame. Function ```valentine_match_batch``` returns a MatcherResults object, which is a dictionary with additional convenience methods, such as `one_to_one`, `take_top_percent`, `get_metrics` and more. It stores as keys column pairs from the two DataFrames and as values the corresponding similarity scores.


### MatcherResults instance
The `MatcherResults` instance has some convenience methods that the user can use to either obtain a subset of the data or to transform the data. This instance is a dictionary and is sorted upon instantiation, from high similarity to low similarity.
```python
top_n_matches = matches.take_top_n(5)

top_n_percent_matches = matches.take_top_percent(25)

one_to_one_matches = matches.one_to_one()
```


### Measuring effectiveness
The MatcherResults instance that is returned by `valentine_match` or `valentine_match_batch` also has a `get_metrics` method that the user can use 

```python 
metrics = matches.get_metrics(ground_truth)
``` 

in order to get all effectiveness metrics, such as Precision, Recall, F1-score and others as described in the original Valentine paper. In order to do so, the user needs to also input the ground truth of matches based on which the metrics will be calculated. The ground truth can be given as a list of tuples representing column matches that should hold (see example below).

By default, all the core metrics will be used for this with default parameters, but the user can also customize which metrics to run with what parameters, and implement own custom metrics by extending from the `Metric` base class. Some sets of metrics are available as well.

```python
from valentine.metrics import F1Score, PrecisionTopNPercent, METRICS_PRECISION_INCREASING_N
metrics_custom = matches.get_metrics(ground_truth, metrics={F1Score(one_to_one=False), PrecisionTopNPercent(n=70)})
metrics_prefefined_set = matches.get_metrics(ground_truth, metrics=METRICS_PRECISION_INCREASING_N)

```


### Example
The following block of code shows: 1) how to run a matcher from Valentine on two DataFrames storing information about authors and their publications, and then 2) how to assess its effectiveness based on a given ground truth (a more extensive example is shown in [`valentine_example.py`](https://github.com/delftdata/valentine/blob/master/examples/valentine_example.py)):

```python
import os
import pandas as pd
from valentine import valentine_match
from valentine.algorithms import Coma

# Load data using pandas
d1_path = os.path.join('data', 'authors1.csv')
d2_path = os.path.join('data', 'authors2.csv')
df1 = pd.read_csv(d1_path)
df2 = pd.read_csv(d2_path)

# Instantiate matcher and run
matcher = Coma(use_instances=True)
matches = valentine_match(df1, df2, matcher)

print(matches)

# If ground truth available valentine could calculate the metrics
ground_truth = [('Cited by', 'Cited by'),
                ('Authors', 'Authors'),
                ('EID', 'EID')]

metrics = matches.get_metrics(ground_truth)
    
print(metrics)
```

The output of the above code block is:

```
{
     (('table_1', 'Cited by'), ('table_2', 'Cited by')): 0.86994505, 
     (('table_1', 'Authors'), ('table_2', 'Authors')): 0.8679843, 
     (('table_1', 'EID'), ('table_2', 'EID')): 0.8571245
}
{
     'Recall': 1.0, 
     'F1Score': 1.0, 
     'RecallAtSizeofGroundTruth': 1.0, 
     'Precision': 1.0, 
     'PrecisionTop10Percent': 1.0
}
```

## Cite Valentine
```
Original Valentine paper:
@inproceedings{koutras2021valentine,
  title={Valentine: Evaluating Matching Techniques for Dataset Discovery},
  author={Koutras, Christos and Siachamis, George and Ionescu, Andra and Psarakis, Kyriakos and Brons, Jerry and Fragkoulis, Marios and Lofi, Christoph and Bonifati, Angela and Katsifodimos, Asterios},
  booktitle={2021 IEEE 37th International Conference on Data Engineering (ICDE)},
  pages={468--479},
  year={2021},
  organization={IEEE}
}
Demo Paper:
@article{koutras2021demo,
  title={Valentine in Action: Matching Tabular Data at Scale},
  author={Koutras, Christos and Psarakis, Kyriakos and Siachamis, George and Ionescu, Andra and Fragkoulis, Marios and Bonifati, Angela and Katsifodimos, Asterios},
  journal={VLDB},
  volume={14},
  number={12},
  pages={2871--2874},
  year={2021},
  publisher={VLDB Endowment}
}
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://delftdata.github.io/valentine/",
    "name": "valentine",
    "maintainer": "Delft Data",
    "docs_url": null,
    "requires_python": ">=3.8,<3.13",
    "maintainer_email": "delftdatasystems@gmail.com",
    "keywords": "matching,valentine,schema matching,dataset discovery,coma,cupid,similarity flooding",
    "author": "Delft Data",
    "author_email": "delftdatasystems@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/85/b3/7f683791645e4ddb5a5198af49d746db68d5f750c20fd887edafc7f7bb9c/valentine-0.2.0.tar.gz",
    "platform": null,
    "description": "# Valentine: (Schema-) Matching DataFrames Made Easy\n\n[![build](https://github.com/delftdata/valentine/actions/workflows/build.yml/badge.svg)](https://github.com/delftdata/valentine/actions/workflows/build.yml)\n[![codecov](https://codecov.io/gh/delftdata/valentine/branch/master/graph/badge.svg?token=4QR0X315CL)](https://codecov.io/gh/delftdata/valentine)\n[![PyPI version](https://badge.fury.io/py/valentine.svg)](https://badge.fury.io/py/valentine)\n![PyPI - Downloads](https://img.shields.io/pypi/dm/valentine)\n[![Python 3.8+](https://img.shields.io/badge/python-3.8|3.9|3.10|3.11|3.12-blue.svg)](https://www.python.org/downloads/release/python-380/)\n[![Codacy Badge](https://app.codacy.com/project/badge/Grade/85cfebfc9c6a43359c5b2e56a5fdf3a3)](https://app.codacy.com/gh/delftdata/valentine/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)\n\nA python package for capturing potential relationships among columns of different tabular datasets, which are given in the form of pandas DataFrames. Valentine is based on [Valentine: Evaluating Matching Techniques for Dataset Discovery](https://ieeexplore.ieee.org/abstract/document/9458921)\n\nYou can find more information about the research supporting Valentine [here](https://delftdata.github.io/valentine/).\n\n## Experimental suite version\n\nThe original experimental suite version of Valentine, as first published for the needs of the research paper, can be still found [here](https://github.com/delftdata/valentine/tree/v1.1).\n\n## Installation instructions\n### Requirements\n\n*   *Python* >=3.8,<3.13\n*   *Java*: For the Coma matcher it is required to have java (jre) installed\n\nTo install Valentine simply run:\n\n```shell\npip install valentine\n```\n\n\n## Usage\nValentine can be used to find matches among columns of a given pair of pandas DataFrames. \n\n### Matching methods\nIn order to do so, the user can choose one of the following 5 matching methods:\n\n1.   `Coma(int: max_n, bool: use_instances, str: java_xmx)` is a python wrapper around [COMA 3.0 Comunity edition](https://sourceforge.net/projects/coma-ce/)\n     *    **Parameters**: \n           *    **max_n**(*int*) - Accept similarity threshold, (default: 0).\n           *    **use_instances**(*bool*) - Wheather Coma will make use of the data instances or just the schema information, (default: False).\n           *    **java_xmx**(*str*) - The amount of RAM that Coma is allowed to use, (default: \"1024m\") .\n\n2.   `Cupid(float: w_struct, float: leaf_w_struct, float: th_accept)` is the python implementation of the paper [Generic Schema Matching with Cupid](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.79.4079&rep=rep1&type=pdf)\n     *    **Parameters**:\n          *    **w_struct**(*float*) - Structural similarity threshold, default is 0.2.\n          *    **leaf_w_struct**(*float*) - Structural similarity threshold, leaf level, default is 0.2.\n          *    **th_accept**(*float*) - Accept similarity threshold, default is 0.7.\n\n3.   `DistributionBased(float: threshold1, float: threshold2)` is the python implementation of the paper [Automatic Discovery of Attributes in Relational Databases](https://dl-acm-org.tudelft.idm.oclc.org/doi/pdf/10.1145/1989323.1989336)\n     *    **Parameters**: \n          *    **threshold1**(*float*) - The threshold for phase 1 of the method, default is 0.15.\n          *    **threshold2**(*float*) - The threshold for phase 2 of the method, default is 0.15.\n\n4.   `JaccardDistanceMatcher(float: threshold_dist)` is a baseline method that uses Jaccard Similarity between columns to assess their correspondence score, optionally enhanced by a string similarity measure of choice.\n     *    **Parameters**: \n          *    **threshold_dist**(*float*) - Acceptance threshold for assessing two strings as equal, default is 0.8.\n     \n          *    **distance_fun**(*StringDistanceFunction*) - String similarity function used to assess whether two strings are equal. The enumeration class type `StringDistanceFunction` can be imported from `valentine.algorithms.jaccard_distance`. Functions currently supported are:  \n   \t\t       * `StringDistanceFunction.Levenshtein`: [Levenshtein distance](https://en.wikipedia.org/wiki/Levenshtein_distance)\n               * `StringDistanceFunction.DamerauLevenshtein`: [Damerau-Levenshtein distance](https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance)\n               * `StringDistanceFunction.Hamming`: [Hamming distance](https://en.wikipedia.org/wiki/Hamming_distance)\n               * `StringDistanceFunction.Jaro`: [Jaro distance](https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance)\n               * `StringDistanceFunction.JaroWinkler`: [Jaro-Winkler distance](https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance)\n              * `StringDistanceFunction.Exact`: String equality `==`\n\n5.   `SimilarityFlooding(str: coeff_policy, str: formula)` is the python implementation of the paper [Similarity Flooding: A Versatile Graph Matching Algorithmand its Application to Schema Matching](http://p8090-ilpubs.stanford.edu.tudelft.idm.oclc.org/730/1/2002-1.pdf)\n     * **Parameters**: \n        *    **coeff_policy**(*str*) - Policy for deciding the weight coefficients of the propagation graph. Choice of \"inverse\\_product\" or \"inverse\\_average\" (default).\n        *    **formula**(*str*) - Formula on which iterative fixpoint computation is based. Choice of \"basic\", \"formula\\_a\", \"formula\\_b\" and \"formula\\_c\" (default).\n\n### Matching DataFrame Pair\n\nAfter selecting one of the 5 matching methods, the user can initiate the pairwise matching process in the following way:\n\n```python\nmatches = valentine_match(df1, df2, matcher, df1_name, df2_name)\n```\n\nwhere df1 and df2 are the two pandas DataFrames for which we want to find matches and matcher is one of Coma, Cupid, DistributionBased, JaccardLevenMatcher or SimilarityFlooding. The user can also input a name for each DataFrame (defaults are \"table\\_1\" and \"table\\_2\"). Function ```valentine_match``` returns a MatcherResults object, which is a dictionary with additional convenience methods, such as `one_to_one`, `take_top_percent`, `get_metrics` and more. It stores as keys column pairs from the two DataFrames and as values the corresponding similarity scores.\n\n### Matching DataFrame Batch\n\nAfter selecting one of the 5 matching methods, the user can initiate the batch matching process in the following way:\n\n```python\nmatches = valentine_match_batch(df_iter_1, df_iter_2, matcher, df_iter_1_names, df_iter_2_names)\n```\n\nwhere df_iter_1 and df_iter_2 are the two iterable structures containing pandas DataFrames for which we want to find matches and matcher is one of Coma, Cupid, DistributionBased, JaccardLevenMatcher or SimilarityFlooding. The user can also input an iterable with names for each DataFrame. Function ```valentine_match_batch``` returns a MatcherResults object, which is a dictionary with additional convenience methods, such as `one_to_one`, `take_top_percent`, `get_metrics` and more. It stores as keys column pairs from the two DataFrames and as values the corresponding similarity scores.\n\n\n### MatcherResults instance\nThe `MatcherResults` instance has some convenience methods that the user can use to either obtain a subset of the data or to transform the data. This instance is a dictionary and is sorted upon instantiation, from high similarity to low similarity.\n```python\ntop_n_matches = matches.take_top_n(5)\n\ntop_n_percent_matches = matches.take_top_percent(25)\n\none_to_one_matches = matches.one_to_one()\n```\n\n\n### Measuring effectiveness\nThe MatcherResults instance that is returned by `valentine_match` or `valentine_match_batch` also has a `get_metrics` method that the user can use \n\n```python \nmetrics = matches.get_metrics(ground_truth)\n``` \n\nin order to get all effectiveness metrics, such as Precision, Recall, F1-score and others as described in the original Valentine paper. In order to do so, the user needs to also input the ground truth of matches based on which the metrics will be calculated. The ground truth can be given as a list of tuples representing column matches that should hold (see example below).\n\nBy default, all the core metrics will be used for this with default parameters, but the user can also customize which metrics to run with what parameters, and implement own custom metrics by extending from the `Metric` base class. Some sets of metrics are available as well.\n\n```python\nfrom valentine.metrics import F1Score, PrecisionTopNPercent, METRICS_PRECISION_INCREASING_N\nmetrics_custom = matches.get_metrics(ground_truth, metrics={F1Score(one_to_one=False), PrecisionTopNPercent(n=70)})\nmetrics_prefefined_set = matches.get_metrics(ground_truth, metrics=METRICS_PRECISION_INCREASING_N)\n\n```\n\n\n### Example\nThe following block of code shows: 1) how to run a matcher from Valentine on two DataFrames storing information about authors and their publications, and then 2) how to assess its effectiveness based on a given ground truth (a more extensive example is shown in [`valentine_example.py`](https://github.com/delftdata/valentine/blob/master/examples/valentine_example.py)):\n\n```python\nimport os\nimport pandas as pd\nfrom valentine import valentine_match\nfrom valentine.algorithms import Coma\n\n# Load data using pandas\nd1_path = os.path.join('data', 'authors1.csv')\nd2_path = os.path.join('data', 'authors2.csv')\ndf1 = pd.read_csv(d1_path)\ndf2 = pd.read_csv(d2_path)\n\n# Instantiate matcher and run\nmatcher = Coma(use_instances=True)\nmatches = valentine_match(df1, df2, matcher)\n\nprint(matches)\n\n# If ground truth available valentine could calculate the metrics\nground_truth = [('Cited by', 'Cited by'),\n                ('Authors', 'Authors'),\n                ('EID', 'EID')]\n\nmetrics = matches.get_metrics(ground_truth)\n    \nprint(metrics)\n```\n\nThe output of the above code block is:\n\n```\n{\n     (('table_1', 'Cited by'), ('table_2', 'Cited by')): 0.86994505, \n     (('table_1', 'Authors'), ('table_2', 'Authors')): 0.8679843, \n     (('table_1', 'EID'), ('table_2', 'EID')): 0.8571245\n}\n{\n     'Recall': 1.0, \n     'F1Score': 1.0, \n     'RecallAtSizeofGroundTruth': 1.0, \n     'Precision': 1.0, \n     'PrecisionTop10Percent': 1.0\n}\n```\n\n## Cite Valentine\n```\nOriginal Valentine paper:\n@inproceedings{koutras2021valentine,\n  title={Valentine: Evaluating Matching Techniques for Dataset Discovery},\n  author={Koutras, Christos and Siachamis, George and Ionescu, Andra and Psarakis, Kyriakos and Brons, Jerry and Fragkoulis, Marios and Lofi, Christoph and Bonifati, Angela and Katsifodimos, Asterios},\n  booktitle={2021 IEEE 37th International Conference on Data Engineering (ICDE)},\n  pages={468--479},\n  year={2021},\n  organization={IEEE}\n}\nDemo Paper:\n@article{koutras2021demo,\n  title={Valentine in Action: Matching Tabular Data at Scale},\n  author={Koutras, Christos and Psarakis, Kyriakos and Siachamis, George and Ionescu, Andra and Fragkoulis, Marios and Bonifati, Angela and Katsifodimos, Asterios},\n  journal={VLDB},\n  volume={14},\n  number={12},\n  pages={2871--2874},\n  year={2021},\n  publisher={VLDB Endowment}\n}\n```\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "Valentine Matcher",
    "version": "0.2.0",
    "project_urls": {
        "Download": "https://github.com/delftdata/valentine/archive/refs/tags/v0.2.0.tar.gz",
        "Homepage": "https://delftdata.github.io/valentine/"
    },
    "split_keywords": [
        "matching",
        "valentine",
        "schema matching",
        "dataset discovery",
        "coma",
        "cupid",
        "similarity flooding"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "85b37f683791645e4ddb5a5198af49d746db68d5f750c20fd887edafc7f7bb9c",
                "md5": "1e8e449146bdf5679ed60a4989e2c70c",
                "sha256": "321ec4fd1d416d14196005b64e8b359b58aad0b706576aca16f8a92f56cd8611"
            },
            "downloads": -1,
            "filename": "valentine-0.2.0.tar.gz",
            "has_sig": false,
            "md5_digest": "1e8e449146bdf5679ed60a4989e2c70c",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8,<3.13",
            "size": 38208059,
            "upload_time": "2024-02-14T12:43:07",
            "upload_time_iso_8601": "2024-02-14T12:43:07.137096Z",
            "url": "https://files.pythonhosted.org/packages/85/b3/7f683791645e4ddb5a5198af49d746db68d5f750c20fd887edafc7f7bb9c/valentine-0.2.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-02-14 12:43:07",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "delftdata",
    "github_project": "valentine",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "lcname": "valentine"
}
        
Elapsed time: 0.21799s