Repository: prometheus/client_python
Pull request #796 (2022-04-08 02:18:18)

Rename choose_formatter back to choose_encoder
Other libraries depend on this function and we did not mean to create a breaking change. Add a test to document that this is part of the API.

Fixes https://github.com/prometheus/client_python/issues/795

Starkteetje: Note that this renaming is again a breaking change. If you want to avoid it, you could define one of the names as an alias to the other to get backwards-compatibility with the prior versions and 0.14 (though that's obviously ugly)
Starkteetje: Note that this renaming is again a breaking change. If you want to avoid it, you could define one of the names as an alias to the other to get backwards-compatibility with the prior versions and 0.14 (though that's obviously ugly)
csmarchbanks: Yeah, that is the case and I would prefer not to maintain the second function name forever. I am hoping that most people who are pinning versions are either pinning both or will upgrade to the patch version fairly quickly. Since the release has only been out for three days a bugfix to revert to the previous behavior seems reasonable to me?
csmarchbanks: To avoid the second breaking change in 0.14.x I added choose_formatter back in with a deprecation notice. It will be removed as part of 0.15, but that at least gives everyone some time to use either.

Patch:
diff --git a/prometheus_client/exposition.py b/prometheus_client/exposition.py
index 86a9be4..345b247 100644
--- a/prometheus_client/exposition.py
+++ b/prometheus_client/exposition.py
@@ -13,6 +13,7 @@ from urllib.parse import parse_qs, quote_plus, urlparse
 from urllib.request import (
     build_opener, HTTPHandler, HTTPRedirectHandler, Request,
 )
+import warnings
 from wsgiref.simple_server import make_server, WSGIRequestHandler, WSGIServer
 
 from .openmetrics import exposition as openmetrics
@@ -97,10 +98,10 @@ class _PrometheusRedirectHandler(HTTPRedirectHandler):
 def _bake_output(registry, accept_header, accept_encoding_header, params, disable_compression):
     """Bake output for metrics output."""
     # Choose the correct plain text format of the output.
-    formatter, content_type = choose_formatter(accept_header)
+    encoder, content_type = choose_encoder(accept_header)
     if 'name[]' in params:
         registry = registry.restricted_registry(params['name[]'])
-    output = formatter(registry)
+    output = encoder(registry)
     headers = [('Content-Type', content_type)]
     # If gzip encoding required, gzip the output.
     if not disable_compression and gzip_accepted(accept_encoding_header):
@@ -237,7 +238,7 @@ def generate_latest(registry: CollectorRegistry = REGISTRY) -> bytes:
     return ''.join(output).encode('utf-8')
 
 
-def choose_formatter(accept_header: str) -> Tuple[Callable[[CollectorRegistry], bytes], str]:
+def choose_encoder(accept_header: str) -> Tuple[Callable[[CollectorRegistry], bytes], str]:
     accept_header = accept_header or ''
     for accepted in accept_header.split(','):
         if accepted.split(';')[0].strip() == 'application/openmetrics-text':
@@ -246,6 +247,15 @@ def choose_formatter(accept_header: str) -> Tuple[Callable[[CollectorRegistry],
     return generate_latest, CONTENT_TYPE_LATEST
 
 
+def choose_formatter(accept_header: str) -> Tuple[Callable[[CollectorRegistry], bytes], str]:
+    warnings.warn(
+        "choose_formatter is deprecated and will be removed in 0.15.0, please use choose_encoder instead",
+        DeprecationWarning,
+        stacklevel=2
+    )
+    return choose_encoder(accept_header)
+
+
 def gzip_accepted(accept_encoding_header: str) -> bool:
     accept_encoding_header = accept_encoding_header or ''
     for accepted in accept_encoding_header.split(','):


Test patch:
diff --git a/tests/test_exposition.py b/tests/test_exposition.py
index fd13055..8da12a1 100644
--- a/tests/test_exposition.py
+++ b/tests/test_exposition.py
@@ -2,6 +2,7 @@ from http.server import BaseHTTPRequestHandler, HTTPServer
 import threading
 import time
 import unittest
+import warnings
 
 import pytest
 
@@ -12,9 +13,10 @@ from prometheus_client import (
 )
 from prometheus_client.core import GaugeHistogramMetricFamily, Timestamp
 from prometheus_client.exposition import (
-    basic_auth_handler, default_handler, MetricsHandler,
-    passthrough_redirect_handler,
+    basic_auth_handler, choose_encoder, choose_formatter, default_handler,
+    MetricsHandler, passthrough_redirect_handler,
 )
+import prometheus_client.openmetrics.exposition as openmetrics
 
 
 class TestGenerateText(unittest.TestCase):
@@ -460,5 +462,19 @@ def test_histogram_metric_families(MetricFamily, registry, buckets, sum_value, e
     _expect_metric_exception(registry, error)
 
 
+def test_choose_encoder():
+    assert choose_encoder(None) == (generate_latest, CONTENT_TYPE_LATEST)
+    assert choose_encoder(CONTENT_TYPE_LATEST) == (generate_latest, CONTENT_TYPE_LATEST)
+    assert choose_encoder(openmetrics.CONTENT_TYPE_LATEST) == (openmetrics.generate_latest, openmetrics.CONTENT_TYPE_LATEST)
+
+
+def test_choose_formatter():
+    with warnings.catch_warnings(record=True) as w:
+        assert choose_formatter('') == (generate_latest, CONTENT_TYPE_LATEST)
+        assert len(w) == 1
+        assert issubclass(w[-1].category, DeprecationWarning)
+        assert "choose_formatter is deprecated" in str(w[-1].message)
+
+
 if __name__ == '__main__':
     unittest.main()