nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: prometheus/client_python
Pull request #445 (2019-08-06 16:19:30)

Check for duplicate label names, add missing checks on new code path.
@SuperQ 


Patch:
diff --git a/prometheus_client/openmetrics/parser.py b/prometheus_client/openmetrics/parser.py
index 3e28509..50fa341 100644
--- a/prometheus_client/openmetrics/parser.py
+++ b/prometheus_client/openmetrics/parser.py
@@ -139,9 +139,12 @@ def _parse_labels_with_state_machine(text):
             if char == '\\':
                 state = 'labelvalueslash'
             elif char == '"':
-                if not METRIC_LABEL_NAME_RE.match(''.join(labelname)):
-                    raise ValueError("Invalid line: " + text)
-                labels[''.join(labelname)] = ''.join(labelvalue)
+                ln = ''.join(labelname)
+                if not METRIC_LABEL_NAME_RE.match(ln):
+                    raise ValueError("Invalid line, bad label name: " + text)
+                if ln in labels:
+                    raise ValueError("Invalid line, duplicate label name: " + text)
+                labels[ln] = ''.join(labelvalue)
                 labelname = []
                 labelvalue = []
                 state = 'endoflabelvalue'
@@ -217,6 +220,10 @@ def _parse_labels(text):
             # Replace escaping if needed
             if "\\" in label_value:
                 label_value = _replace_escaping(label_value)
+            if not METRIC_LABEL_NAME_RE.match(label_name):
+                raise ValueError("invalid line, bad label name: " + text)
+            if label_name in labels:
+                raise ValueError("invalid line, duplicate label name: " + text)
             labels[label_name] = label_value
 
             # Remove the processed label from the sub-slice for next iteration


Test patch:
diff --git a/tests/openmetrics/test_parser.py b/tests/openmetrics/test_parser.py
index 8187338..63dd5e4 100644
--- a/tests/openmetrics/test_parser.py
+++ b/tests/openmetrics/test_parser.py
@@ -560,6 +560,11 @@ foo_created 1.520430000123e+09
             ('a{a="1"b="2"} 1\n# EOF\n'),
             ('a{a="1",,b="2"} 1\n# EOF\n'),
             ('a{a="1",b="2",} 1\n# EOF\n'),
+            # Invalid labels.
+            ('a{1="1"} 1\n# EOF\n'),
+            ('a{a="1",a="1"} 1\n# EOF\n'),
+            ('a{1=" # "} 1\n# EOF\n'),
+            ('a{a=" # ",a=" # "} 1\n# EOF\n'),
             # Missing value.
             ('a\n# EOF\n'),
             ('a \n# EOF\n'),
Repository: prometheus/client_python
Pull request #471 (2019-10-01 13:30:21)

#470 Add `HELP` output for auto-created metrics

brian-brazil: Could you add the DCO and a unittest?
davidlukac: @brian-brazil yep, on it
davidlukac: @brian-brazil done

Patch:
diff --git a/prometheus_client/exposition.py b/prometheus_client/exposition.py
index 2e32985..238591b 100644
--- a/prometheus_client/exposition.py
+++ b/prometheus_client/exposition.py
@@ -122,6 +122,8 @@ def generate_latest(registry=REGISTRY):
             raise
 
         for suffix, lines in sorted(om_samples.items()):
+            output.append('# HELP {0}{1} {2}\n'.format(metric.name, suffix, 
+                                                       metric.documentation.replace('\\', r'\\').replace('\n', r'\n')))
             output.append('# TYPE {0}{1} gauge\n'.format(metric.name, suffix))
             output.extend(lines)
     return ''.join(output).encode('utf-8')


Test patch:
diff --git a/tests/test_exposition.py b/tests/test_exposition.py
index de116a0..44b197a 100644
--- a/tests/test_exposition.py
+++ b/tests/test_exposition.py
@@ -56,6 +56,7 @@ class TestGenerateText(unittest.TestCase):
         self.assertEqual(b"""# HELP cc_total A counter
 # TYPE cc_total counter
 cc_total 1.0
+# HELP cc_created A counter
 # TYPE cc_created gauge
 cc_created 123.456
 """, generate_latest(self.registry))
@@ -66,6 +67,7 @@ cc_created 123.456
         self.assertEqual(b"""# HELP cc_total A counter
 # TYPE cc_total counter
 cc_total 1.0
+# HELP cc_created A counter
 # TYPE cc_created gauge
 cc_created 123.456
 """, generate_latest(self.registry))
@@ -82,6 +84,7 @@ cc_created 123.456
 # TYPE ss summary
 ss_count{a="c",b="d"} 1.0
 ss_sum{a="c",b="d"} 17.0
+# HELP ss_created A summary
 # TYPE ss_created gauge
 ss_created{a="c",b="d"} 123.456
 """, generate_latest(self.registry))
@@ -109,6 +112,7 @@ hh_bucket{le="10.0"} 1.0
 hh_bucket{le="+Inf"} 1.0
 hh_count 1.0
 hh_sum 0.05
+# HELP hh_created A histogram
 # TYPE hh_created gauge
 hh_created 123.456
 """, generate_latest(self.registry))
@@ -119,8 +123,10 @@ hh_created 123.456
 # TYPE gh histogram
 gh_bucket{le="1.0"} 4.0
 gh_bucket{le="+Inf"} 5.0
+# HELP gh_gcount help
 # TYPE gh_gcount gauge
 gh_gcount 5.0
+# HELP gh_gsum help
 # TYPE gh_gsum gauge
 gh_gsum 7.0
 """, generate_latest(self.registry))
Repository: canonical/operator
Pull request #590 (2021-08-24 21:44:50)

Fix Container.restart() accidentally operating on strings, add a testcase
My fault for writing patches first thing in the morning and not adding a test...


Patch:
diff --git a/ops/model.py b/ops/model.py
index 2bf1d8e..c89d026 100644
--- a/ops/model.py
+++ b/ops/model.py
@@ -1118,7 +1118,7 @@ class Container:
         if not service_names:
             raise TypeError('restart expected at least 1 argument, got 0')
 
-        for svc in self.get_services(service_names):
+        for svc in self.get_services(*service_names).values():
             if svc.is_running():
                 self._pebble.stop_services(svc.name)
         self._pebble.start_services(service_names)


Test patch:
diff --git a/test/test_model.py b/test/test_model.py
index 3f80664..9070d88 100755
--- a/test/test_model.py
+++ b/test/test_model.py
@@ -828,6 +828,24 @@ containers:
         with self.assertRaises(TypeError):
             self.container.start()
 
+    def test_restart(self):
+        two_services = [
+            self._make_service('foo', 'enabled', 'active'),
+            self._make_service('bar', 'disabled', 'inactive'),
+        ]
+        self.pebble.responses.append(two_services)
+        self.container.restart('foo')
+        self.pebble.responses.append(two_services)
+        self.container.restart('foo', 'bar')
+        self.assertEqual(self.pebble.requests, [
+            ('get_services', ('foo',)),
+            ('stop', 'foo'),
+            ('start', ('foo',)),
+            ('get_services', ('foo', 'bar')),
+            ('stop', 'foo'),
+            ('start', ('foo', 'bar',)),
+        ])
+
     def test_stop(self):
         self.container.stop('foo')
         self.container.stop('foo', 'bar')
Repository: canonical/operator
Pull request #771 (2022-06-07 20:51:08)

Improved error message for invalid storage key usage
Just trying to be more helpful to users.  Pretty self explanitory.

## Checklist

 - [x] Have any types changed? If so, have the type annotations been updated?
 - [x] If this code exposes model data, does it do so thoughtfully, in a way that aids understanding?

       We want to avoid simple passthrough of model data, without contextualization, where possible.

 - [x] Do error messages, if any, present charm authors or operators with enough information to solve the problem?

## Bug reference

@sed-i had this idea [on discourse](https://discourse.charmhub.io/t/operator-framework-1-5-0/6533/2)

## Changelog

- Incorrect storage access (via model.storages) now provides a more helpful message - e.g. "Did you mean x, or y?".



Patch:
diff --git a/ops/model.py b/ops/model.py
index 083311c..8425736 100644
--- a/ops/model.py
+++ b/ops/model.py
@@ -1139,6 +1139,10 @@ class StorageMapping(Mapping[str, List['Storage']]):
         return iter(self._storage_map)
 
     def __getitem__(self, storage_name: str) -> List['Storage']:
+        if storage_name not in self._storage_map:
+            meant = ', or '.join(['{!r}'.format(k) for k in self._storage_map.keys()])
+            raise KeyError(
+                'Storage {!r} not found. Did you mean {}?'.format(storage_name, meant))
         storage_list = self._storage_map[storage_name]
         if storage_list is None:
             storage_list = self._storage_map[storage_name] = []


Test patch:
diff --git a/test/test_model.py b/test/test_model.py
index 015d267..b672b84 100755
--- a/test/test_model.py
+++ b/test/test_model.py
@@ -690,7 +690,6 @@ class TestModel(unittest.TestCase):
         self.assertBackendCalls([])
 
     def test_storage(self):
-        # TODO: (jam) 2020-05-07 Harness doesn't yet expose storage-get issue #263
         meta = ops.charm.CharmMeta()
         meta.storages = {'disks': None, 'data': None}
         model = ops.model.Model(meta, ops.model._ModelBackend('myapp/0'))
@@ -716,6 +715,13 @@ class TestModel(unittest.TestCase):
         self.assertEqual(len(model.storages), 2)
         self.assertEqual(model.storages.keys(), meta.storages.keys())
         self.assertIn('disks', model.storages)
+        try:
+            model.storages['does-not-exist']
+        except KeyError as err:
+            assert 'Did you mean' in str(err), 'got wrong error message'
+        except Exception as err:
+            assert False, 'got wrong exception type: ' + str(err)
+
         test_cases = {
             0: {'name': 'disks', 'location': pathlib.Path('/var/srv/disks/0')},
             1: {'name': 'disks', 'location': pathlib.Path('/var/srv/disks/1')},
Repository: softwaremill/elasticmq
Pull request #513 (2021-07-27 07:39:00)

Changed way of reading tags without values
closing #511 


Patch:
diff --git a/rest/rest-sqs/src/main/scala/org/elasticmq/rest/sqs/TagsModule.scala b/rest/rest-sqs/src/main/scala/org/elasticmq/rest/sqs/TagsModule.scala
index e6b07cf9..2574703d 100644
--- a/rest/rest-sqs/src/main/scala/org/elasticmq/rest/sqs/TagsModule.scala
+++ b/rest/rest-sqs/src/main/scala/org/elasticmq/rest/sqs/TagsModule.scala
@@ -16,7 +16,10 @@ trait TagsModule {
         parameters.get(tagPrefix + suffix + ".Key") match {
           case None => acc
           case Some(an) =>
-            collect(suffix + 1, acc + (an -> parameters(tagPrefix + suffix + ".Value")))
+            parameters.get(tagPrefix + suffix + ".Value") match {
+              case None => collect(suffix + 1, acc + (an -> ""))
+              case Some(tagValue) => collect(suffix + 1, acc + (an -> tagValue))
+            }
         }
       }
 
@@ -45,4 +48,4 @@ trait TagsModule {
       </Tag>)
     }
   }
-}
+}
\ No newline at end of file


Test patch:
diff --git a/rest/rest-sqs/src/test/scala/org/elasticmq/rest/sqs/TagsModuleTest.scala b/rest/rest-sqs/src/test/scala/org/elasticmq/rest/sqs/TagsModuleTest.scala
new file mode 100644
index 00000000..4d5dde83
--- /dev/null
+++ b/rest/rest-sqs/src/test/scala/org/elasticmq/rest/sqs/TagsModuleTest.scala
@@ -0,0 +1,30 @@
+package org.elasticmq.rest.sqs
+
+import org.scalatest.flatspec.AnyFlatSpec
+import org.scalatest.matchers.should.Matchers
+
+class TagsModuleTest extends AnyFlatSpec with AttributesModule with Matchers {
+
+  "Key Value pair for tag" should "result in map with one entry " in {
+    val parameters = Map("Tag.1.Key" -> "Test", "Tag.1.Value" -> "2")
+    val tagsModule = new TagsModule {}
+    val tags = tagsModule.tagNameAndValuesReader.read(parameters)
+    tags shouldEqual Map("Test" -> "2")
+  }
+
+  "Two tags" should "result in two-entry map with correct relation" in {
+    val parameters = Map(
+      "Tag.1.Key" -> "Test-1", "Tag.1.Value" -> "1",
+      "Tag.2.Key" -> "Test-2", "Tag.2.Value" -> "2")
+    val tagsModule = new TagsModule {}
+    val tags = tagsModule.tagNameAndValuesReader.read(parameters)
+    tags shouldEqual Map("Test-1" -> "1", "Test-2" -> "2")
+  }
+
+  "Empty value for tag" should "be read as empty string" in {
+    val parameters = Map("Tag.1.Key" -> "Test")
+    val tagsModule = new TagsModule {}
+    val tags = tagsModule.tagNameAndValuesReader.read(parameters)
+    tags("Test") shouldEqual ""
+  }
+}
Repository: softwaremill/elasticmq
Pull request #677 (2022-04-19 12:06:01)

Queue ordering fix
After merging and releasing ask people from #673 if this solved their problem


Patch:
diff --git a/persistence/persistence-file/src/main/scala/org/elasticmq/persistence/file/QueueConfigUtil.scala b/persistence/persistence-file/src/main/scala/org/elasticmq/persistence/file/QueueConfigUtil.scala
index 72bb8373..09375f91 100644
--- a/persistence/persistence-file/src/main/scala/org/elasticmq/persistence/file/QueueConfigUtil.scala
+++ b/persistence/persistence-file/src/main/scala/org/elasticmq/persistence/file/QueueConfigUtil.scala
@@ -1,7 +1,7 @@
 package org.elasticmq.persistence.file
 
 import com.typesafe.config.{Config, ConfigFactory, ConfigObject, ConfigValue}
-import org.elasticmq.persistence.{CreateQueueMetadata, DeadLettersQueue}
+import org.elasticmq.persistence.{CreateQueueMetadata, DeadLettersQueue, QueueSorter}
 import org.joda.time.DateTime
 
 import java.io.File
@@ -43,7 +43,7 @@ object QueueConfigUtil {
 
     val now = new DateTime().toInstant.getMillis
 
-    queuesConfig.map { case (n, v) =>
+    val unsortedQueues = queuesConfig.map { case (n, v) =>
       val c = v.asInstanceOf[ConfigObject].toConfig
       val isFifo = getOptionalBoolean(c, "fifo").getOrElse(false)
       CreateQueueMetadata(
@@ -68,6 +68,7 @@ object QueueConfigUtil {
         tags = getOptionalTags(c, "tags")
       )
     }.toList
+    QueueSorter.sortCreateQueues(unsortedQueues)
   }
 
   private def addSuffixWhenFifoQueue(queueName: String, isFifo: Boolean): String = {


Test patch:
diff --git a/persistence/persistence-file/src/test/resources/expected-single-queue-config.conf b/persistence/persistence-file/src/test/resources/expected-single-queue-config.conf
index e030d270..851b3372 100644
--- a/persistence/persistence-file/src/test/resources/expected-single-queue-config.conf
+++ b/persistence/persistence-file/src/test/resources/expected-single-queue-config.conf
@@ -17,4 +17,8 @@ queues {
       tag1Key = tag1Value
     }
   }
+  dead {
+    created = 0,
+    lastModified = 0,
+  }
 }
\ No newline at end of file
diff --git a/persistence/persistence-file/src/test/scala/org/elasticmq/persistence/file/QueueConfigUtilTest.scala b/persistence/persistence-file/src/test/scala/org/elasticmq/persistence/file/QueueConfigUtilTest.scala
index f09fd7c8..56670d38 100644
--- a/persistence/persistence-file/src/test/scala/org/elasticmq/persistence/file/QueueConfigUtilTest.scala
+++ b/persistence/persistence-file/src/test/scala/org/elasticmq/persistence/file/QueueConfigUtilTest.scala
@@ -60,8 +60,10 @@ class QueueConfigUtilTest extends AnyFunSuite with Matchers with OptionValues {
       Some("messageTo"),
       Map("tag1Key" -> "tag1Value")
     )
-    persistedQueues.length shouldBe 1
-    persistedQueues.head shouldBe expectedQueue
+    val expectedDeadLetters = CreateQueueMetadata("dead")
+    persistedQueues.length shouldBe 2
+    persistedQueues.head shouldBe expectedDeadLetters
+    persistedQueues.last shouldBe expectedQueue
   }
 
   test("Persisted queues should take precedence over startup queues with same names") {