nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: caikit/caikit
Pull request #206 (2023-06-08 19:27:28)

Allow dataobject classes to inhert with the same sema…
…ntics as dataclasses


Patch:
diff --git a/caikit/core/data_model/dataobject.py b/caikit/core/data_model/dataobject.py
index 6dcc2cd4..00bc7750 100644
--- a/caikit/core/data_model/dataobject.py
+++ b/caikit/core/data_model/dataobject.py
@@ -381,4 +381,6 @@ def _has_dataclass_init(cls) -> bool:
     __annotations__ to the init function itself. This function uses that fact to
     detect if the class's __init__ function was generated by @dataclass
     """
-    return bool(getattr(cls.__init__, "__annotations__", None))
+    return bool(getattr(cls.__init__, "__annotations__", None)) and not any(
+        cls.__init__ is base.__init__ for base in cls.__bases__
+    )


Test patch:
diff --git a/tests/core/data_model/test_dataobject.py b/tests/core/data_model/test_dataobject.py
index 6dcefba2..4fd0ad4d 100644
--- a/tests/core/data_model/test_dataobject.py
+++ b/tests/core/data_model/test_dataobject.py
@@ -834,3 +834,45 @@ def test_dataobject_to_kwargs(temp_dpool):
 
     # `type_union_val` is set here rather than the `type_union_val_str_val` internal oneof field name
     assert kwargs == {"int_val": 1, "type_union_val": "foo", "bar_val": bar}
+
+
+def test_dataobject_inheritance(temp_dpool):
+    """Make sure that dataobject classes can inherit from each other in the same
+    way that dataclasses can
+    """
+
+    @dataobject
+    class Base(DataObjectBase):
+        foo: int
+        bar: int
+
+    @dataobject
+    class Derived(Base):
+        bar: str
+        baz: str
+
+    # Validate Base
+    desc = Base.get_proto_class().DESCRIPTOR
+    fld = desc.fields_by_name["foo"]  # To save typing
+    assert "foo" in desc.fields_by_name
+    assert "bar" in desc.fields_by_name
+    assert "baz" not in desc.fields_by_name
+    assert desc.fields_by_name["foo"].type == fld.TYPE_INT64
+    assert desc.fields_by_name["bar"].type == fld.TYPE_INT64
+    inst = Derived(1, 2)
+    assert inst.foo == 1
+    assert inst.bar == 2
+
+    # Validate Derived
+    desc = Derived.get_proto_class().DESCRIPTOR
+    fld = desc.fields_by_name["foo"]  # To save typing
+    assert "foo" in desc.fields_by_name
+    assert "bar" in desc.fields_by_name
+    assert "baz" in desc.fields_by_name
+    assert desc.fields_by_name["foo"].type == fld.TYPE_INT64
+    assert desc.fields_by_name["bar"].type == fld.TYPE_STRING
+    assert desc.fields_by_name["baz"].type == fld.TYPE_STRING
+    inst = Derived(1, "asdf", "qwer")
+    assert inst.foo == 1
+    assert inst.bar == "asdf"
+    assert inst.baz == "qwer"
Repository: caikit/caikit
Pull request #293 (2023-06-30 18:59:42)

🐛 Add back producers for producer priority
Closes: #292 

Removing the init since dataobject decorator should do init. The custom logic is not particularly needed here, also adding tests


Patch:
diff --git a/caikit/interfaces/common/data_model/producer.py b/caikit/interfaces/common/data_model/producer.py
index 167eff67..868de170 100644
--- a/caikit/interfaces/common/data_model/producer.py
+++ b/caikit/interfaces/common/data_model/producer.py
@@ -38,13 +38,4 @@ class ProducerPriority(DataObjectBase):
     data structure.
     """
 
-    elements: List[ProducerId]
-
-    def __init__(self, producers):
-        """Construct a new ProducerPriority
-
-        Args:
-            producers (list(ProducerId))
-        """
-        error.type_check_all("<COR01353088E>", ProducerId, producers=producers)
-        self.producers = producers
+    producers: List[ProducerId]


Test patch:
diff --git a/tests/interfaces/common/test_producer.py b/tests/interfaces/common/test_producer.py
new file mode 100644
index 00000000..559358fa
--- /dev/null
+++ b/tests/interfaces/common/test_producer.py
@@ -0,0 +1,43 @@
+# Copyright The Caikit Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for producer priority"""
+
+
+# Local
+from caikit.core.data_model import ProducerId
+from caikit.interfaces.common.data_model.producer import ProducerPriority
+
+## Setup #####################################################################
+PROD_ID_1 = ProducerId("foo", "1.2.3")
+PROD_ID_2 = ProducerId("bar", "1.2.3")
+
+## Tests #####################################################################
+
+
+def test_proto_roundtrip():
+    producer_priority = ProducerPriority(producers=[PROD_ID_1, PROD_ID_2])
+    producer_priority_roundtrip = ProducerPriority.from_proto(
+        producer_priority.to_proto()
+    )
+    assert producer_priority_roundtrip.producers[0] == PROD_ID_1
+    assert producer_priority_roundtrip.producers[1] == PROD_ID_2
+
+
+def test_json_roundtrip():
+    producer_priority = ProducerPriority(producers=[PROD_ID_1, PROD_ID_2])
+    producer_priority_roundtrip = ProducerPriority.from_json(
+        producer_priority.to_json()
+    )
+    assert producer_priority_roundtrip.producers[0] == PROD_ID_1
+    assert producer_priority_roundtrip.producers[1] == PROD_ID_2
Repository: caikit/caikit
Pull request #367 (2023-07-25 22:46:37)

🐛  No canceled after completed
Supports #332 

This PR fixes the bug where a training run in a `DestroyableThread` can move from `COMPLETED` -> `CANCELED`


Patch:
diff --git a/caikit/core/toolkit/destroyable_thread.py b/caikit/core/toolkit/destroyable_thread.py
index 34ac4ddb..7fb72eca 100644
--- a/caikit/core/toolkit/destroyable_thread.py
+++ b/caikit/core/toolkit/destroyable_thread.py
@@ -87,7 +87,7 @@ class DestroyableThread(threading.Thread, Destroyable):
 
     @property
     def canceled(self) -> bool:
-        return self.destroyed and self.__started
+        return self.destroyed and self.__started and not self.__ran
 
     @property
     def ran(self) -> bool:


Test patch:
diff --git a/tests/core/model_management/test_local_model_trainer.py b/tests/core/model_management/test_local_model_trainer.py
index 31ea55d2..2ef6eb17 100644
--- a/tests/core/model_management/test_local_model_trainer.py
+++ b/tests/core/model_management/test_local_model_trainer.py
@@ -20,7 +20,6 @@ import multiprocessing
 import os
 import tempfile
 import threading
-import time
 
 # Third Party
 import pytest
diff --git a/tests/core/toolkit/test_destroyable_process.py b/tests/core/toolkit/test_destroyable_process.py
index 10656cd5..46570b1a 100644
--- a/tests/core/toolkit/test_destroyable_process.py
+++ b/tests/core/toolkit/test_destroyable_process.py
@@ -54,6 +54,15 @@ def test_processes_can_return_results():
     assert not proc.threw
 
 
+def test_process_not_canceled_after_success():
+    proc = DestroyableProcess(lambda: None)
+    proc.start()
+    proc.join()
+    assert not proc.canceled
+    proc.destroy()
+    assert not proc.canceled
+
+
 def test_processes_can_be_set_to_not_return_results():
     expected = "test-any-result"
     proc = DestroyableProcess(lambda: expected, return_result=False)
diff --git a/tests/core/toolkit/test_destroyable_thread.py b/tests/core/toolkit/test_destroyable_thread.py
index 02692f73..388e0961 100644
--- a/tests/core/toolkit/test_destroyable_thread.py
+++ b/tests/core/toolkit/test_destroyable_thread.py
@@ -113,6 +113,15 @@ def test_threads_can_return_results():
     assert expected == thread.get_or_throw()
 
 
+def test_threads_not_canceled_after_success():
+    thread = DestroyableThread(lambda: None)
+    thread.start()
+    thread.join()
+    assert not thread.canceled
+    thread.destroy()
+    assert not thread.canceled
+
+
 def test_threads_can_throw():
     expected = ValueError("test-any-error")
Repository: caikit/caikit
Pull request #368 (2023-07-26 02:18:00)

HealthCheckOkResponse: Return an OK response from the health check
Signed-off-by: Gabe Goodhart <ghart@us.ibm.com>

with help from Micah Goodhart ;)


Patch:
diff --git a/caikit/runtime/http_server.py b/caikit/runtime/http_server.py
index 873c6f3c..c84406ef 100644
--- a/caikit/runtime/http_server.py
+++ b/caikit/runtime/http_server.py
@@ -29,6 +29,7 @@ import time
 
 # Third Party
 from fastapi import FastAPI, Request, Response
+from fastapi.responses import PlainTextResponse
 from grpc import StatusCode
 from sse_starlette import EventSourceResponse, ServerSentEvent
 import numpy as np
@@ -126,7 +127,9 @@ class RuntimeHTTPServer(RuntimeServerBase):
         self.package_name = inference_service.descriptor.full_name.rsplit(".", 1)[0]
 
         # Add the health endpoint
-        self.app.get(HEALTH_ENDPOINT)(self._health_check)
+        self.app.get(HEALTH_ENDPOINT, response_class=PlainTextResponse)(
+            self._health_check
+        )
 
         # Bind all routes to the server
         self._bind_routes(inference_service)
@@ -542,8 +545,9 @@ class RuntimeHTTPServer(RuntimeServerBase):
         return pydantic_model
 
     @staticmethod
-    def _health_check():
+    def _health_check() -> str:
         log.debug4("Server healthy")
+        return "OK"
 
 
 ## Main ########################################################################


Test patch:
diff --git a/tests/runtime/test_http_server.py b/tests/runtime/test_http_server.py
index 54355dc4..9731ee92 100644
--- a/tests/runtime/test_http_server.py
+++ b/tests/runtime/test_http_server.py
@@ -300,6 +300,15 @@ def test_inference_sample_task_throws_incorrect_input(sample_task_model_id):
         assert response.status_code == 400
 
 
+def test_health_check_ok():
+    """Make sure the health check returns OK"""
+    server = http_server.RuntimeHTTPServer()
+    with TestClient(server.app) as client:
+        response = client.get(http_server.HEALTH_ENDPOINT)
+        assert response.status_code == 200
+        assert response.text == "OK"
+
+
 def test_pydantic_wrapping_with_enums():
     """Check that the pydantic wrapping works on our data models when they have enums"""
     # The NLP GeneratedTextStreamResult data model contains enums
Repository: caikit/caikit
Pull request #542 (2023-10-23 18:39:25)

Fix GRPC server over Unix socket
<!--  Thanks for sending a pull request!  Here are some tips for you:
1. Make sure to read the Contributing Guide before submitting your PR: https://github.com/caikit/caikit/blob/main/CONTRIBUTING.md
2. If this PR closes another issue, add 'closes #<issue number>' somewhere in the PR summary. GitHub will automatically close that issue when this PR gets merged. Alternatively, adding 'refs #<issue number>' will not close the issue, but help provide the reviewer more context.-->

**What this PR does / why we need it**:
This PR updates the GRPCServer unix socket implementation to actually allow listening over unix sockets. Prior to this the server would always skip adding the unix socket even if the target directory existed.

**Special notes for your reviewer**:

**If applicable**:
- [ ] this PR contains documentation
- [ ] this PR contains unit tests
- [ ] this PR has been tested for backwards compatibility



Patch:
diff --git a/caikit/runtime/grpc_server.py b/caikit/runtime/grpc_server.py
index b7b38af9..ef572004 100644
--- a/caikit/runtime/grpc_server.py
+++ b/caikit/runtime/grpc_server.py
@@ -153,7 +153,7 @@ class RuntimeGRPCServer(RuntimeServerBase):
 
         # Listen on a unix socket as well for model mesh.
         if self.config.runtime.grpc.unix_socket_path and os.path.exists(
-            self.config.runtime.grpc.unix_socket_path
+            os.path.dirname(self.config.runtime.grpc.unix_socket_path)
         ):
             try:
                 self.server.add_insecure_port(


Test patch:
diff --git a/tests/runtime/test_grpc_server.py b/tests/runtime/test_grpc_server.py
index 0c5fa549..6b31fc9b 100644
--- a/tests/runtime/test_grpc_server.py
+++ b/tests/runtime/test_grpc_server.py
@@ -1283,6 +1283,25 @@ def test_construct_with_options(open_port, sample_train_service, sample_int_file
             assert context.value.code() == grpc.StatusCode.RESOURCE_EXHAUSTED
 
 
+def test_grpc_server_socket_listen():
+    """Make sure that the server correctly listen on a unix socket"""
+    with tempfile.TemporaryDirectory() as socket_dir:
+        with temp_config(
+            {"runtime": {"grpc": {"unix_socket_path": socket_dir + "/grpc.sock"}}},
+            "merge",
+        ):
+            with RuntimeGRPCServer():
+                stub = model_runtime_pb2_grpc.ModelRuntimeStub(
+                    grpc.insecure_channel(f"unix://{socket_dir}/grpc.sock")
+                )
+                runtime_status_request = model_runtime_pb2.RuntimeStatusRequest()
+                actual_response = stub.runtimeStatus(runtime_status_request)
+                assert (
+                    actual_response.status
+                    == model_runtime_pb2.RuntimeStatusResponse.READY
+                )
+
+
 # Test implementation details #########################
 @dataclass
 class KeyPair:
Repository: caikit/caikit
Pull request #625 (2023-12-20 17:41:45)

DoubleCountTasks: Don't re-add tasks from the class itself
Closes https://github.com/caikit/caikit/issues/624

**What this PR does / why we need it**:

Minor cleanup that I happened to find while poking around!

**Special notes for your reviewer**:

**If applicable**:
- [ ] this PR contains documentation
- [x] this PR contains unit tests
- [x] this PR has been tested for backwards compatibility



Patch:
diff --git a/caikit/core/modules/decorator.py b/caikit/core/modules/decorator.py
index 2764e202..ca2d5007 100644
--- a/caikit/core/modules/decorator.py
+++ b/caikit/core/modules/decorator.py
@@ -227,7 +227,7 @@ def module(
         tasks_in_hierarchy = []
 
         for class_ in cls_.mro():
-            if hasattr(class_, "_TASK_CLASSES"):
+            if hasattr(class_, "_TASK_CLASSES") and class_ is not cls_:
                 tasks_in_hierarchy.extend(class_._TASK_CLASSES)
 
         if tasks_in_hierarchy:


Test patch:
diff --git a/tests/core/test_task.py b/tests/core/test_task.py
index 13082193..27c7e201 100644
--- a/tests/core/test_task.py
+++ b/tests/core/test_task.py
@@ -162,6 +162,9 @@ def test_tasks_added_from_parent_and_child_module():
     for t in [FirstTask, SecondTask, ThirdTask]:
         assert t in MultiTaskChildModule.tasks
 
+    # Make sure no tasks are double-counted
+    assert len(MultiTaskChildModule.tasks) == len(MultiTaskChildModule._TASK_CLASSES)
+
 
 def test_task_is_not_required_for_modules():
     @caikit.core.modules.module(id=str(uuid.uuid4()), name="Stuff", version="0.0.1")