nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: vshn/k8up
Pull request #174 (2020-12-03 07:41:11)

Adjust the exclusivity of the restore and archive job
Restores aren't exclusive in upstream Restic:
https://github.com/restic/restic/blob/master/cmd/restic/cmd_restore.go#L105

The exclusivity of the various job types should match what's defined in
the upstream Restic project.

Resolves: #173


Patch:
diff --git a/executor/archive.go b/executor/archive.go
index 5a1be2fc..0c438cea 100644
--- a/executor/archive.go
+++ b/executor/archive.go
@@ -56,11 +56,6 @@ func (a *ArchiveExecutor) Execute() error {
 	return nil
 }
 
-// Exclusive should return true for jobs that can't run while other jobs run.
-func (*ArchiveExecutor) Exclusive() bool {
-	return true
-}
-
 func (a *ArchiveExecutor) startArchive(job *batchv1.Job, archive *k8upv1alpha1.Archive) {
 	name := types.NamespacedName{Namespace: a.Obj.GetMetaObject().GetNamespace(), Name: a.Obj.GetMetaObject().GetName()}
 	a.setArchiveCallback(name, archive)
diff --git a/executor/restore.go b/executor/restore.go
index ffd4ce37..ac192a81 100644
--- a/executor/restore.go
+++ b/executor/restore.go
@@ -51,11 +51,6 @@ func (r *RestoreExecutor) Execute() error {
 	return nil
 }
 
-// Exclusive should return true for jobs that can't run while other jobs run.
-func (r *RestoreExecutor) Exclusive() bool {
-	return true
-}
-
 func (r *RestoreExecutor) startRestore(restore *k8upv1alpha1.Restore) {
 	name := types.NamespacedName{Namespace: r.Obj.GetMetaObject().GetNamespace(), Name: r.Obj.GetMetaObject().GetName()}
 	r.setRestoreCallback(name, restore)


Test patch:
diff --git a/executor/restore_test.go b/executor/restore_test.go
index da4f08db..76762781 100644
--- a/executor/restore_test.go
+++ b/executor/restore_test.go
@@ -276,7 +276,7 @@ func jobMatcher(restoreType string, additionalArgs []string, env Elements, volum
 		"ObjectMeta": MatchFields(IgnoreExtras, Fields{
 			"Labels": MatchAllKeys(Keys{
 				"k8upjob":           Equal("true"),
-				"k8upjob/exclusive": Equal("true"),
+				"k8upjob/exclusive": Equal("false"),
 			}),
 		}),
 		"Spec": MatchFields(IgnoreExtras, Fields{
Repository: quora/pyanalyze
Pull request #508 (2022-03-29 01:04:47)

fix conditionally declared module-scope variables
Followup from #505



Patch:
diff --git a/pyanalyze/name_check_visitor.py b/pyanalyze/name_check_visitor.py
index 14a05a1..0bf4bfb 100644
--- a/pyanalyze/name_check_visitor.py
+++ b/pyanalyze/name_check_visitor.py
@@ -1381,7 +1381,7 @@ class NameCheckVisitor(node_visitor.ReplacingNodeVisitor):
                 self.reexport_tracker.record_exported_attribute(
                     self.module.__name__, varname
                 )
-            if varname in current_scope:
+            if varname in current_scope.variables:
                 value, _ = current_scope.get_local(varname, lookup_node, self.state)
                 return value, EMPTY_ORIGIN
         if scope_type == ScopeType.class_scope:


Test patch:
diff --git a/pyanalyze/test_name_check_visitor.py b/pyanalyze/test_name_check_visitor.py
index 6f83f32..f785448 100644
--- a/pyanalyze/test_name_check_visitor.py
+++ b/pyanalyze/test_name_check_visitor.py
@@ -1892,6 +1892,15 @@ class TestAnnAssign(TestNameCheckVisitorBase):
 
             j: int = 0  # E: already_declared
 
+    @assert_passes()
+    def test_module_scope(self):
+        x: int = 3
+        assert_is_value(x, TypedValue(int))
+
+        if __name__ == "__main__":
+            y: int = 3
+            assert_is_value(y, TypedValue(int))
+
 
 class TestWhile(TestNameCheckVisitorBase):
     @assert_passes()
Repository: quora/pyanalyze
Pull request #541 (2022-09-02 02:48:10)

Preserve `Annotated` annotations on access to methods of literals


Patch:
diff --git a/docs/changelog.md b/docs/changelog.md
index a687f51..25bd9a7 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -2,6 +2,8 @@
 
 ## Unreleased
 
+- Preserve `Annotated` annotations on access to methods of
+  literals (#541)
 - `allow_call` callables are now also called if the arguments
   are literals wrapped in `Annotated` (#540)
 - Support Python 3.11 (#537)
diff --git a/pyanalyze/attributes.py b/pyanalyze/attributes.py
index eb23a44..786deeb 100644
--- a/pyanalyze/attributes.py
+++ b/pyanalyze/attributes.py
@@ -348,6 +348,16 @@ def _get_attribute_from_known(obj: object, ctx: AttrContext) -> Value:
         return GenericValue(dict, [TypedValue(str), TypedValue(types.ModuleType)])
 
     result, _, _ = _get_attribute_from_mro(obj, ctx, on_class=True)
+    if (
+        isinstance(result, KnownValue)
+        and (
+            safe_isinstance(result.val, types.MethodType)
+            or safe_isinstance(result.val, types.BuiltinFunctionType)
+            and result.val.__self__ is obj
+        )
+        and isinstance(ctx.root_value, AnnotatedValue)
+    ):
+        result = UnboundMethodValue(ctx.attr, ctx.root_composite)
     if safe_isinstance(obj, type):
         result = set_self(result, TypedValue(obj))
     if isinstance(obj, (types.ModuleType, type)):


Test patch:
diff --git a/pyanalyze/test_attributes.py b/pyanalyze/test_attributes.py
index 7ce4c2b..8b748a7 100644
--- a/pyanalyze/test_attributes.py
+++ b/pyanalyze/test_attributes.py
@@ -4,8 +4,10 @@ from typing import Dict, Union
 from .test_name_check_visitor import TestNameCheckVisitorBase
 from .test_node_visitor import assert_passes, only_before
 from .value import (
+    AnnotatedValue,
     AnySource,
     AnyValue,
+    UnboundMethodValue,
     assert_is_value,
     GenericValue,
     KnownValue,
@@ -170,6 +172,31 @@ class TestAttributes(TestNameCheckVisitorBase):
                 x.attr, MultiValuedValue([TypedValue(int), TypedValue(str)])
             )
 
+    @assert_passes()
+    def test_annotated_known(self):
+        from typing_extensions import Annotated, Literal
+        from pyanalyze.extensions import LiteralOnly
+        from pyanalyze.stacked_scopes import Composite, VarnameWithOrigin
+        from pyanalyze.value import CustomCheckExtension
+        from qcore.testing import Anything
+
+        origin = VarnameWithOrigin("encoding", Anything)  # E: incompatible_argument
+
+        def capybara():
+            encoding: Annotated[Literal["ascii"], LiteralOnly()] = "ascii"
+            assert_is_value(
+                encoding.encode,
+                UnboundMethodValue(
+                    "encode",
+                    Composite(
+                        AnnotatedValue(
+                            KnownValue("ascii"), [CustomCheckExtension(LiteralOnly())]
+                        ),
+                        origin,
+                    ),
+                ),
+            )
+
     @assert_passes()
     def test_optional_operation(self):
         from typing import Optional
Repository: quora/pyanalyze
Pull request #548 (2022-11-05 22:59:50)

Fix false positive error when calling an UnboundMethodValue


Patch:
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..cbd920f
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,10 @@
+version: 2
+updates:
+  - package-ecosystem: "github-actions"
+    directory: "/"
+    schedule:
+      interval: "weekly"
+  - package-ecosystem: "pip"
+    directory: "/"
+    schedule:
+      interval: "weekly"
diff --git a/docs/changelog.md b/docs/changelog.md
index 25bd9a7..6e13df4 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -2,6 +2,7 @@
 
 ## Unreleased
 
+- Fix false positive error certain method calls on literals (#548)
 - Preserve `Annotated` annotations on access to methods of
   literals (#541)
 - `allow_call` callables are now also called if the arguments
diff --git a/pyanalyze/value.py b/pyanalyze/value.py
index 5873722..0203e58 100644
--- a/pyanalyze/value.py
+++ b/pyanalyze/value.py
@@ -21,7 +21,6 @@ these subclasses and some related utilities.
 
 import collections.abc
 import enum
-import inspect
 import textwrap
 from collections import deque, OrderedDict
 from dataclasses import dataclass, field, InitVar
@@ -544,17 +543,20 @@ class UnboundMethodValue(Value):
     def get_method(self) -> Optional[Any]:
         """Return the runtime callable for this ``UnboundMethodValue``, or
         None if it cannot be found."""
+        root = self.composite.value
+        if isinstance(root, AnnotatedValue):
+            root = root.value
+        if isinstance(root, KnownValue):
+            typ = root.val
+        else:
+            typ = root.get_type()
         try:
-            typ = self.composite.value.get_type()
             method = getattr(typ, self.attr_name)
             if self.secondary_attr_name is not None:
                 method = getattr(method, self.secondary_attr_name)
-            # don't use unbound methods in py2
-            if inspect.ismethod(method) and method.__self__ is None:
-                method = method.__func__
-            return method
         except AttributeError:
             return None
+        return method
 
     def is_type(self, typ: type) -> bool:
         return isinstance(self.get_method(), typ)


Test patch:
diff --git a/pyanalyze/test_attributes.py b/pyanalyze/test_attributes.py
index 4b099b3..05f1d4d 100644
--- a/pyanalyze/test_attributes.py
+++ b/pyanalyze/test_attributes.py
@@ -351,3 +351,15 @@ class TestHasAttrExtension(TestNameCheckVisitorBase):
             if hasattr(x, "a") and hasattr(x, "b"):
                 assert_is_value(x.a, AnyValue(AnySource.inference))
                 assert_is_value(x.b, AnyValue(AnySource.inference))
+
+    @assert_passes()
+    def test_hasattr_plus_call(self):
+        class X:
+            @classmethod
+            def types(cls):
+                return []
+
+        def capybara(x: X) -> None:
+            cls = X
+            if hasattr(cls, "types"):  # E: value_always_true
+                assert_is_value(cls.types(), AnyValue(AnySource.unannotated))
Repository: quora/pyanalyze
Pull request #557 (2022-11-06 01:48:21)

async def returns Coroutine, not Awaitable


Patch:
diff --git a/docs/changelog.md b/docs/changelog.md
index 61b7e0e..9249ba5 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -2,6 +2,8 @@
 
 ## Unreleased
 
+- Infer `async def` functions as returning `Coroutine`, not
+  `Awaitable` (#557)
 - Drop support for Python 3.6 (#554)
 - Require `typeshed_client>=2.1.0`. Older versions will throw
   false-positive errors around context managers when
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 88f8e90..c6b7c43 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1,3 +1,3 @@
-myst-parser==0.16.1
+myst-parser==0.18.1
 Sphinx==4.5.0
 pygments==2.13.0
diff --git a/pyanalyze/functions.py b/pyanalyze/functions.py
index 346fadd..95c1beb 100644
--- a/pyanalyze/functions.py
+++ b/pyanalyze/functions.py
@@ -449,7 +449,10 @@ def compute_value_of_function(
             if visitor.is_generator:
                 break
         if not visitor.is_generator:
-            result = GenericValue(collections.abc.Awaitable, [result])
+            result = GenericValue(
+                collections.abc.Coroutine,
+                [AnyValue(AnySource.inference), AnyValue(AnySource.inference), result],
+            )
     sig = Signature.make(
         [param_info.param for param_info in info.params],
         result,
diff --git a/requirements.txt b/requirements.txt
index c45a6fd..99577c0 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,7 +8,7 @@ typing_inspect>=0.5.0
 typing_extensions>=4.1.1
 aenum>=2.2.3
 codemod
-myst-parser==0.15.1
+myst-parser==0.18.1
 Sphinx==4.2.0
 black==22.10.0
 flake8==5.0.4


Test patch:
diff --git a/pyanalyze/test_functions.py b/pyanalyze/test_functions.py
index ffad7ad..1987657 100644
--- a/pyanalyze/test_functions.py
+++ b/pyanalyze/test_functions.py
@@ -58,7 +58,15 @@ class TestNestedFunction(TestNameCheckVisitorBase):
                 return 1
 
             assert_is_value(
-                nested(), GenericValue(collections.abc.Awaitable, [TypedValue(int)])
+                nested(),
+                GenericValue(
+                    collections.abc.Coroutine,
+                    [
+                        AnyValue(AnySource.inference),
+                        AnyValue(AnySource.inference),
+                        TypedValue(int),
+                    ],
+                ),
             )
 
     @assert_passes()
Repository: quora/pyanalyze
Pull request #620 (2023-05-06 00:38:05)

Fix Self handling for builtin methods


Patch:
diff --git a/pyanalyze/typeshed.py b/pyanalyze/typeshed.py
index 68fd000..f783a1c 100644
--- a/pyanalyze/typeshed.py
+++ b/pyanalyze/typeshed.py
@@ -231,7 +231,7 @@ class TypeshedFinder:
                 sig = self._get_sig_from_method_descriptor(method, allow_call)
                 if sig is None:
                     return None
-                bound = make_bound_method(sig, Composite(KnownValue(obj.__self__)))
+                bound = make_bound_method(sig, Composite(TypedValue(obj.__self__)))
                 if bound is None:
                     return None
                 return bound.get_signature(ctx=self.ctx)


Test patch:
diff --git a/pyanalyze/test_typeshed.py b/pyanalyze/test_typeshed.py
index 135528f..8c3ca58 100644
--- a/pyanalyze/test_typeshed.py
+++ b/pyanalyze/test_typeshed.py
@@ -154,6 +154,15 @@ class TestTypeshedClient(TestNameCheckVisitorBase):
                 ),
             )
 
+    @assert_passes()
+    def test_datetime(self):
+        from datetime import datetime
+        from typing_extensions import assert_type
+
+        def capybara(i: int):
+            dt = datetime.fromtimestamp(i)
+            assert_type(dt, datetime)
+
     def test_has_stubs(self) -> None:
         tsf = TypeshedFinder(Checker(), verbose=True)
         assert tsf.has_stubs(object)
Repository: quora/pyanalyze
Pull request #624 (2023-05-12 17:28:19)

Avoid false positives on generic aliases with nested classes


Patch:
diff --git a/docs/changelog.md b/docs/changelog.md
index 7d04b1d..56e3cc1 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -1,5 +1,10 @@
 # Changelog
 
+## Unreleased
+
+- Fix false positive error when annotations refer to classes defined
+  inside functions (#624)
+
 ## Version 0.10.0 (May 10, 2023)
 
 - Infer the signature for built-in static methods, such as `dict.fromkeys` (#619)
diff --git a/pyanalyze/name_check_visitor.py b/pyanalyze/name_check_visitor.py
index 5995f36..0b8009a 100644
--- a/pyanalyze/name_check_visitor.py
+++ b/pyanalyze/name_check_visitor.py
@@ -225,6 +225,13 @@ except ImportError:
         pass
 
 
+try:
+    from types import GenericAlias
+except ImportError:
+    # 3.8 and lower
+    GenericAlias = None
+
+
 T = TypeVar("T")
 U = TypeVar("U")
 AwaitableValue = GenericValue(collections.abc.Awaitable, [TypeVarValue(T)])
@@ -4467,6 +4474,17 @@ class NameCheckVisitor(node_visitor.ReplacingNodeVisitor):
                         return_value = self.check_call(
                             node.value, cgi, [index_composite], allow_call=True
                         )
+                        # Special case to avoid "Unrecognized annotation types.GenericAlias" later;
+                        # ideally we'd be more precise.
+                        if GenericAlias is not None and return_value == TypedValue(
+                            GenericAlias
+                        ):
+                            return_value = self.check_call(
+                                node.value,
+                                cgi,
+                                [Composite(KnownValue(Any))],
+                                allow_call=True,
+                            )
 
                 if (
                     self._should_use_varname_value(return_value)


Test patch:
diff --git a/pyanalyze/test_annotations.py b/pyanalyze/test_annotations.py
index fe7338c..e08fe36 100644
--- a/pyanalyze/test_annotations.py
+++ b/pyanalyze/test_annotations.py
@@ -705,6 +705,19 @@ class TestAnnotated(TestNameCheckVisitorBase):
                 ),
             )
 
+    @skip_before((3, 9))
+    @assert_passes()
+    def test_genericalias_nested_class(self):
+        def capybara():
+            class Base:
+                pass
+
+            class Child:
+                attrs: list[Base]
+
+            # Ideally should not be Any, but this is better than throwing a false positive error.
+            assert_is_value(Child().attrs, AnyValue(AnySource.from_another))
+
 
 class TestCallable(TestNameCheckVisitorBase):
     @assert_passes()
Repository: quora/pyanalyze
Pull request #665 (2023-08-09 23:09:20)

Infer constructor for Pydantic models


Patch:
diff --git a/docs/changelog.md b/docs/changelog.md
index 0543d3f..b1722b7 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -2,6 +2,8 @@
 
 ## Unreleased
 
+- Support classes that set a `__signature__` attribute to
+  define their constructor signature (such as Pydantic models) (#665)
 - Handle mangling of private attribute names (#658)
 - Declare support for Python 3.12. Not all new features in
   Python 3.12 are supported yet. (#656)
diff --git a/pyanalyze/arg_spec.py b/pyanalyze/arg_spec.py
index 2b7d2d1..13fbcf3 100644
--- a/pyanalyze/arg_spec.py
+++ b/pyanalyze/arg_spec.py
@@ -112,6 +112,8 @@ MethodWrapperType = type(object().__str__)
 
 _ENUM_CALL = enum.Enum.__call__.__func__
 
+_SELF_PARAM = inspect.Parameter("__self", inspect.Parameter.POSITIONAL_ONLY)
+
 
 @used  # exposed as an API
 @contextlib.contextmanager
@@ -809,9 +811,20 @@ class ArgSpecCache:
                 if isinstance(override, inspect.Signature):
                     inspect_sig = override
                     constructor = None
+                elif (
+                    override is None
+                    and hasattr_static(obj, "__signature__")
+                    and safe_isinstance(obj.__signature__, inspect.Signature)
+                ):
+                    # Pydantic classes set a static __signature__ field
+                    inspect_sig = obj.__signature__.replace(
+                        parameters=[_SELF_PARAM, *obj.__signature__.parameters.values()]
+                    )
+                    constructor = obj
                 else:
                     if override is not None:
                         constructor = override
+
                     # We pick __new__ if it is implemented as a Python function only;
                     # if we picked it whenever it was overridden we'd get too many C
                     # types that have a meaningless __new__ signature. Typeshed


Test patch:
diff --git a/pyanalyze/test_arg_spec.py b/pyanalyze/test_arg_spec.py
index 43ea208..2c70b41 100644
--- a/pyanalyze/test_arg_spec.py
+++ b/pyanalyze/test_arg_spec.py
@@ -364,6 +364,20 @@ class TestClassInstantiation(TestNameCheckVisitorBase):
             Capybara(3)  # E: incompatible_argument
             Capybara(pathlib.Path("x"))
 
+    @assert_passes()
+    def test_dunder_signature(self):
+        import inspect
+
+        class Cls:
+            __signature__ = inspect.Signature(
+                [inspect.Parameter("x", inspect.Parameter.KEYWORD_ONLY)]
+            )
+
+        def capybara():
+            assert_is_value(Cls(x=3), TypedValue(Cls))
+            Cls()  # E: incompatible_call
+            Cls(1)  # E: incompatible_call
+
 
 class TestFunctionsSafeToCall(TestNameCheckVisitorBase):
     @assert_passes()
Repository: quora/pyanalyze
Pull request #701 (2023-10-18 23:20:42)

Fix bug in SequenceValue / KnownValue interaction


Patch:
diff --git a/docs/changelog.md b/docs/changelog.md
index 44bdd4b..441efe6 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -1,5 +1,10 @@
 # Changelog
 
+## Unreleased
+
+- Fix bug in type compatibility check between known-length sequence
+  types and literal values (#701)
+
 ## Version 0.11.0 (October 3, 2023)
 
 - Partial support for PEP 695-style type aliases. Scoping changes
diff --git a/pyanalyze/value.py b/pyanalyze/value.py
index 6b6a484..433e1a8 100644
--- a/pyanalyze/value.py
+++ b/pyanalyze/value.py
@@ -1057,6 +1057,7 @@ class SequenceValue(GenericValue):
             return SequenceValue(typ, members)
 
     def can_assign(self, other: Value, ctx: CanAssignContext) -> CanAssign:
+        other = replace_known_sequence_value(other)
         if isinstance(other, SequenceValue):
             can_assign = self.get_type_object(ctx).can_assign(self, other, ctx)
             if isinstance(can_assign, CanAssignError):


Test patch:
diff --git a/pyanalyze/test_value.py b/pyanalyze/test_value.py
index a2e20d4..6569331 100644
--- a/pyanalyze/test_value.py
+++ b/pyanalyze/test_value.py
@@ -238,6 +238,10 @@ def test_sequence_value() -> None:
         ),
     )
 
+    assert_can_assign(val, KnownValue((1, "x")))
+    assert_cannot_assign(val, KnownValue((1, 2)))
+    assert_cannot_assign(val, KnownValue((1, "x", "y")))
+
     assert str(val) == "tuple[int, str]"
     assert str(value.SequenceValue(tuple, [(False, TypedValue(int))])) == "tuple[int]"
     assert (
Repository: networknt/json-schema-validator
Pull request #69 (2018-03-03 02:39:26)

Only apply required validator to objects
The spec for `require` say

>  An object instance is valid against this keyword if every item in the array is the name of a property in the instance.

`require` shouldn't be applied to non-objects.


Patch:
diff --git a/src/main/java/com/networknt/schema/RequiredValidator.java b/src/main/java/com/networknt/schema/RequiredValidator.java
index e77e7e5..4d092c7 100644
--- a/src/main/java/com/networknt/schema/RequiredValidator.java
+++ b/src/main/java/com/networknt/schema/RequiredValidator.java
@@ -35,9 +35,8 @@ public class RequiredValidator extends BaseJsonValidator implements JsonValidato
 
         super(schemaPath, schemaNode, parentSchema, ValidatorTypeCode.REQUIRED, validationContext);
         if (schemaNode.isArray()) {
-            int size = schemaNode.size();
-            for (int i = 0; i < size; i++) {
-                fieldNames.add(schemaNode.get(i).asText());
+            for (JsonNode fieldNme : schemaNode) {
+                fieldNames.add(fieldNme.asText());
             }
         }
 
@@ -47,6 +46,10 @@ public class RequiredValidator extends BaseJsonValidator implements JsonValidato
     public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String at) {
         debug(logger, node, rootNode, at);
 
+        if (!node.isObject()) {
+            return Collections.emptySet();
+        }
+
         Set<ValidationMessage> errors = new LinkedHashSet<ValidationMessage>();
 
         for (String fieldName : fieldNames) {


Test patch:
diff --git a/src/test/resources/tests/required.json b/src/test/resources/tests/required.json
index 612f73f..5999cb1 100644
--- a/src/test/resources/tests/required.json
+++ b/src/test/resources/tests/required.json
@@ -35,5 +35,18 @@
                 "valid": true
             }
         ]
+    },
+    {
+        "description": "required validation on non-object",
+        "schema": {
+            "required": ["foo"]
+        },
+        "tests": [
+            {
+                "description": "required not applied on null",
+                "data": null,
+                "valid": true
+            }
+        ]
     }
 ]