nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: prometheus/client_python
Pull request #520 (2020-02-29 14:47:22)

Raise exception when setting state in non-observable Enum
A fix for #501.


Patch:
diff --git a/prometheus_client/metrics.py b/prometheus_client/metrics.py
index 4094449..b34ca81 100644
--- a/prometheus_client/metrics.py
+++ b/prometheus_client/metrics.py
@@ -656,6 +656,7 @@ class Enum(MetricWrapperBase):
 
     def state(self, state):
         """Set enum metric state."""
+        self._raise_if_not_observable()
         with self._lock:
             self._value = self._states.index(state)
 


Test patch:
diff --git a/tests/test_core.py b/tests/test_core.py
index 2d6f83f..f0b856a 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -428,6 +428,7 @@ class TestEnum(unittest.TestCase):
         self.assertEqual(0, self.registry.get_sample_value('el', {'l': 'a', 'el': 'a'}))
         self.assertEqual(0, self.registry.get_sample_value('el', {'l': 'a', 'el': 'b'}))
         self.assertEqual(1, self.registry.get_sample_value('el', {'l': 'a', 'el': 'c'}))
+        self.assertRaises(ValueError, self.labels.state, 'a')
 
     def test_overlapping_labels(self):
         with pytest.raises(ValueError):
Repository: prometheus/client_python
Pull request #543 (2020-05-09 15:51:06)

Cleaning up name before appending unit on name
Unit append in the name were being removed when *_total* exists. This moves the clean up before appending the unit. 

Refs https://github.com/prometheus/client_python/issues/542

@brian-brazil Should this "repeated" unit raise an ValueError exception instead since this suffix is already append when dumping on WSGI.


Patch:
diff --git a/prometheus_client/metrics.py b/prometheus_client/metrics.py
index b34ca81..95770eb 100644
--- a/prometheus_client/metrics.py
+++ b/prometheus_client/metrics.py
@@ -27,12 +27,12 @@ def _build_full_name(metric_type, name, namespace, subsystem, unit):
     if subsystem:
         full_name += subsystem + '_'
     full_name += name
+    if metric_type == 'counter' and full_name.endswith('_total'):
+        full_name = full_name[:-6]  # Munge to OpenMetrics.
     if unit and not full_name.endswith("_" + unit):
         full_name += "_" + unit
     if unit and metric_type in ('info', 'stateset'):
         raise ValueError('Metric name is of a type that cannot have a unit: ' + full_name)
-    if metric_type == 'counter' and full_name.endswith('_total'):
-        full_name = full_name[:-6]  # Munge to OpenMetrics.
     return full_name
 
 


Test patch:
diff --git a/tests/test_core.py b/tests/test_core.py
index f0b856a..b14e340 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -527,6 +527,11 @@ class TestMetricWrapper(unittest.TestCase):
         self.assertRaises(ValueError, Info, 'foo', 'help', unit="x")
         self.assertRaises(ValueError, Enum, 'foo', 'help', unit="x")
 
+    def test_name_cleanup_before_unit_append(self):
+        self.assertEqual(self.counter._name, 'c')
+        self.c = Counter('c_total', 'help', unit="total", labelnames=['l'], registry=self.registry)
+        self.assertEqual(self.c._name, 'c_total')
+
 
 class TestMetricFamilies(unittest.TestCase):
     def setUp(self):
diff --git a/tests/test_exposition.py b/tests/test_exposition.py
index 47c200f..21b3f59 100644
--- a/tests/test_exposition.py
+++ b/tests/test_exposition.py
@@ -59,6 +59,17 @@ cc_total 1.0
 # HELP cc_created A counter
 # TYPE cc_created gauge
 cc_created 123.456
+""", generate_latest(self.registry))
+
+    def test_counter_name_unit_append(self):
+        c = Counter('requests', 'Request counter', unit="total", registry=self.registry)
+        c.inc()
+        self.assertEqual(b"""# HELP requests_total_total Request counter
+# TYPE requests_total_total counter
+requests_total_total 1.0
+# HELP requests_total_created Request counter
+# TYPE requests_total_created gauge
+requests_total_created 123.456
 """, generate_latest(self.registry))
 
     def test_counter_total(self):
Repository: prometheus/client_python
Pull request #631 (2021-02-23 17:43:47)

Add separate handling of the /favicon.ico path in the default wsgi implementation
By default many browsers will attempt to load a /favicon.ico resource from the server. Currently the default wsgi implementation serves metrics on any path and thus will incorrectly return metrics when being asked for a favicon. This PR fixes this behavior by serving an empty response.


Patch:
diff --git a/prometheus_client/exposition.py b/prometheus_client/exposition.py
index 0720ce4..caae9c8 100644
--- a/prometheus_client/exposition.py
+++ b/prometheus_client/exposition.py
@@ -113,8 +113,14 @@ def make_wsgi_app(registry=REGISTRY):
         # Prepare parameters
         accept_header = environ.get('HTTP_ACCEPT')
         params = parse_qs(environ.get('QUERY_STRING', ''))
-        # Bake output
-        status, header, output = _bake_output(registry, accept_header, params)
+        if environ['PATH_INFO'] == '/favicon.ico':
+            # Serve empty response for browsers
+            status = '200 OK'
+            header = ('', '')
+            output = b''
+        else:
+            # Bake output
+            status, header, output = _bake_output(registry, accept_header, params)
         # Return output
         start_response(status, [header])
         return [output]


Test patch:
diff --git a/tests/test_wsgi.py b/tests/test_wsgi.py
index 80ee48c..79fea88 100644
--- a/tests/test_wsgi.py
+++ b/tests/test_wsgi.py
@@ -1,10 +1,12 @@
 from __future__ import absolute_import, unicode_literals
 
+import sys
+import unittest
 from unittest import TestCase
 from wsgiref.util import setup_testing_defaults
 
 from prometheus_client import CollectorRegistry, Counter, make_wsgi_app
-from prometheus_client.exposition import CONTENT_TYPE_LATEST
+from prometheus_client.exposition import _bake_output, CONTENT_TYPE_LATEST
 
 
 class WSGITest(TestCase):
@@ -65,3 +67,22 @@ class WSGITest(TestCase):
 
     def test_report_metrics_4(self):
         self.validate_metrics("failed_requests", "Number of failed requests", 7)
+
+    @unittest.skipIf(sys.version_info < (3, 3), "Test requires Python 3.3+.")
+    def test_favicon_path(self):
+        from unittest.mock import patch
+
+        # Create mock to enable counting access of _bake_output
+        with patch("prometheus_client.exposition._bake_output", side_effect=_bake_output) as mock:
+            # Create and run WSGI app
+            app = make_wsgi_app(self.registry)
+            # Try accessing the favicon path
+            favicon_environ = dict(self.environ)
+            favicon_environ['PATH_INFO'] = '/favicon.ico'
+            outputs = app(favicon_environ, self.capture)
+            # Test empty response
+            self.assertEqual(outputs, [b''])
+            self.assertEqual(mock.call_count, 0)
+            # Try accessing normal paths
+            app(self.environ, self.capture)
+            self.assertEqual(mock.call_count, 1)
Repository: prometheus/client_python
Pull request #872 (2022-12-21 23:53:13)

Allow Prometheus parser to handle missing space
If there is no delimiter separating the labels and value when parsing the Prometheus format the parser currently will chop off the first digit of the value. Instead, allow a missing delimiter in the Prometheus format to align with what the Go parser does.

In addition, add a test to specifically check that a delimiter is still required in OpenMetrics.

Fixes: #871 


Patch:
diff --git a/prometheus_client/parser.py b/prometheus_client/parser.py
index ad3e1c6..7135bc8 100644
--- a/prometheus_client/parser.py
+++ b/prometheus_client/parser.py
@@ -116,8 +116,8 @@ def _parse_sample(text):
         name = text[:label_start].strip()
         # We ignore the starting curly brace
         label = text[label_start + 1:label_end]
-        # The value is after the label end (ignoring curly brace and space)
-        value, timestamp = _parse_value_and_timestamp(text[label_end + 2:])
+        # The value is after the label end (ignoring curly brace)
+        value, timestamp = _parse_value_and_timestamp(text[label_end + 1:])
         return Sample(name, _parse_labels(label), value, timestamp)
 
     # We don't have labels


Test patch:
diff --git a/tests/openmetrics/test_parser.py b/tests/openmetrics/test_parser.py
index 4b4aecd..937aef5 100644
--- a/tests/openmetrics/test_parser.py
+++ b/tests/openmetrics/test_parser.py
@@ -642,6 +642,8 @@ bar_bucket{a="c",le="+Inf"} 0.0
             ('a{a""} 1\n# EOF\n'),
             ('a{a=} 1\n# EOF\n'),
             ('a{a="} 1\n# EOF\n'),
+            # Missing delimiters.
+            ('a{a="1"}1\n# EOF\n'),
             # Missing or extra commas.
             ('a{a="1"b="2"} 1\n# EOF\n'),
             ('a{a="1",,b="2"} 1\n# EOF\n'),
diff --git a/tests/test_parser.py b/tests/test_parser.py
index 1d20d27..61b3c8a 100644
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -146,6 +146,7 @@ a\t\t{\t\tfoo\t\t=\t\t"baz"\t\t}\t\t2
 a   {    foo   =  "buz"   }    3
 a\t {  \t foo\t = "biz"\t  } \t 4
 a \t{\t foo   = "boz"\t}\t 5
+a{foo="bez"}6
 """)
         metric_family = CounterMetricFamily("a", "help", labels=["foo"])
         metric_family.add_metric(["bar"], 1)
@@ -153,6 +154,7 @@ a \t{\t foo   = "boz"\t}\t 5
         metric_family.add_metric(["buz"], 3)
         metric_family.add_metric(["biz"], 4)
         metric_family.add_metric(["boz"], 5)
+        metric_family.add_metric(["bez"], 6)
         self.assertEqualMetrics([metric_family], list(families))
 
     def test_commas(self):
Repository: urlaubsverwaltung/urlaubsverwaltung
Pull request #4268 (2023-11-05 12:55:11)

enable approval/cancellation process for new vacation type by default
refs #2730


Patch:
diff --git a/src/main/java/org/synyx/urlaubsverwaltung/settings/SettingsAbsenceTypesViewController.java b/src/main/java/org/synyx/urlaubsverwaltung/settings/SettingsAbsenceTypesViewController.java
index 27541efe3..0c7ec12f5 100644
--- a/src/main/java/org/synyx/urlaubsverwaltung/settings/SettingsAbsenceTypesViewController.java
+++ b/src/main/java/org/synyx/urlaubsverwaltung/settings/SettingsAbsenceTypesViewController.java
@@ -85,8 +85,8 @@ public class SettingsAbsenceTypesViewController implements HasLaunchpad {
             new AbsenceTypeSettingsItemLabelDto(Locale.ENGLISH, ""),
             new AbsenceTypeSettingsItemLabelDto(Locale.forLanguageTag("el"), "")
         ));
-        newAbsenceType.setRequiresApprovalToApply(false);
-        newAbsenceType.setRequiresApprovalToCancel(false);
+        newAbsenceType.setRequiresApprovalToApply(true);
+        newAbsenceType.setRequiresApprovalToCancel(true);
         newAbsenceType.setVisibleToEveryone(false);
         newAbsenceType.setColor(VacationTypeColor.YELLOW);
 


Test patch:
diff --git a/src/test/java/org/synyx/urlaubsverwaltung/settings/SettingsAbsenceTypesViewControllerTest.java b/src/test/java/org/synyx/urlaubsverwaltung/settings/SettingsAbsenceTypesViewControllerTest.java
index 41f1576fb..9723acc2f 100644
--- a/src/test/java/org/synyx/urlaubsverwaltung/settings/SettingsAbsenceTypesViewControllerTest.java
+++ b/src/test/java/org/synyx/urlaubsverwaltung/settings/SettingsAbsenceTypesViewControllerTest.java
@@ -181,8 +181,8 @@ class SettingsAbsenceTypesViewControllerTest {
             new AbsenceTypeSettingsItemLabelDto(ENGLISH, ""),
             new AbsenceTypeSettingsItemLabelDto(LOCALE_EL, "")
         ));
-        newAbsenceType.setRequiresApprovalToApply(false);
-        newAbsenceType.setRequiresApprovalToCancel(false);
+        newAbsenceType.setRequiresApprovalToApply(true);
+        newAbsenceType.setRequiresApprovalToCancel(true);
         newAbsenceType.setVisibleToEveryone(false);
         newAbsenceType.setColor(YELLOW);
 
@@ -240,8 +240,8 @@ class SettingsAbsenceTypesViewControllerTest {
             new AbsenceTypeSettingsItemLabelDto(ENGLISH, ""),
             new AbsenceTypeSettingsItemLabelDto(LOCALE_EL, "")
         ));
-        newAbsenceType.setRequiresApprovalToApply(false);
-        newAbsenceType.setRequiresApprovalToCancel(false);
+        newAbsenceType.setRequiresApprovalToApply(true);
+        newAbsenceType.setRequiresApprovalToCancel(true);
         newAbsenceType.setVisibleToEveryone(false);
         newAbsenceType.setColor(YELLOW);
Repository: canonical/operator
Pull request #62 (2019-12-01 16:52:34)

Fix an argument name passed to pod-spec-set
* --file needs to be used instead of --spec;
* the current implementation of pod_spec_set function does not allow for
  easy testing of hook tool calls as temporary directories created for
  json files are hidden from the caller and contain a randomized 8-byte
  component. The current test is an attempt to do an immediate fix
  without reworking pod_spec_set to solve an immediate problem of it
  being broken.


Patch:
diff --git a/op/model.py b/op/model.py
index 9c8a306..87b9440 100644
--- a/op/model.py
+++ b/op/model.py
@@ -522,7 +522,7 @@ class ModelBackend:
         try:
             spec_path = tmpdir / 'spec.json'
             spec_path.write_text(json.dumps(spec))
-            args = ['--spec', str(spec_path)]
+            args = ['--file', str(spec_path)]
             if k8s_resources:
                 k8s_res_path = tmpdir / 'k8s-resources.json'
                 k8s_res_path.write_text(json.dumps(k8s_resources))


Test patch:
diff --git a/test/test_model.py b/test/test_model.py
index 7b88402..0d47e99 100644
--- a/test/test_model.py
+++ b/test/test_model.py
@@ -7,6 +7,7 @@ import pathlib
 import shutil
 import unittest
 import time
+import re
 
 import op.model
 import op.charm
@@ -372,14 +373,27 @@ class TestModel(unittest.TestCase):
         spec_path = self.fake_script_path / 'spec.json'
         k8s_res_path = self.fake_script_path / 'k8s_res.json'
 
+        def check_calls(calls):
+            self.assertEqual(len(fake_calls), 1)
+            self.assertEqual(fake_calls[0][:2], ['pod-spec-set', '--file'])
+            # 8 bytes are used as of python 3.4.0, see Python bug #12015.
+            # Other characters are from POSIX 3.282 (Portable Filename Character Set) a subset of which Python's mkdtemp uses.
+            self.assertTrue(re.match('/tmp/tmp[A-Za-z0-9._-]{8}-pod-spec-set', fake_calls[0][2]))
+
         model.pod.set_spec({'foo': 'bar'})
         self.assertEqual(spec_path.read_text(), '{"foo": "bar"}')
         self.assertFalse(k8s_res_path.exists())
 
+        fake_calls = fake_script_calls(self, clear=True)
+        check_calls(fake_calls)
+
         model.pod.set_spec({'bar': 'foo'}, {'qux': 'baz'})
         self.assertEqual(spec_path.read_text(), '{"bar": "foo"}')
         self.assertEqual(k8s_res_path.read_text(), '{"qux": "baz"}')
 
+        fake_calls = fake_script_calls(self, clear=True)
+        check_calls(fake_calls)
+
     def test_base_status_instance_raises(self):
         with self.assertRaises(TypeError):
             op.model.StatusBase('test')
Repository: canonical/operator
Pull request #68 (2019-12-04 16:22:22)

Use TypeError for invalid argument type errors
RuntimeError is currently used instead of TypeError in multiple places
in ModelBackend where incorrect argument type is handled. There is a
more specific exception for that purpose:

https://docs.python.org/3/library/exceptions.html#TypeError
"Passing arguments of the wrong type (e.g. passing a list when an int is
expected) should result in a TypeError"


Patch:
diff --git a/op/model.py b/op/model.py
index 231c42c..5cf48ea 100644
--- a/op/model.py
+++ b/op/model.py
@@ -490,7 +490,7 @@ class ModelBackend:
 
     def relation_get(self, relation_id, member_name, is_app):
         if not isinstance(is_app, bool):
-            raise RuntimeError('is_app parameter to relation_get must be a boolean')
+            raise TypeError('is_app parameter to relation_get must be a boolean')
 
         try:
             return self._run('relation-get', '-r', str(relation_id), '-', member_name, f'--app={is_app}', return_output=True, use_json=True)
@@ -501,7 +501,7 @@ class ModelBackend:
 
     def relation_set(self, relation_id, key, value, is_app):
         if not isinstance(is_app, bool):
-            raise RuntimeError('is_app parameter to relation_set must be a boolean')
+            raise TypeError('is_app parameter to relation_set must be a boolean')
 
         try:
             return self._run('relation-set', '-r', str(relation_id), f'{key}={value}', f'--app={is_app}')
@@ -556,5 +556,5 @@ class ModelBackend:
         app -- A boolean indicating whether the status should be set for a unit or an application.
         """
         if not isinstance(is_app, bool):
-            raise RuntimeError('is_app parameter must be boolean')
+            raise TypeError('is_app parameter must be boolean')
         return self._run('status-set', f'--application={is_app}', status, message)


Test patch:
diff --git a/test/test_model.py b/test/test_model.py
index 5f53470..5a24ae7 100644
--- a/test/test_model.py
+++ b/test/test_model.py
@@ -288,10 +288,10 @@ class TestModel(unittest.TestCase):
 
         # Invalid types for is_app.
         for is_app_v in [None, 1, 2.0, 'a', b'beef']:
-            with self.assertRaises(RuntimeError):
+            with self.assertRaises(TypeError):
                 self.backend.relation_set(1, 'fookey', 'barval', is_app=is_app_v)
 
-            with self.assertRaises(RuntimeError):
+            with self.assertRaises(TypeError):
                 self.backend.relation_get(1, 'fooentity', is_app=is_app_v)
 
     def test_relation_data_type_check(self):
@@ -545,7 +545,7 @@ class TestModel(unittest.TestCase):
         self.backend = op.model.ModelBackend()
 
         for is_app_v in [None, 1, 2.0, 'a', b'beef', object]:
-            with self.assertRaises(RuntimeError):
+            with self.assertRaises(TypeError):
                 self.backend.status_set(op.model.ActiveStatus, is_app=is_app_v)
 
     def test_remote_unit_status(self):
Repository: canonical/operator
Pull request #121 (2020-01-30 11:56:58)

Include set_default as a method on BoundStoredState.
This solves one of the big "how do I initialize my State" questions. The
implementation is fairly lean, and it avoids problems where things end
up dirty because you wanted to have a default value.


Patch:
diff --git a/ops/framework.py b/ops/framework.py
index 146f3fe..de3993c 100755
--- a/ops/framework.py
+++ b/ops/framework.py
@@ -704,6 +704,12 @@ class BoundStoredState:
         self._data[key] = _unwrap_stored(self._data, value)
         self.on.changed.emit()
 
+    def set_default(self, **kwargs):
+        """"Set the value of any given key if it has not already been set"""
+        for k, v in kwargs.items():
+            if k not in self._data:
+                self._data[k] = v
+
 
 class StoredState:
 


Test patch:
diff --git a/test/test_framework.py b/test/test_framework.py
index 9ceb994..d8aaa72 100755
--- a/test/test_framework.py
+++ b/test/test_framework.py
@@ -1139,6 +1139,29 @@ class TestStoredState(unittest.TestCase):
                 self.assertEqual(a, old_a)
                 self.assertEqual(b, old_b)
 
+    def test_set_default(self):
+        framework = self.create_framework()
+
+        class StatefulObject(Object):
+            state = StoredState()
+        parent = StatefulObject(framework, 'key')
+        parent.state.set_default(foo=1)
+        self.assertEqual(parent.state.foo, 1)
+        parent.state.set_default(foo=2)
+        # foo was already set, so it doesn't get replaced
+        self.assertEqual(parent.state.foo, 1)
+        parent.state.set_default(foo=3, bar=4)
+        self.assertEqual(parent.state.foo, 1)
+        self.assertEqual(parent.state.bar, 4)
+        # reloading the state still leaves things at the default values
+        framework.commit()
+        del parent
+        parent = StatefulObject(framework, 'key')
+        parent.state.set_default(foo=5, bar=6)
+        self.assertEqual(parent.state.foo, 1)
+        self.assertEqual(parent.state.bar, 4)
+        # TODO(jam) 2020-01-30: is there a clean way to tell that parent.state._data.dirty is False?
+
 
 if __name__ == "__main__":
     unittest.main()
Repository: canonical/operator
Pull request #159 (2020-03-03 09:06:28)

Add support for storing floats
Storing floats was not supported although we claimed to support basic types.


Patch:
diff --git a/ops/framework.py b/ops/framework.py
index cfe9238..bcad9ef 100755
--- a/ops/framework.py
+++ b/ops/framework.py
@@ -757,8 +757,8 @@ class BoundStoredState:
 
         value = _unwrap_stored(self._data, value)
 
-        if not isinstance(value, (type(None), int, str, bytes, list, dict, set)):
-            raise AttributeError("attribute '{}' cannot be set to {}: must be int/dict/list/etc".format(key, type(value).__name__))
+        if not isinstance(value, (type(None), int, float, str, bytes, list, dict, set)):
+            raise AttributeError("attribute '{}' cannot be set to {}: must be int/float/dict/list/etc".format(key, type(value).__name__))
 
         self._data[key] = _unwrap_stored(self._data, value)
         self.on.changed.emit()


Test patch:
diff --git a/test/test_framework.py b/test/test_framework.py
index 261b38f..d240b77 100755
--- a/test/test_framework.py
+++ b/test/test_framework.py
@@ -786,6 +786,8 @@ class TestStoredState(unittest.TestCase):
         obj.state.foo = 41
         obj.state.foo = 42
         obj.state.bar = "s"
+        obj.state.baz = 4.2
+        obj.state.bing = True
 
         self.assertEqual(obj.state.foo, 42)
 
@@ -801,6 +803,8 @@ class TestStoredState(unittest.TestCase):
         obj_copy = SomeObject(framework_copy, "1")
         self.assertEqual(obj_copy.state.foo, 42)
         self.assertEqual(obj_copy.state.bar, "s")
+        self.assertEqual(obj_copy.state.baz, 4.2)
+        self.assertEqual(obj_copy.state.bing, True)
 
     def test_mutable_types_invalid(self):
         framework = self.create_framework()
@@ -814,7 +818,7 @@ class TestStoredState(unittest.TestCase):
                 pass
             obj.state.foo = CustomObject()
         except AttributeError as e:
-            self.assertEqual(str(e), "attribute 'foo' cannot be set to CustomObject: must be int/dict/list/etc")
+            self.assertEqual(str(e), "attribute 'foo' cannot be set to CustomObject: must be int/float/dict/list/etc")
         else:
             self.fail('AttributeError not raised')