From 4d06175d305e18739aae1b89eaafdff08e4db9cd Mon Sep 17 00:00:00 2001 From: Mattijn van Hoek Date: Sat, 16 Dec 2023 17:49:23 +0100 Subject: [PATCH 1/2] doc: add histogram with gradient color (#3282) * histogram with gradient color * change to pinkyellowgreen --- .../histogram_gradient_color.py | 23 +++++++++++++++++++ .../histogram_gradient_color.py | 17 ++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 tests/examples_arguments_syntax/histogram_gradient_color.py create mode 100644 tests/examples_methods_syntax/histogram_gradient_color.py diff --git a/tests/examples_arguments_syntax/histogram_gradient_color.py b/tests/examples_arguments_syntax/histogram_gradient_color.py new file mode 100644 index 000000000..6bd3e7b6e --- /dev/null +++ b/tests/examples_arguments_syntax/histogram_gradient_color.py @@ -0,0 +1,23 @@ +""" +Histogram with Gradient Color +----------------------------- +This example shows how to make a histogram with gradient color. +The low-high IMDB rating is represented with the color scheme `pinkyellowgreen`. +""" +# category: distributions +import altair as alt +from vega_datasets import data + +source = data.movies.url + +alt.Chart(source).mark_bar().encode( + alt.X("IMDB_Rating:Q", + bin=alt.Bin(maxbins=20), + scale=alt.Scale(domain=[1, 10]) + ), + alt.Y('count()'), + alt.Color("IMDB_Rating:Q", + bin=alt.Bin(maxbins=20), + scale=alt.Scale(scheme='pinkyellowgreen') + ) +) \ No newline at end of file diff --git a/tests/examples_methods_syntax/histogram_gradient_color.py b/tests/examples_methods_syntax/histogram_gradient_color.py new file mode 100644 index 000000000..645453475 --- /dev/null +++ b/tests/examples_methods_syntax/histogram_gradient_color.py @@ -0,0 +1,17 @@ +""" +Histogram with Gradient Color +----------------------------- +This example shows how to make a histogram with gradient color. +The low-high IMDB rating is represented with the color scheme `pinkyellowgreen`. +""" +# category: distributions +import altair as alt +from vega_datasets import data + +source = data.movies.url + +alt.Chart(source).mark_bar().encode( + alt.X("IMDB_Rating:Q").bin(maxbins=20).scale(domain=[1, 10]), + alt.Y('count()'), + alt.Color("IMDB_Rating:Q").bin(maxbins=20).scale(scheme='pinkyellowgreen') +) \ No newline at end of file From 5540ed98a9589c745152e4791f4674e1737c1408 Mon Sep 17 00:00:00 2001 From: Chad Cravens Date: Fri, 22 Dec 2023 09:16:17 -0500 Subject: [PATCH 2/2] Update for FIPS Compliance (#3291) * Update md5 to sha256 for FIPS compliance * Update md5 to sha256 for FIPS compliance * Update md5 to sha256 for FIPS compliance * Update api.py * Adapt url encoding in test_to_url. It changed because the specification changed due to the different hash algorithm which is used for the dataset name * Truncate hash value to be same size as md5 * Truncate sha256 hash to match md5 hash length * Truncate sha256 to match md5 hash size * Truncate sha265 hash to be same size as md5 * update test * add change note --------- Co-authored-by: Stefan Binder Co-authored-by: mattijn --- altair/utils/data.py | 2 +- altair/vegalite/v5/api.py | 2 +- doc/releases/changes.rst | 4 ++++ sphinxext/altairgallery.py | 2 +- sphinxext/utils.py | 4 ++-- tests/vegalite/v5/test_api.py | 9 +-------- 6 files changed, 10 insertions(+), 13 deletions(-) diff --git a/altair/utils/data.py b/altair/utils/data.py index 2a3a3474b..7fba7adaa 100644 --- a/altair/utils/data.py +++ b/altair/utils/data.py @@ -257,7 +257,7 @@ def check_data_type(data: DataType) -> None: # Private utilities # ============================================================================== def _compute_data_hash(data_str: str) -> str: - return hashlib.md5(data_str.encode()).hexdigest() + return hashlib.sha256(data_str.encode()).hexdigest()[:32] def _data_to_json_string(data: DataType) -> str: diff --git a/altair/vegalite/v5/api.py b/altair/vegalite/v5/api.py index c87c2e85d..56b15db79 100644 --- a/altair/vegalite/v5/api.py +++ b/altair/vegalite/v5/api.py @@ -57,7 +57,7 @@ def _dataset_name(values: Union[dict, list, core.InlineDataset]) -> str: if values == [{}]: return "empty" values_json = json.dumps(values, sort_keys=True) - hsh = hashlib.md5(values_json.encode()).hexdigest() + hsh = hashlib.sha256(values_json.encode()).hexdigest()[:32] return "data-" + hsh diff --git a/doc/releases/changes.rst b/doc/releases/changes.rst index 206e7f8c3..998fbe3e9 100644 --- a/doc/releases/changes.rst +++ b/doc/releases/changes.rst @@ -8,10 +8,14 @@ Version 5.3.0 (unreleased month day, year) Enhancements ~~~~~~~~~~~~ +- Support restrictive FIPS-compliant environment (#3291) + Bug Fixes ~~~~~~~~~ + Backward-Incompatible Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +- Changed hash function from ``md5`` to a truncated ``sha256`` non-cryptograhic hash (#3291) Version 5.2.0 (released Nov 28, 2023) ------------------------------------------- diff --git a/sphinxext/altairgallery.py b/sphinxext/altairgallery.py index f76805c90..a6310ddd9 100644 --- a/sphinxext/altairgallery.py +++ b/sphinxext/altairgallery.py @@ -166,7 +166,7 @@ def save_example_pngs(examples, image_dir, make_thumbnails=True): filename = example["name"] + (".svg" if example["use_svg"] else ".png") image_file = os.path.join(image_dir, filename) - example_hash = hashlib.md5(example["code"].encode()).hexdigest() + example_hash = hashlib.sha256(example["code"].encode()).hexdigest()[:32] hashes_match = hashes.get(filename, "") == example_hash if hashes_match and os.path.exists(image_file): diff --git a/sphinxext/utils.py b/sphinxext/utils.py index c3bd2052d..50d17608c 100644 --- a/sphinxext/utils.py +++ b/sphinxext/utils.py @@ -193,8 +193,8 @@ def dict_hash(dct): serialized = json.dumps(dct, sort_keys=True) try: - m = hashlib.md5(serialized) + m = hashlib.sha256(serialized)[:32] except TypeError: - m = hashlib.md5(serialized.encode()) + m = hashlib.sha256(serialized.encode())[:32] return m.hexdigest() diff --git a/tests/vegalite/v5/test_api.py b/tests/vegalite/v5/test_api.py index 638eaac46..af963be7d 100644 --- a/tests/vegalite/v5/test_api.py +++ b/tests/vegalite/v5/test_api.py @@ -382,14 +382,7 @@ def test_save_html(basic_chart, inline): def test_to_url(basic_chart): share_url = basic_chart.to_url() - expected_vegalite_encoding = ( - "N4Igxg9gdgZglgcxALlANzgUwO4tJKAFzigFcJSBnAdTgBNCALFAZgAY2AacaYsiygAlMiRoVYcAvpO5" - "0AhoTl4QUOQFtMKEPMUBaMACY5LTAA4AnACM55ugFY6ARgBspgOz2zh03Wfs5bCwsIDIganIATgDWyoQ" - "AngAOmsgg1hEh3JhQkHQkSKggAB7K8JgANnRaStzxSVpQEGokcmUZIHElWBValiA1ickgAI6kckRwisR" - "omtLcACSUYIyY4VpihAmUyAD029MIcgB0CBOMpJaHcBDbi8vhe5gHumUTmHt2hy6HLIcAVpTQPraBRyS" - "iYQiUZQ6OT6IwmCzWWwOFzuTymby+fyBYLIADaoCUKQAgkDesgDKYZAStAAhUkoOx2KkgQkgADC9OQABY" - "WMzWQARTnmRx8rQAUU5phFnGpKQAYpy7LyZSytABxTmOcyilKCSVuHUgACSioMkgAutIgA" - ) + expected_vegalite_encoding = "N4Igxg9gdgZglgcxALlANzgUwO4tJKAFzigFcJSBnAdTgBNCALFAZgAY2AacaYsiygAlMiRoVYcAvpO50AhoTl4QUOQFtMKEPMUBaAOwA2ABwAWFi1NyTcgEb7TtuabAswc-XTZhMczLdNDAEYQGRA1OQAnAGtlQgBPAAdNZBAnSNDuTChIOhIkVBAAD2V4TAAbOi0lbgTkrSgINRI5csyQeNKsSq1bEFqklJAAR1I5IjhFYjRNaW4AEkowRkwIrTFCRMpkAHodmYQ5ADoEScZSWyO4CB2llYj9zEPdcsnMfYBWI6DDI5YjgBWlGg-W0CjklEwhEoyh0cgMJnMlmsxjsDicLjcHi8Pj8AWCKAA2qAlKkAIKgvrIABMxhkJK0ACFKSgPh96SBSSAAMIs5DmDlcgAifIAnEFBVoAKJ84wSzgM1IAMT5HxYktSAHE+UFRRqQIJZfp9QBJVXUyQAXWkQA" assert ( share_url