From a34a80fc7a384e3bca5469532c13b1c6cea34557 Mon Sep 17 00:00:00 2001 From: Yury Pliner Date: Fri, 28 Jan 2022 16:51:53 +0000 Subject: [PATCH 1/4] Add typing to Histogram Also we could set disallow_incomplete_defs to True Signed-off-by: Yury Pliner --- mypy.ini | 1 + prometheus_client/metrics.py | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/mypy.ini b/mypy.ini index 1470c9b2..fe372d07 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,6 +1,7 @@ [mypy] exclude = prometheus_client/decorator.py|prometheus_client/twisted|tests/test_twisted.py implicit_reexport = False +disallow_incomplete_defs = True [mypy-prometheus_client.decorator] follow_imports = skip diff --git a/prometheus_client/metrics.py b/prometheus_client/metrics.py index be61f05c..c15b33b8 100644 --- a/prometheus_client/metrics.py +++ b/prometheus_client/metrics.py @@ -413,7 +413,7 @@ def set_function(self, f): self._raise_if_not_observable() - def samples(self) -> Iterable[Sample]: + def samples(_: Gauge) -> Iterable[Sample]: return (Sample('', {}, float(f()), None, None),) self._child_samples = types.MethodType(samples, self) @@ -530,15 +530,15 @@ def create_response(request): DEFAULT_BUCKETS = (.005, .01, .025, .05, .075, .1, .25, .5, .75, 1.0, 2.5, 5.0, 7.5, 10.0, INF) def __init__(self, - name, - documentation, - labelnames=(), - namespace='', - subsystem='', - unit='', - registry=REGISTRY, - _labelvalues=None, - buckets=DEFAULT_BUCKETS, + name: str, + documentation: str, + labelnames: Iterable[str] = (), + namespace: str = '', + subsystem: str = '', + unit: str = '', + registry: Optional[CollectorRegistry] = REGISTRY, + _labelvalues: Optional[Sequence[str]] = None, + buckets: Sequence[float] = DEFAULT_BUCKETS, ): self._prepare_buckets(buckets) super().__init__( @@ -553,7 +553,7 @@ def __init__(self, ) self._kwargs['buckets'] = buckets - def _prepare_buckets(self, buckets): + def _prepare_buckets(self, buckets: Sequence[float]) -> None: buckets = [float(b) for b in buckets] if buckets != sorted(buckets): # This is probably an error on the part of the user, @@ -565,7 +565,7 @@ def _prepare_buckets(self, buckets): raise ValueError('Must have at least two buckets') self._upper_bounds = buckets - def _metric_init(self): + def _metric_init(self) -> None: self._buckets = [] self._created = time.time() bucket_labelnames = self._labelnames + ('le',) @@ -579,7 +579,7 @@ def _metric_init(self): self._labelvalues + (floatToGoString(b),)) ) - def observe(self, amount, exemplar=None): + def observe(self, amount: float = 1, exemplar: Optional[Dict[str, str]] = None) -> None: """Observe the given amount. The amount is usually positive or zero. Negative values are @@ -599,7 +599,7 @@ def observe(self, amount, exemplar=None): self._buckets[i].set_exemplar(Exemplar(exemplar, amount, time.time())) break - def time(self): + def time(self) -> Timer: """Time a block of code or function, and observe the duration in seconds. Can be used as a function decorator or context manager. From 76c0c4823a0d6b40814cd77c7e3845e378c1a009 Mon Sep 17 00:00:00 2001 From: Yury Pliner Date: Fri, 28 Jan 2022 17:17:11 +0000 Subject: [PATCH 2/4] Add typing to Gauge/Summary Signed-off-by: Yury Pliner --- prometheus_client/metrics.py | 42 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/prometheus_client/metrics.py b/prometheus_client/metrics.py index c15b33b8..4a60ae16 100644 --- a/prometheus_client/metrics.py +++ b/prometheus_client/metrics.py @@ -337,15 +337,15 @@ def f(): _MULTIPROC_MODES = frozenset(('min', 'max', 'livesum', 'liveall', 'all')) def __init__(self, - name, - documentation, - labelnames=(), - namespace='', - subsystem='', - unit='', - registry=REGISTRY, - _labelvalues=None, - multiprocess_mode='all', + name: str, + documentation: str, + labelnames: Iterable[str] = (), + namespace: str = '', + subsystem: str = '', + unit: str = '', + registry: Optional[CollectorRegistry] = REGISTRY, + _labelvalues: Optional[Sequence[str]] = None, + multiprocess_mode: str = 'all', ): self._multiprocess_mode = multiprocess_mode if multiprocess_mode not in self._MULTIPROC_MODES: @@ -362,32 +362,32 @@ def __init__(self, ) self._kwargs['multiprocess_mode'] = self._multiprocess_mode - def _metric_init(self): + def _metric_init(self) -> None: self._value = values.ValueClass( self._type, self._name, self._name, self._labelnames, self._labelvalues, multiprocess_mode=self._multiprocess_mode ) - def inc(self, amount=1): + def inc(self, amount: float = 1) -> None: """Increment gauge by the given amount.""" self._raise_if_not_observable() self._value.inc(amount) - def dec(self, amount=1): + def dec(self, amount: float = 1) -> None: """Decrement gauge by the given amount.""" self._raise_if_not_observable() self._value.inc(-amount) - def set(self, value): + def set(self, value: float) -> None: """Set gauge to the given value.""" self._raise_if_not_observable() self._value.set(float(value)) - def set_to_current_time(self): + def set_to_current_time(self) -> None: """Set gauge to the current unixtime.""" self.set(time.time()) - def track_inprogress(self): + def track_inprogress(self) -> InprogressTracker: """Track inprogress blocks of code or functions. Can be used as a function decorator or context manager. @@ -397,14 +397,14 @@ def track_inprogress(self): self._raise_if_not_observable() return InprogressTracker(self) - def time(self): + def time(self) -> Timer: """Time a block of code or function, and set the duration in seconds. Can be used as a function decorator or context manager. """ return Timer(self, 'set') - def set_function(self, f): + def set_function(self, f: Callable[[], float]) -> None: """Call the provided function to return the Gauge value. The function must return a float, and may be called from @@ -416,7 +416,7 @@ def set_function(self, f): def samples(_: Gauge) -> Iterable[Sample]: return (Sample('', {}, float(f()), None, None),) - self._child_samples = types.MethodType(samples, self) + self._child_samples = types.MethodType(samples, self) # type: ignore def _child_samples(self) -> Iterable[Sample]: return (Sample('', {}, self._value.get(), None, None),) @@ -455,13 +455,13 @@ def create_response(request): _type = 'summary' _reserved_labelnames = ['quantile'] - def _metric_init(self): + def _metric_init(self) -> None: self._count = values.ValueClass(self._type, self._name, self._name + '_count', self._labelnames, self._labelvalues) self._sum = values.ValueClass(self._type, self._name, self._name + '_sum', self._labelnames, self._labelvalues) self._created = time.time() - def observe(self, amount): + def observe(self, amount: float) -> None: """Observe the given amount. The amount is usually positive or zero. Negative values are @@ -475,7 +475,7 @@ def observe(self, amount): self._count.inc(1) self._sum.inc(amount) - def time(self): + def time(self) -> Timer: """Time a block of code or function, and observe the duration in seconds. Can be used as a function decorator or context manager. From 0551300737910a5c709562215bb2a0a888e3fa8c Mon Sep 17 00:00:00 2001 From: Yury Pliner Date: Fri, 28 Jan 2022 17:58:58 +0000 Subject: [PATCH 3/4] Ditch default value Signed-off-by: Yury Pliner --- prometheus_client/metrics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prometheus_client/metrics.py b/prometheus_client/metrics.py index 4a60ae16..8b9a535a 100644 --- a/prometheus_client/metrics.py +++ b/prometheus_client/metrics.py @@ -579,7 +579,7 @@ def _metric_init(self) -> None: self._labelvalues + (floatToGoString(b),)) ) - def observe(self, amount: float = 1, exemplar: Optional[Dict[str, str]] = None) -> None: + def observe(self, amount: float, exemplar: Optional[Dict[str, str]] = None) -> None: """Observe the given amount. The amount is usually positive or zero. Negative values are From 02b00530e762d30b8f47aabf04a80bd199af4886 Mon Sep 17 00:00:00 2001 From: Yury Pliner Date: Tue, 1 Feb 2022 14:14:01 +0500 Subject: [PATCH 4/4] Fix review comments Signed-off-by: Yury Pliner --- prometheus_client/metrics.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/prometheus_client/metrics.py b/prometheus_client/metrics.py index 8b9a535a..b9780d04 100644 --- a/prometheus_client/metrics.py +++ b/prometheus_client/metrics.py @@ -2,7 +2,7 @@ import time import types from typing import ( - Any, Callable, Dict, Iterable, Optional, Sequence, Type, TypeVar, + Any, Callable, Dict, Iterable, Optional, Sequence, Type, TypeVar, Union, ) from . import values # retain this import style for testability @@ -538,7 +538,7 @@ def __init__(self, unit: str = '', registry: Optional[CollectorRegistry] = REGISTRY, _labelvalues: Optional[Sequence[str]] = None, - buckets: Sequence[float] = DEFAULT_BUCKETS, + buckets: Sequence[Union[float, int, str]] = DEFAULT_BUCKETS, ): self._prepare_buckets(buckets) super().__init__( @@ -553,8 +553,8 @@ def __init__(self, ) self._kwargs['buckets'] = buckets - def _prepare_buckets(self, buckets: Sequence[float]) -> None: - buckets = [float(b) for b in buckets] + def _prepare_buckets(self, source_buckets: Sequence[Union[float, int, str]]) -> None: + buckets = [float(b) for b in source_buckets] if buckets != sorted(buckets): # This is probably an error on the part of the user, # so raise rather than sorting for them.