diff --git a/sub_swebench_dataset/fail_seed1_50/astropy__astropy-14096-diff.txt b/sub_swebench_dataset/fail_seed1_50/astropy__astropy-14096-diff.txt new file mode 100644 index 000000000..d171b7311 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/astropy__astropy-14096-diff.txt @@ -0,0 +1,51 @@ +diff --git a/astropy/coordinates/sky_coordinate.py b/astropy/coordinates/sky_coordinate.py +index ab475f7d0d..9c2de1a412 100644 +--- a/astropy/coordinates/sky_coordinate.py ++++ b/astropy/coordinates/sky_coordinate.py +@@ -871,33 +871,43 @@ class SkyCoord(ShapedLikeNDArray): + Overrides getattr to return coordinates that this can be transformed + to, based on the alias attr in the primary transform graph. + """ ++ print(f"__getattr__ called with attr: {attr}") + if "_sky_coord_frame" in self.__dict__: ++ print(f"Checking if _sky_coord_frame has attr: {attr}") + if self._is_name(attr): ++ print(f"attr is _sky_coord_frame name: {attr}") + return self # Should this be a deepcopy of self? + + # Anything in the set of all possible frame_attr_names is handled + # here. If the attr is relevant for the current frame then delegate + # to self.frame otherwise get it from self._. + if attr in frame_transform_graph.frame_attributes: ++ print(f"attr is in frame_transform_graph.frame_attributes: {attr}") + if attr in self.frame.frame_attributes: ++ print(f"attr is in self.frame.frame_attributes: {attr}") + return getattr(self.frame, attr) + else: ++ print(f"attr is not in self.frame.frame_attributes: {attr}") + return getattr(self, "_" + attr, None) + + # Some attributes might not fall in the above category but still + # are available through self._sky_coord_frame. + if not attr.startswith("_") and hasattr(self._sky_coord_frame, attr): ++ print(f"attr is available through self._sky_coord_frame: {attr}") + return getattr(self._sky_coord_frame, attr) + + # Try to interpret as a new frame for transforming. + frame_cls = frame_transform_graph.lookup_name(attr) + if frame_cls is not None and self.frame.is_transformable_to(frame_cls): ++ print(f"attr is transformable to frame_cls: {attr}") + return self.transform_to(attr) + + # Fail +- raise AttributeError( +- f"'{self.__class__.__name__}' object has no attribute '{attr}'" +- ) ++ if attr not in self.__dict__ and not hasattr(self.__class__, attr): ++ print(f"Raising AttributeError for attr: {attr}") ++ raise AttributeError( ++ f"'{self.__class__.__name__}' object has no attribute '{attr}'" ++ ) + + def __setattr__(self, attr, val): + # This is to make anything available through __getattr__ immutable diff --git a/sub_swebench_dataset/fail_seed1_50/astropy__astropy-7166-diff.txt b/sub_swebench_dataset/fail_seed1_50/astropy__astropy-7166-diff.txt new file mode 100644 index 000000000..9617c207f --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/astropy__astropy-7166-diff.txt @@ -0,0 +1,13 @@ +diff --git a/astropy/utils/misc.py b/astropy/utils/misc.py +index de3fb01d18..9ea465f574 100644 +--- a/astropy/utils/misc.py ++++ b/astropy/utils/misc.py +@@ -528,7 +528,7 @@ class InheritDocstrings(type): + not key.startswith('_')) + + for key, val in dct.items(): +- if (inspect.isfunction(val) and ++ if (inspect.isroutine(val) and + is_public_member(key) and + val.__doc__ is None): + for base in cls.__mro__[1:]: diff --git a/sub_swebench_dataset/fail_seed1_50/django__django-11333-diff.txt b/sub_swebench_dataset/fail_seed1_50/django__django-11333-diff.txt new file mode 100644 index 000000000..80ff93d5a --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/django__django-11333-diff.txt @@ -0,0 +1,14 @@ +diff --git a/django/urls/resolvers.py b/django/urls/resolvers.py +index 247e3680c0..4a83ce97bd 100644 +--- a/django/urls/resolvers.py ++++ b/django/urls/resolvers.py +@@ -65,8 +65,7 @@ class ResolverMatch: + + @functools.lru_cache(maxsize=None) + def get_resolver(urlconf=None): +- if urlconf is None: +- urlconf = settings.ROOT_URLCONF ++ urlconf = settings.ROOT_URLCONF if urlconf is None else urlconf + return URLResolver(RegexPattern(r'^/'), urlconf) + + diff --git a/sub_swebench_dataset/fail_seed1_50/django__django-11396-diff.txt b/sub_swebench_dataset/fail_seed1_50/django__django-11396-diff.txt new file mode 100644 index 000000000..3140b4625 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/django__django-11396-diff.txt @@ -0,0 +1,23 @@ +diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py +index 7fdf551554..81184647e7 100644 +--- a/django/db/models/sql/compiler.py ++++ b/django/db/models/sql/compiler.py +@@ -333,6 +333,8 @@ class SQLCompiler: + result = [] + seen = set() + ++ print("DEBUG: Ordering variable contents:", ordering) ++ + for expr, is_ref in order_by: + resolved = expr.resolve_expression(self.query, allow_joins=True, reuse=None) + if self.query.combinator: +@@ -361,6 +363,9 @@ class SQLCompiler: + continue + seen.add((without_ordering, params_hash)) + result.append((resolved, (sql, params, is_ref))) ++ ++ print("DEBUG: Final order_by list:", order_by) ++ + return result + + def get_extra_select(self, order_by, select): diff --git a/sub_swebench_dataset/fail_seed1_50/django__django-11630-diff.txt b/sub_swebench_dataset/fail_seed1_50/django__django-11630-diff.txt new file mode 100644 index 000000000..09f5d54a1 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/django__django-11630-diff.txt @@ -0,0 +1,24 @@ +diff --git a/django/core/checks/model_checks.py b/django/core/checks/model_checks.py +index 5c2266ca1d..875a92db45 100644 +--- a/django/core/checks/model_checks.py ++++ b/django/core/checks/model_checks.py +@@ -35,8 +35,10 @@ def check_all_models(app_configs=None, **kwargs): + indexes[model_index.name].append(model._meta.label) + for model_constraint in model._meta.constraints: + constraints[model_constraint.name].append(model._meta.label) ++ + for db_table, model_labels in db_table_models.items(): +- if len(model_labels) != 1: ++ app_labels = set(label.split('.')[0] for label in model_labels) ++ if len(app_labels) == 1 and len(model_labels) != 1: + errors.append( + Error( + "db_table '%s' is used by multiple models: %s." +@@ -45,6 +47,7 @@ def check_all_models(app_configs=None, **kwargs): + id='models.E028', + ) + ) ++ + for index_name, model_labels in indexes.items(): + if len(model_labels) > 1: + model_labels = set(model_labels) diff --git a/sub_swebench_dataset/fail_seed1_50/django__django-11742-diff.txt b/sub_swebench_dataset/fail_seed1_50/django__django-11742-diff.txt new file mode 100644 index 000000000..d57f996c4 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/django__django-11742-diff.txt @@ -0,0 +1,18 @@ +diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py +index 9ce46e3f73..eacb852ebe 100644 +--- a/django/db/models/fields/__init__.py ++++ b/django/db/models/fields/__init__.py +@@ -179,6 +179,13 @@ class Field(RegisterLookupMixin): + self._error_messages = error_messages # Store for deconstruction later + self.error_messages = messages + ++ if self.choices: ++ max_choice_length = max(len(choice[0]) for choice in self.choices if isinstance(choice, (list, tuple)) and len(choice) > 0) ++ if self.max_length is not None and max_choice_length > self.max_length: ++ raise exceptions.ValidationError( ++ self.error_messages['max_length'] % {'max_length': self.max_length, 'max_choice_length': max_choice_length} ++ ) ++ + def __str__(self): + """ + Return "app_label.model_label.field_name" for fields attached to diff --git a/sub_swebench_dataset/fail_seed1_50/django__django-12663-diff.txt b/sub_swebench_dataset/fail_seed1_50/django__django-12663-diff.txt new file mode 100644 index 000000000..e69de29bb diff --git a/sub_swebench_dataset/fail_seed1_50/django__django-13233-diff.txt b/sub_swebench_dataset/fail_seed1_50/django__django-13233-diff.txt new file mode 100644 index 000000000..68a91b525 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/django__django-13233-diff.txt @@ -0,0 +1,114 @@ +diff --git a/django/db/models/fields/files.py b/django/db/models/fields/files.py +index b064202ee3..e9ddf9e117 100644 +--- a/django/db/models/fields/files.py ++++ b/django/db/models/fields/files.py +@@ -159,58 +159,23 @@ class FileDescriptor(DeferredAttribute): + if instance is None: + return self + +- # This is slightly complicated, so worth an explanation. +- # instance.file`needs to ultimately return some instance of `File`, +- # probably a subclass. Additionally, this returned object needs to have +- # the FieldFile API so that users can easily do things like +- # instance.file.path and have that delegated to the file storage engine. +- # Easy enough if we're strict about assignment in __set__, but if you +- # peek below you can see that we're not. So depending on the current +- # value of the field we have to dynamically construct some sort of +- # "thing" to return. +- +- # The instance dict contains whatever was originally assigned +- # in __set__. +- file = super().__get__(instance, cls) +- +- # If this value is a string (instance.file = "path/to/file") or None +- # then we simply wrap it with the appropriate attribute class according +- # to the file field. [This is FieldFile for FileFields and +- # ImageFieldFile for ImageFields; it's also conceivable that user +- # subclasses might also want to subclass the attribute class]. This +- # object understands how to convert a path to a file, and also how to +- # handle None. +- if isinstance(file, str) or file is None: +- attr = self.field.attr_class(instance, self.field, file) +- instance.__dict__[self.field.attname] = attr +- +- # Other types of files may be assigned as well, but they need to have +- # the FieldFile interface added to them. Thus, we wrap any other type of +- # File inside a FieldFile (well, the field's attr_class, which is +- # usually FieldFile). +- elif isinstance(file, File) and not isinstance(file, FieldFile): +- file_copy = self.field.attr_class(instance, self.field, file.name) +- file_copy.file = file +- file_copy._committed = False +- instance.__dict__[self.field.attname] = file_copy +- +- # Finally, because of the (some would say boneheaded) way pickle works, +- # the underlying FieldFile might not actually itself have an associated +- # file. So we need to reset the details of the FieldFile in those cases. +- elif isinstance(file, FieldFile) and not hasattr(file, 'field'): +- file.instance = instance +- file.field = self.field +- file.storage = self.field.storage +- +- # Make sure that the instance is correct. +- elif isinstance(file, FieldFile) and instance is not file.instance: +- file.instance = instance +- +- # That was fun, wasn't it? +- return instance.__dict__[self.field.attname] ++ # Reinstate the logic to ensure the model attribute points to the concrete model ++ if self.field.name not in instance.__dict__: ++ instance.refresh_from_db(fields=[self.field.name]) ++ file = instance.__dict__[self.field.name] ++ ++ # ... [rest of the existing __get__ method code] ... ++ ++ if self.field.name is None: ++ raise ValueError("The 'name' attribute of the field is None, which is invalid for file descriptor operations.") ++ return instance.__dict__[self.field.name] + + def __set__(self, instance, value): +- instance.__dict__[self.field.attname] = value ++ if self.field.name is None: ++ raise ValueError("The 'name' attribute of the field is None, which is invalid for file descriptor operations.") ++ instance.__dict__[self.field.name] = value ++ ++ # ... [existing code below] ... + + + class FileField(Field): +@@ -321,6 +286,8 @@ class FileField(Field): + if data is not None: + # This value will be converted to str and stored in the + # database, so leaving False as-is is not acceptable. ++ if not isinstance(self.name, str) or not self.name: ++ raise ValueError("The 'name' attribute of the field must be a non-empty string.") + setattr(instance, self.name, data or '') + + def formfield(self, **kwargs): +@@ -337,7 +304,8 @@ class ImageFileDescriptor(FileDescriptor): + assigning the width/height to the width_field/height_field, if appropriate. + """ + def __set__(self, instance, value): +- previous_file = instance.__dict__.get(self.field.attname) ++ if not isinstance(self.field.name, str) or not self.field.name: ++ raise ValueError("The 'name' attribute of the field must be a non-empty string.") + super().__set__(instance, value) + + # To prevent recalculating image dimensions when we are instantiating +@@ -349,6 +317,7 @@ class ImageFileDescriptor(FileDescriptor): + # hooked up to the post_init signal handles the Model.__init__() cases. + # Assignment happening outside of Model.__init__() will trigger the + # update right here. ++ previous_file = instance.__dict__.get(self.field.attname) + if previous_file is not None: + self.field.update_dimension_fields(instance, force=True) + +@@ -431,6 +400,8 @@ class ImageField(FileField): + # getattr will call the ImageFileDescriptor's __get__ method, which + # coerces the assigned value into an instance of self.attr_class + # (ImageFieldFile in this case). ++ if not isinstance(self.attname, str) or not self.attname: ++ raise ValueError("The 'attname' attribute of the field must be a non-empty string.") + file = getattr(instance, self.attname) + + # Nothing to update if we have no file and not being forced to update. diff --git a/sub_swebench_dataset/fail_seed1_50/django__django-13516-diff.txt b/sub_swebench_dataset/fail_seed1_50/django__django-13516-diff.txt new file mode 100644 index 000000000..e69de29bb diff --git a/sub_swebench_dataset/fail_seed1_50/django__django-14372-diff.txt b/sub_swebench_dataset/fail_seed1_50/django__django-14372-diff.txt new file mode 100644 index 000000000..bdc86b20b --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/django__django-14372-diff.txt @@ -0,0 +1,13 @@ +diff --git a/django/db/models/fields/files.py b/django/db/models/fields/files.py +index a2f972489f..963be46f83 100644 +--- a/django/db/models/fields/files.py ++++ b/django/db/models/fields/files.py +@@ -299,7 +299,7 @@ class FileField(Field): + file = super().pre_save(model_instance, add) + if file and not file._committed: + # Commit the file to storage prior to saving the model +- file.save(file.name, file.file, save=False) ++ file.save(os.path.basename(file.name), file.file, save=False) + return file + + def contribute_to_class(self, cls, name, **kwargs): diff --git a/sub_swebench_dataset/fail_seed1_50/django__django-14434-diff.txt b/sub_swebench_dataset/fail_seed1_50/django__django-14434-diff.txt new file mode 100644 index 000000000..da4d27857 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/django__django-14434-diff.txt @@ -0,0 +1,66 @@ +diff --git a/django/db/backends/base/schema.py b/django/db/backends/base/schema.py +index ad2f5a7da1..c857c30009 100644 +--- a/django/db/backends/base/schema.py ++++ b/django/db/backends/base/schema.py +@@ -170,6 +170,8 @@ class BaseDatabaseSchemaEditor: + col_type_suffix = field.db_type_suffix(connection=self.connection) + if col_type_suffix: + definition += ' %s' % col_type_suffix ++ if extra_params is None: ++ extra_params = [] + params.extend(extra_params) + # FK. + if field.remote_field and field.db_constraint: +@@ -764,6 +766,7 @@ class BaseDatabaseSchemaEditor: + ) + if four_way_default_alteration: + # Update existing rows with default value ++ new_default = self.effective_default(new_field) # Ensure new_default is always bound + self.execute( + self.sql_update_with_default % { + "table": self.quote_name(model._meta.db_table), +@@ -1149,10 +1152,10 @@ class BaseDatabaseSchemaEditor: + } + + def _create_fk_sql(self, model, field, suffix): +- table = Table(model._meta.db_table, self.quote_name) ++ table = model._meta.db_table + name = self._fk_constraint_name(model, field, suffix) + column = Columns(model._meta.db_table, [field.column], self.quote_name) +- to_table = Table(field.target_field.model._meta.db_table, self.quote_name) ++ to_table = field.target_field.model._meta.db_table + to_column = Columns(field.target_field.model._meta.db_table, [field.target_field.column], self.quote_name) + deferrable = self.connection.ops.deferrable_sql() + return Statement( +@@ -1241,7 +1244,7 @@ class BaseDatabaseSchemaEditor: + return self.quote_name(self._create_index_name(*args, **kwargs)) + + compiler = Query(model, alias_cols=False).get_compiler(connection=self.connection) +- table = Table(model._meta.db_table, self.quote_name) ++ table = model._meta.db_table + if name is None: + name = IndexName(model._meta.db_table, columns, '_uniq', create_unique_name) + else: +diff --git a/django/db/backends/ddl_references.py b/django/db/backends/ddl_references.py +index c06386a2fa..6a83cc46a4 100644 +--- a/django/db/backends/ddl_references.py ++++ b/django/db/backends/ddl_references.py +@@ -82,6 +82,9 @@ class Columns(TableColumns): + self.col_suffixes = col_suffixes + super().__init__(table, columns) + ++ def references_column(self, table, column): ++ return self.table == table and column in self.columns ++ + def __str__(self): + def col_str(column, idx): + col = self.quote_name(column) +@@ -206,7 +209,7 @@ class Expressions(TableColumns): + self.compiler = compiler + self.expressions = expressions + self.quote_value = quote_value +- columns = [col.target.column for col in self.compiler.query._gen_cols([self.expressions])] ++ columns = [col.target.column for col in self.compiler.query._gen_cols([expressions])] + super().__init__(table, columns) + + def rename_table_references(self, old_table, new_table): diff --git a/sub_swebench_dataset/fail_seed1_50/django__django-14634-diff.txt b/sub_swebench_dataset/fail_seed1_50/django__django-14634-diff.txt new file mode 100644 index 000000000..17020108c --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/django__django-14634-diff.txt @@ -0,0 +1,37 @@ +diff --git a/django/views/generic/edit.py b/django/views/generic/edit.py +index ccfef9cbcd..1bda06b2c0 100644 +--- a/django/views/generic/edit.py ++++ b/django/views/generic/edit.py +@@ -199,6 +199,16 @@ class UpdateView(SingleObjectTemplateResponseMixin, BaseUpdateView): + template_name_suffix = '_form' + + ++class SuccessMessageMixin: ++ """ ++ Provide a way to display a success message after an object has been deleted. ++ """ ++ success_message = "" ++ ++ def set_success_message(self, message): ++ self.success_message = message ++ ++ + class DeletionMixin: + """Provide the ability to delete objects.""" + success_url = None +@@ -233,9 +243,14 @@ class BaseDeleteView(DeletionMixin, BaseDetailView): + """ + + +-class DeleteView(SingleObjectTemplateResponseMixin, BaseDeleteView): ++class DeleteView(SuccessMessageMixin, SingleObjectTemplateResponseMixin, BaseDeleteView): + """ + View for deleting an object retrieved with self.get_object(), with a + response rendered by a template. + """ + template_name_suffix = '_confirm_delete' ++ ++ def delete(self, request, *args, **kwargs): ++ response = super().delete(request, *args, **kwargs) ++ self.set_success_message("The object was deleted successfully.") ++ return response diff --git a/sub_swebench_dataset/fail_seed1_50/django__django-15018-diff.txt b/sub_swebench_dataset/fail_seed1_50/django__django-15018-diff.txt new file mode 100644 index 000000000..c104c516f --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/django__django-15018-diff.txt @@ -0,0 +1,44 @@ +diff --git a/django/core/management/__init__.py b/django/core/management/__init__.py +index 4e30a28f33..3699cf99fa 100644 +--- a/django/core/management/__init__.py ++++ b/django/core/management/__init__.py +@@ -142,14 +142,17 @@ def call_command(command_name, *args, **options): + for group in parser._mutually_exclusive_groups + for opt in group._group_actions if group.required + } +- # Any required arguments which are passed in via **options must be passed +- # to parse_args(). ++ # Track which options have been added to parse_args to avoid duplicates ++ added_options = set() ++ + for opt in parser_actions: + if ( + opt.dest in options and +- (opt.required or opt in mutually_exclusive_required_options) ++ (opt.required or opt in mutually_exclusive_required_options) and ++ opt.dest not in added_options # Check if the dest has not been added already + ): + parse_args.append(min(opt.option_strings)) ++ added_options.add(opt.dest) # Mark this dest as added + if isinstance(opt, (_AppendConstAction, _CountAction, _StoreConstAction)): + continue + value = arg_options[opt.dest] +diff --git a/tests/user_commands/tests.py b/tests/user_commands/tests.py +index d3afb697bb..02ef937a23 100644 +--- a/tests/user_commands/tests.py ++++ b/tests/user_commands/tests.py +@@ -421,3 +421,14 @@ class UtilsTests(SimpleTestCase): + def test_normalize_path_patterns_truncates_wildcard_base(self): + expected = [os.path.normcase(p) for p in ['foo/bar', 'bar/*/']] + self.assertEqual(normalize_path_patterns(['foo/bar/*', 'bar/*/']), expected) ++ ++from django.core.management import call_command ++from django.core.management.base import CommandError ++from django.test import TestCase ++ ++class SimulateIssueCommandTests(TestCase): ++ def test_call_command_with_mutually_exclusive_arguments(self): ++ with self.assertRaises(CommandError): ++ # This should raise an error because the --for and --until arguments are mutually exclusive ++ # and use the same dest, which is not currently supported by call_command. ++ call_command('simulate_issue', '--for', '2h') diff --git a/sub_swebench_dataset/fail_seed1_50/django__django-15766-diff.txt b/sub_swebench_dataset/fail_seed1_50/django__django-15766-diff.txt new file mode 100644 index 000000000..10f9ed043 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/django__django-15766-diff.txt @@ -0,0 +1,77 @@ +diff --git a/django/db/transaction.py b/django/db/transaction.py +index b3c7b4bbaa..f8ee615204 100644 +--- a/django/db/transaction.py ++++ b/django/db/transaction.py +@@ -1,4 +1,5 @@ + from contextlib import ContextDecorator, contextmanager ++import logging + + from django.db import ( + DEFAULT_DB_ALIAS, +@@ -8,6 +9,7 @@ from django.db import ( + connections, + ) + ++logger = logging.getLogger('django.db.transaction') + + class TransactionManagementError(ProgrammingError): + """Transaction management is used improperly.""" +@@ -125,12 +127,23 @@ def mark_for_rollback_on_error(using=None): + raise + + +-def on_commit(func, using=None): ++def on_commit(func, using=None, robust=False): + """ + Register `func` to be called when the current transaction is committed. + If the current transaction is rolled back, `func` will not be called. ++ If `robust` is True, exceptions in `func` will be suppressed. + """ +- get_connection(using).on_commit(func) ++ connection = get_connection(using) ++ if robust: ++ def wrapped_func(): ++ try: ++ func() ++ except Exception as e: ++ # Log the exception and suppress it ++ logger.error("Suppressed exception in robust on_commit handler: %s", e) ++ connection.on_commit(wrapped_func) ++ else: ++ connection.on_commit(func) + + + ################################# +@@ -221,6 +234,7 @@ class Atomic(ContextDecorator): + connection.atomic_blocks.append(self) + + def __exit__(self, exc_type, exc_value, traceback): ++ sid = None + connection = get_connection(self.using) + + if connection.in_atomic_block: +diff --git a/django/local_settings.py b/django/local_settings.py +new file mode 100644 +index 0000000000..4b3b4ab5ba +--- /dev/null ++++ b/django/local_settings.py +@@ -0,0 +1,19 @@ ++ ++# local_settings.py ++SECRET_KEY = 'fake-key-for-testing' ++ ++INSTALLED_APPS = [ ++ 'django.contrib.auth', ++ 'django.contrib.contenttypes', ++ 'django.contrib.sessions', ++] ++ ++DATABASES = { ++ 'default': { ++ 'ENGINE': 'django.db.backends.sqlite3', ++ 'NAME': 'mydatabase', ++ } ++} ++ ++# Use console backend for email during testing ++EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' diff --git a/sub_swebench_dataset/fail_seed1_50/django__django-15957-diff.txt b/sub_swebench_dataset/fail_seed1_50/django__django-15957-diff.txt new file mode 100644 index 000000000..2e806b30f --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/django__django-15957-diff.txt @@ -0,0 +1,66 @@ +diff --git a/django/db/models/query.py b/django/db/models/query.py +index be0deb90b0..bd194a0d0b 100644 +--- a/django/db/models/query.py ++++ b/django/db/models/query.py +@@ -1564,9 +1564,14 @@ class QuerySet: + if lookups == (None,): + clone._prefetch_related_lookups = () + else: ++ lookups = normalize_prefetch_lookups(lookups) + for lookup in lookups: + if isinstance(lookup, Prefetch): +- lookup = lookup.prefetch_to ++ if lookup.queryset is not None and lookup.queryset.query.is_sliced: ++ # The queryset has slicing applied, so we make a clone of the ++ # queryset before using it for prefetching. ++ lookup.queryset = lookup.queryset._chain() ++ lookup = lookup.prefetch_to + lookup = lookup.split(LOOKUP_SEP, 1)[0] + if lookup in self.query._filtered_relations: + raise ValueError( +@@ -2022,7 +2027,7 @@ class RawQuerySet: + annotation_fields = [ + (column, pos) + for pos, column in enumerate(self.columns) +- if column not in self.model_fields ++ if column not in the model_fields + ] + model_init_order = [ + self.columns.index(converter(f.column)) for f in model_init_fields +@@ -2036,13 +2041,20 @@ class RawQuerySet: + if lookups == (None,): + clone._prefetch_related_lookups = () + else: ++ for lookup in lookups: ++ if isinstance(lookup, Prefetch): ++ lookup = lookup.prefetch_to ++ lookup = lookup.split(LOOKUP_SEP, 1)[0] ++ if lookup in self.query._filtered_relations: ++ raise ValueError( ++ "prefetch_related() is not supported with FilteredRelation." ++ ) + clone._prefetch_related_lookups = clone._prefetch_related_lookups + lookups + return clone + + def _prefetch_related_objects(self): + prefetch_related_objects(self._result_cache, *self._prefetch_related_lookups) + self._prefetch_done = True +- + def _clone(self): + """Same as QuerySet._clone()""" + c = self.__class__( +diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt +index 223bb452b0..ceb8dc1fda 100644 +--- a/docs/ref/models/querysets.txt ++++ b/docs/ref/models/querysets.txt +@@ -1363,9 +1363,7 @@ database selected by the outer query. All of the following are valid:: + >>> prefetch_related('pizzas__toppings', Prefetch('pizzas', queryset=Pizza.objects.all())) + + This will raise a ``ValueError`` because of the attempt to redefine the +- queryset of a previously seen lookup. Note that an implicit queryset was +- created to traverse ``'pizzas'`` as part of the ``'pizzas__toppings'`` +- lookup. ++ This will not raise a ``ValueError`` anymore because the queryset of a previously seen lookup can now be redefined with slicing. Note that an implicit queryset was created to traverse ``'pizzas'`` as part of the ``'pizzas__toppings'`` lookup. + + >>> prefetch_related('pizza_list__toppings', Prefetch('pizzas', to_attr='pizza_list')) + diff --git a/sub_swebench_dataset/fail_seed1_50/django__django-16076-diff.txt b/sub_swebench_dataset/fail_seed1_50/django__django-16076-diff.txt new file mode 100644 index 000000000..1809cc562 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/django__django-16076-diff.txt @@ -0,0 +1,32 @@ +diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py +index 63ed2ff4c7..9f9bb428f8 100644 +--- a/django/db/models/fields/related.py ++++ b/django/db/models/fields/related.py +@@ -897,6 +897,27 @@ ForeignObject.register_lookup(RelatedGreaterThanOrEqual) + ForeignObject.register_lookup(RelatedLessThanOrEqual) + ForeignObject.register_lookup(RelatedIsNull) + ++from django.db.models.lookups import StartsWith ++ ++class StartsWithNoJoin(StartsWith): ++ # This class should override methods from StartsWith to change the SQL generation ++ # to not require a join. The implementation details would depend on Django's ORM ++ # internals and require a deep understanding of how Django constructs SQL queries ++ # for lookups. ++ ++ def as_sql(self, compiler, connection): ++ # We override the as_sql method to modify the default behavior of the 'startswith' lookup ++ # to prevent a join. Instead, we directly apply the 'startswith' pattern to the foreign key column. ++ lhs, lhs_params = self.process_lhs(compiler, connection) ++ rhs, rhs_params = self.process_rhs(compiler, connection) ++ params = lhs_params + rhs_params ++ # The pattern '%' is appended to the rhs value to achieve the 'startswith' SQL behavior. ++ rhs = self.get_rhs_op(connection, rhs) ++ return '%s LIKE %s' % (lhs, rhs), params ++ ++# Register the custom lookup for ForeignObject fields ++ForeignObject.register_lookup(StartsWithNoJoin) ++ + + class ForeignKey(ForeignObject): + """ diff --git a/sub_swebench_dataset/fail_seed1_50/django__django-16254-diff.txt b/sub_swebench_dataset/fail_seed1_50/django__django-16254-diff.txt new file mode 100644 index 000000000..271ae5941 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/django__django-16254-diff.txt @@ -0,0 +1,30 @@ +diff --git a/django/db/backends/sqlite3/schema.py b/django/db/backends/sqlite3/schema.py +index 6c106ae868..39029a39ec 100644 +--- a/django/db/backends/sqlite3/schema.py ++++ b/django/db/backends/sqlite3/schema.py +@@ -379,18 +379,13 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): + + def add_field(self, model, field): + """Create a field on a model.""" +- if ( +- # Primary keys and unique fields are not supported in ALTER TABLE +- # ADD COLUMN. +- field.primary_key +- or field.unique +- or +- # Fields with default values cannot by handled by ALTER TABLE ADD +- # COLUMN statement because DROP DEFAULT is not supported in +- # ALTER TABLE. +- not field.null +- or self.effective_default(field) is not None +- ): ++ # Special-case implicit M2M tables ++ if field.many_to_many and field.remote_field.through._meta.auto_created: ++ return self.create_model(field.remote_field.through) ++ # Fields with default values cannot by handled by ALTER TABLE ADD ++ # COLUMN statement because DROP DEFAULT is not supported in ++ # ALTER TABLE. ++ if not field.null or self.effective_default(field) is not None: + self._remake_table(model, create_field=field) + else: + super().add_field(model, field) diff --git a/sub_swebench_dataset/fail_seed1_50/django__django-16511-diff.txt b/sub_swebench_dataset/fail_seed1_50/django__django-16511-diff.txt new file mode 100644 index 000000000..62eed4f97 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/django__django-16511-diff.txt @@ -0,0 +1,43 @@ +diff --git a/django/db/models/query.py b/django/db/models/query.py +index 9d621c4f69..12dcfc1c8a 100644 +--- a/django/db/models/query.py ++++ b/django/db/models/query.py +@@ -926,20 +926,24 @@ class QuerySet(AltersData): + **kwargs, + ) + +- def update_or_create(self, defaults=None, **kwargs): ++ def update_or_create(self, defaults=None, create_defaults=None, **kwargs): + """ + Look up an object with the given kwargs, updating one with defaults +- if it exists, otherwise create a new one. ++ if it exists, otherwise create a new one with create_defaults. + Return a tuple (object, created), where created is a boolean + specifying whether an object was created. + """ + defaults = defaults or {} ++ create_defaults = create_defaults or {} + self._for_write = True + with transaction.atomic(using=self.db): + # Lock the row so that a concurrent update is blocked until + # update_or_create() has performed its save. + obj, created = self.select_for_update().get_or_create(defaults, **kwargs) + if created: ++ for k, v in resolve_callables(create_defaults): ++ setattr(obj, k, v) ++ obj.save(using=self.db) + return obj, created + for k, v in resolve_callables(defaults): + setattr(obj, k, v) +@@ -964,9 +968,10 @@ class QuerySet(AltersData): + obj.save(using=self.db) + return obj, False + +- async def aupdate_or_create(self, defaults=None, **kwargs): ++ async def aupdate_or_create(self, defaults=None, create_defaults=None, **kwargs): + return await sync_to_async(self.update_or_create)( + defaults=defaults, ++ create_defaults=create_defaults, + **kwargs, + ) + diff --git a/sub_swebench_dataset/fail_seed1_50/django__django-16517-diff.txt b/sub_swebench_dataset/fail_seed1_50/django__django-16517-diff.txt new file mode 100644 index 000000000..28e313b18 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/django__django-16517-diff.txt @@ -0,0 +1,28 @@ +diff --git a/django/contrib/admindocs/views.py b/django/contrib/admindocs/views.py +index a5e710835e..75bcdd0387 100644 +--- a/django/contrib/admindocs/views.py ++++ b/django/contrib/admindocs/views.py +@@ -173,13 +173,20 @@ class ViewDetailView(BaseAdminDocsView): + # Separate the module and function, e.g. + # 'mymodule.views.myview' -> 'mymodule.views', 'myview'). + return getattr(import_module(mod), func) +- except ImportError: ++ except ImportError as e: + # Import may fail because view contains a class name, e.g. + # 'mymodule.views.ViewContainer.my_view', so mod takes the form + # 'mymodule.views.ViewContainer'. Parse it again to separate + # the module and class. +- mod, klass = get_mod_func(mod) +- return getattr(getattr(import_module(mod), klass), func) ++ parts = mod.split('.') ++ for i in range(len(parts) - 1, 0, -1): ++ try: ++ mod = '.'.join(parts[:i]) ++ klass = parts[i] ++ return getattr(getattr(import_module(mod), klass), func) ++ except ImportError: ++ continue ++ raise e + + def get_context_data(self, **kwargs): + view = self.kwargs["view"] diff --git a/sub_swebench_dataset/fail_seed1_50/matplotlib__matplotlib-20676-diff.txt b/sub_swebench_dataset/fail_seed1_50/matplotlib__matplotlib-20676-diff.txt new file mode 100644 index 000000000..40ead9da6 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/matplotlib__matplotlib-20676-diff.txt @@ -0,0 +1,17 @@ +diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py +index a199e45d40..40538bc397 100644 +--- a/lib/matplotlib/widgets.py ++++ b/lib/matplotlib/widgets.py +@@ -1879,8 +1879,10 @@ class _SelectorWidget(AxesWidget): + """Get the xdata and ydata for event, with limits.""" + if event.xdata is None: + return None, None +- xdata = np.clip(event.xdata, *self.ax.get_xbound()) +- ydata = np.clip(event.ydata, *self.ax.get_ybound()) ++ x0, x1 = self.ax.get_xbound() ++ y0, y1 = self.ax.get_ybound() ++ xdata = event.xdata if x0 <= event.xdata <= x1 else np.clip(event.xdata, x0, x1) ++ ydata = event.ydata if y0 <= event.ydata <= y1 else np.clip(event.ydata, y0, y1) + return xdata, ydata + + def _clean_event(self, event): diff --git a/sub_swebench_dataset/fail_seed1_50/matplotlib__matplotlib-22929-diff.txt b/sub_swebench_dataset/fail_seed1_50/matplotlib__matplotlib-22929-diff.txt new file mode 100644 index 000000000..54ba1ac4a --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/matplotlib__matplotlib-22929-diff.txt @@ -0,0 +1,32 @@ +diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py +index c3a79b0d45..2dece1060e 100644 +--- a/lib/matplotlib/axes/_axes.py ++++ b/lib/matplotlib/axes/_axes.py +@@ -2676,11 +2676,22 @@ class Axes(_AxesBase): + + if err is None: + endpt = extrema +- elif orientation == "vertical": +- endpt = err[:, 1].max() if dat >= 0 else err[:, 1].min() +- elif orientation == "horizontal": +- endpt = err[:, 0].max() if dat >= 0 else err[:, 0].min() +- ++ else: ++ # Check if 'err' is 1D and convert to 2D if needed ++ if err.ndim == 1: ++ err = np.array([err, err]) ++ # Check if 'err' is empty and set 'endpt' to 'extrema' ++ if err.size == 0: ++ endpt = extrema ++ else: ++ # Handle NaN in error values: if err array contains NaN, use extrema as endpoint ++ if np.any(np.isnan(err)): ++ endpt = extrema ++ else: ++ if orientation == "vertical": ++ endpt = err[:, 1].max() if dat >= 0 else err[:, 1].min() ++ elif orientation == "horizontal": ++ endpt = err[:, 0].max() if dat >= 0 else err[:, 0].min() + if label_type == "center": + value = sign(dat) * length + elif label_type == "edge": diff --git a/sub_swebench_dataset/fail_seed1_50/matplotlib__matplotlib-24013-diff.txt b/sub_swebench_dataset/fail_seed1_50/matplotlib__matplotlib-24013-diff.txt new file mode 100644 index 000000000..857115e4a --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/matplotlib__matplotlib-24013-diff.txt @@ -0,0 +1,17 @@ +diff --git a/lib/matplotlib/tri/__init__.py b/lib/matplotlib/tri/__init__.py +index 4185452c01..588234e272 100644 +--- a/lib/matplotlib/tri/__init__.py ++++ b/lib/matplotlib/tri/__init__.py +@@ -7,7 +7,7 @@ from .tricontour import TriContourSet, tricontour, tricontourf + from .trifinder import TriFinder, TrapezoidMapTriFinder + from .triinterpolate import (TriInterpolator, LinearTriInterpolator, + CubicTriInterpolator) +-from .tripcolor import tripcolor ++from ._tripcolor import tripcolor + from .triplot import triplot + from .trirefine import TriRefiner, UniformTriRefiner + from .tritools import TriAnalyzer +diff --git a/lib/matplotlib/tri/tripcolor.py b/lib/matplotlib/tri/_tripcolor.py +similarity index 100% +rename from lib/matplotlib/tri/tripcolor.py +rename to lib/matplotlib/tri/_tripcolor.py diff --git a/sub_swebench_dataset/fail_seed1_50/matplotlib__matplotlib-25281-diff.txt b/sub_swebench_dataset/fail_seed1_50/matplotlib__matplotlib-25281-diff.txt new file mode 100644 index 000000000..75c7b1f86 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/matplotlib__matplotlib-25281-diff.txt @@ -0,0 +1,31 @@ +diff --git a/lib/matplotlib/legend.py b/lib/matplotlib/legend.py +index e06069a675..c396d5b669 100644 +--- a/lib/matplotlib/legend.py ++++ b/lib/matplotlib/legend.py +@@ -670,14 +670,23 @@ class Legend(Artist): + a.set_transform(self.get_transform()) + + def _set_loc(self, loc): +- # find_offset function will be provided to _legend_box and +- # _legend_box will draw itself at the location of the return +- # value of the find_offset. ++ # Validation for 'loc' inputs ++ print(f"DEBUG: loc value passed: {loc}") ++ print(f"DEBUG: valid loc codes: {self._get_loc_codes()}") ++ if isinstance(loc, str): ++ if loc not in self._get_loc_codes(): # Use a method to get valid codes ++ raise ValueError(f"'{loc}' is not a valid string for 'loc'.") ++ elif not (isinstance(loc, tuple) and len(loc) == 2 and all(isinstance(item, float) for item in loc)): ++ raise ValueError("The 'loc' argument must be a string or a tuple of two floats") ++ # Existing code to set the location + self._loc_used_default = False + self._loc_real = loc + self.stale = True + self._legend_box.set_offset(self._findoffset) + ++ def _get_loc_codes(self): ++ return self.codes ++ + def set_ncols(self, ncols): + """Set the number of columns.""" + self._ncols = ncols diff --git a/sub_swebench_dataset/fail_seed1_50/psf__requests-1657-diff.txt b/sub_swebench_dataset/fail_seed1_50/psf__requests-1657-diff.txt new file mode 100644 index 000000000..9c616caa8 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/psf__requests-1657-diff.txt @@ -0,0 +1,93 @@ +diff --git a/requests/sessions.py b/requests/sessions.py +index d8e040c8..7deefa44 100644 +--- a/requests/sessions.py ++++ b/requests/sessions.py +@@ -9,7 +9,7 @@ requests (cookies, auth, proxies). + + """ + import os +-from collections import Mapping ++from collections.abc import Mapping + from datetime import datetime + + from .compat import cookielib, OrderedDict, urljoin, urlparse, urlunparse +@@ -26,41 +26,40 @@ from .utils import requote_uri, get_environ_proxies, get_netrc_auth + + from .status_codes import codes + REDIRECT_STATI = ( +- codes.moved, # 301 ++ codes.moved_permanently, # 301 + codes.found, # 302 +- codes.other, # 303 +- codes.temporary_moved, # 307 ++ codes.see_other, # 303 ++ codes.temporary_redirect, # 307 + ) + DEFAULT_REDIRECT_LIMIT = 30 + + + def merge_setting(request_setting, session_setting, dict_class=OrderedDict): +- """ +- Determines appropriate setting for a given request, taking into account the +- explicit setting on that request, and the setting in the session. If a +- setting is a dictionary, they will be merged together using `dict_class` +- """ +- ++ # If either setting is None, return the other + if session_setting is None: + return request_setting +- + if request_setting is None: + return session_setting + +- # Bypass if not a dictionary (e.g. verify) +- if not ( +- isinstance(session_setting, Mapping) and +- isinstance(request_setting, Mapping) +- ): ++ # If settings are not dictionaries, return request_setting ++ if not (isinstance(session_setting, Mapping) and isinstance(request_setting, Mapping)): + return request_setting + +- merged_setting = dict_class(to_key_val_list(session_setting)) +- merged_setting.update(to_key_val_list(request_setting)) +- +- # Remove keys that are set to None. +- for (k, v) in request_setting.items(): +- if v is None: +- del merged_setting[k] ++ # Initialize merged_setting with session_setting items ++ merged_setting = dict_class() ++ session_items = to_key_val_list(session_setting) if session_setting is not None else [] ++ request_items = to_key_val_list(request_setting) if request_setting is not None else [] ++ for key, value in session_items: ++ if key in request_items: ++ merged_setting[key] = value + request_items[key] ++ else: ++ merged_setting[key] = value ++ for key, value in request_items: ++ if key not in merged_setting: ++ merged_setting[key] = value ++ ++ # Remove keys that are set to None ++ merged_setting = {k: v for k, v in merged_setting.items() if v is not None} + + return merged_setting + +@@ -114,14 +113,14 @@ class SessionRedirectMixin(object): + method = 'GET' + + # Do what the browsers do, despite standards... +- if (resp.status_code in (codes.moved, codes.found) and ++ if (resp.status_code in (codes.moved_permanently, codes.found) and + method not in ('GET', 'HEAD')): + method = 'GET' + + prepared_request.method = method + + # https://github.com/kennethreitz/requests/issues/1084 +- if resp.status_code not in (codes.temporary, codes.resume): ++ if resp.status_code not in (codes.temporary_redirect, codes.resume_incomplete): + if 'Content-Length' in prepared_request.headers: + del prepared_request.headers['Content-Length'] + diff --git a/sub_swebench_dataset/fail_seed1_50/pydata__xarray-7019-diff.txt b/sub_swebench_dataset/fail_seed1_50/pydata__xarray-7019-diff.txt new file mode 100644 index 000000000..06d92450f --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/pydata__xarray-7019-diff.txt @@ -0,0 +1,138 @@ +diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py +index 2336883d..aa40b69b 100644 +--- a/xarray/core/dataset.py ++++ b/xarray/core/dataset.py +@@ -73,7 +73,7 @@ from xarray.core.merge import ( + ) + from xarray.core.missing import get_clean_interp_index + from xarray.core.options import OPTIONS, _get_keep_attrs +-from xarray.core.pycompat import array_type, is_duck_array, is_duck_dask_array ++from xarray.core.parallel_computation_interface import ParallelComputationInterface + from xarray.core.types import QuantileMethods, T_Dataset + from xarray.core.utils import ( + Default, +@@ -741,25 +741,40 @@ class Dataset( + -------- + dask.compute + """ +- # access .data to coerce everything to numpy or dask arrays +- lazy_data = { +- k: v._data for k, v in self.variables.items() if is_duck_dask_array(v._data) +- } +- if lazy_data: +- import dask.array as da ++ def compute(self, **kwargs): ++ """Manually trigger loading of this dataset's data from disk or a remote source into memory and return a new dataset. The original is left unaltered. + +- # evaluate all the dask arrays simultaneously +- evaluated_data = da.compute(*lazy_data.values(), **kwargs) ++ This is particularly useful when working with many file objects on disk. + +- for k, data in zip(lazy_data, evaluated_data): +- self.variables[k].data = data ++ Parameters ++ ---------- ++ **kwargs : dict ++ Additional keyword arguments passed on to the computation interface's compute method. + +- # load everything else sequentially +- for k, v in self.variables.items(): +- if k not in lazy_data: +- v.load() ++ See Also ++ -------- ++ ParallelComputationInterface.compute ++ """ ++ # access .data to coerce everything to numpy or computation interface arrays ++ lazy_data = { ++ k: v._data for k, v in self.variables.items() if is_duck_dask_array(v._data) ++ } ++ if lazy_data: ++ # Create an instance of the computation interface ++ computation_interface = ParallelComputationInterface() + +- return self ++ # evaluate all the computation interface arrays simultaneously ++ evaluated_data = computation_interface.compute(*lazy_data.values(), **kwargs) ++ ++ for k, data in zip(lazy_data, evaluated_data): ++ self.variables[k].data = data ++ ++ # load everything else sequentially ++ for k, v in self.variables.items(): ++ if k not in lazy_data: ++ v.load() ++ ++ return self + + def __dask_tokenize__(self): + from dask.base import normalize_token +@@ -806,15 +821,15 @@ class Dataset( + + @property + def __dask_optimize__(self): +- import dask.array as da +- +- return da.Array.__dask_optimize__ ++ return self._parallel_computation_interface.get_optimize_function() + + @property + def __dask_scheduler__(self): +- import dask.array as da ++ return self._parallel_computation_interface.get_scheduler() + +- return da.Array.__dask_scheduler__ ++ def __init__(self, *args, **kwargs): ++ super().__init__(*args, **kwargs) ++ self._parallel_computation_interface = ParallelComputationInterface() + + def __dask_postcompute__(self): + return self._dask_postcompute, () +@@ -2227,11 +2242,11 @@ class Dataset( + token : str, optional + Token uniquely identifying this dataset. + lock : bool, default: False +- Passed on to :py:func:`dask.array.from_array`, if the array is not +- already as dask array. ++ If the array is not already as dask array, this will be passed on to the ++ computation interface. + inline_array: bool, default: False +- Passed on to :py:func:`dask.array.from_array`, if the array is not +- already as dask array. ++ If the array is not already as dask array, this will be passed on to the ++ computation interface. + **chunks_kwargs : {dim: chunks, ...}, optional + The keyword arguments form of ``chunks``. + One of chunks or chunks_kwargs must be provided +@@ -2245,7 +2260,6 @@ class Dataset( + Dataset.chunks + Dataset.chunksizes + xarray.unify_chunks +- dask.array.from_array + """ + if chunks is None and chunks_kwargs is None: + warnings.warn( +@@ -2266,8 +2280,12 @@ class Dataset( + f"some chunks keys are not dimensions on this object: {bad_dims}" + ) + ++ # Create an instance of the DaskComputationInterface ++ dask_interface = DaskComputationInterface() ++ + variables = { +- k: _maybe_chunk(k, v, chunks, token, lock, name_prefix) ++ k: dask_interface.array_from_template(v, chunks, name_prefix=name_prefix, lock=lock, inline_array=inline_array) ++ if not is_duck_dask_array(v._data) else v._data.rechunk(chunks) + for k, v in self.variables.items() + } + return self._replace(variables) +@@ -6394,8 +6412,7 @@ class Dataset( + dask.dataframe.DataFrame + """ + +- import dask.array as da +- import dask.dataframe as dd ++ from xarray.core.parallel_computation_interface import ParallelComputationInterface + + ordered_dims = self._normalize_dim_order(dim_order=dim_order) + diff --git a/sub_swebench_dataset/fail_seed1_50/pydata__xarray-7120-diff.txt b/sub_swebench_dataset/fail_seed1_50/pydata__xarray-7120-diff.txt new file mode 100644 index 000000000..37068e281 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/pydata__xarray-7120-diff.txt @@ -0,0 +1,30 @@ +diff --git a/xarray/core/dataarray.py b/xarray/core/dataarray.py +index 794984b7..20f8e270 100644 +--- a/xarray/core/dataarray.py ++++ b/xarray/core/dataarray.py +@@ -2736,6 +2736,11 @@ class DataArray( + numpy.transpose + Dataset.transpose + """ ++ # Check if any element in dims is a list and raise an error if so ++ for dim in dims: ++ if isinstance(dim, list): ++ raise ValueError("When calling transpose, provide dimension names as separate arguments, not as a list. For example, use .transpose('dim1', 'dim2') instead of .transpose(['dim1', 'dim2']).") ++ + if dims: + dims = tuple(utils.infix_dims(dims, self.dims, missing_dims)) + variable = self.variable.transpose(*dims) +diff --git a/xarray/core/utils.py b/xarray/core/utils.py +index 0320ea81..2766c496 100644 +--- a/xarray/core/utils.py ++++ b/xarray/core/utils.py +@@ -905,6 +905,9 @@ def drop_missing_dims( + dims : sequence + missing_dims : {"raise", "warn", "ignore"} + """ ++ for dim in supplied_dims: ++ if not isinstance(dim, Hashable): ++ raise ValueError("Dimension names must be hashable. Provide dimension names as separate arguments, not as a list.") + + if missing_dims == "raise": + supplied_dims_set = {val for val in supplied_dims if val is not ...} diff --git a/sub_swebench_dataset/fail_seed1_50/pydata__xarray-7150-diff.txt b/sub_swebench_dataset/fail_seed1_50/pydata__xarray-7150-diff.txt new file mode 100644 index 000000000..44510b61c --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/pydata__xarray-7150-diff.txt @@ -0,0 +1,32 @@ +diff --git a/xarray/backends/netCDF4_.py b/xarray/backends/netCDF4_.py +index 19047d17..0c5780b5 100644 +--- a/xarray/backends/netCDF4_.py ++++ b/xarray/backends/netCDF4_.py +@@ -551,6 +551,27 @@ class NetCDF4BackendEntrypoint(BackendEntrypoint): + autoclose=False, + ): + ++ # Custom backend modification to handle multiindex datasets: ++ # The following pseudocode represents how the custom backend's `open_dataset` method ++ # might be modified to handle multiindex datasets correctly. ++ # ++ # class MultiindexNetCDF4BackendEntrypoint(NetCDF4BackendEntrypoint): ++ # def open_dataset(self, *args, handle_multiindex=True, **kwargs): ++ # ds = super().open_dataset(*args, **kwargs) ++ # ++ # if handle_multiindex: ++ # # Instead of assigning data to IndexVariable, use appropriate methods ++ # # to handle multiindex datasets without violating immutability. ++ # # For example, use Dataset.assign_coords or similar methods. ++ # ds = decode_compress_to_multiindex(ds) ++ # ++ # return ds ++ # ++ # This pseudocode is a high-level representation and does not include the specific ++ # implementation details of the `decode_compress_to_multiindex` function or how exactly ++ # the dataset's coordinates should be modified. The actual implementation would need to be ++ # done by the user or the developer responsible for the custom backend. ++ + filename_or_obj = _normalize_path(filename_or_obj) + store = NetCDF4DataStore.open( + filename_or_obj, diff --git a/sub_swebench_dataset/fail_seed1_50/pylint-dev__pylint-8929-diff.txt b/sub_swebench_dataset/fail_seed1_50/pylint-dev__pylint-8929-diff.txt new file mode 100644 index 000000000..e51ca1b07 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/pylint-dev__pylint-8929-diff.txt @@ -0,0 +1,119 @@ +diff --git a/pylint/reporters/json_reporter.py b/pylint/reporters/json_reporter.py +index 176946e72..a44ac9d65 100644 +--- a/pylint/reporters/json_reporter.py ++++ b/pylint/reporters/json_reporter.py +@@ -1,7 +1,3 @@ +-# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html +-# For details: https://github.com/pylint-dev/pylint/blob/main/LICENSE +-# Copyright (c) https://github.com/pylint-dev/pylint/blob/main/CONTRIBUTORS.txt +- + """JSON reporter.""" + + from __future__ import annotations +@@ -33,6 +29,7 @@ OldJsonExport = TypedDict( + "symbol": str, + "message": str, + "message-id": str, ++ "score": Optional[float], # Added score to the TypedDict + }, + ) + +@@ -43,9 +40,23 @@ class BaseJSONReporter(BaseReporter): + name = "json" + extension = "json" + ++ def __init__(self): ++ super().__init__() ++ self.include_score = False # Added attribute to track score inclusion ++ ++ def handle_options(self, options): ++ """Handle the options related to JSON output.""" ++ self.include_score = options.score # Set the include_score based on the passed options ++ + def display_messages(self, layout: Section | None) -> None: + """Launch layouts display.""" + json_dumpable = [self.serialize(message) for message in self.messages] ++ if self.include_score: ++ score = self.linter.stats.global_note # Retrieve the global score using the correct attribute ++ # Include the score in each message dictionary ++ json_dumpable = [ ++ {**message, 'score': score} for message in json_dumpable ++ ] + print(json.dumps(json_dumpable, indent=4), file=self.out) + + def display_reports(self, layout: Section) -> None: +@@ -56,11 +67,39 @@ class BaseJSONReporter(BaseReporter): + + @staticmethod + def serialize(message: Message) -> OldJsonExport: +- raise NotImplementedError ++ serialized_message = { ++ "type": message.category, ++ "module": message.module, ++ "obj": message.obj, ++ "line": message.line, ++ "column": message.column, ++ "endLine": message.end_line, ++ "endColumn": message.end_column, ++ "path": message.path, ++ "symbol": message.symbol, ++ "message": message.msg or "", ++ "message-id": message.msg_id, ++ } ++ return serialized_message + + @staticmethod + def deserialize(message_as_json: OldJsonExport) -> Message: +- raise NotImplementedError ++ return Message( ++ msg_id=message_as_json["message-id"], ++ symbol=message_as_json["symbol"], ++ msg=message_as_json["message"], ++ location=MessageLocationTuple( ++ abspath=message_as_json["path"], ++ path=message_as_json["path"], ++ module=message_as_json["module"], ++ obj=message_as_json["obj"], ++ line=message_as_json["line"], ++ column=message_as_json["column"], ++ end_line=message_as_json["endLine"], ++ end_column=message_as_json["endColumn"], ++ ), ++ confidence=UNDEFINED, ++ ) + + + class JSONReporter(BaseJSONReporter): +@@ -75,7 +114,7 @@ class JSONReporter(BaseJSONReporter): + + @staticmethod + def serialize(message: Message) -> OldJsonExport: +- return { ++ serialized_message = { + "type": message.category, + "module": message.module, + "obj": message.obj, +@@ -88,6 +127,7 @@ class JSONReporter(BaseJSONReporter): + "message": message.msg or "", + "message-id": message.msg_id, + } ++ return serialized_message + + @staticmethod + def deserialize(message_as_json: OldJsonExport) -> Message: +@@ -96,7 +136,6 @@ class JSONReporter(BaseJSONReporter): + symbol=message_as_json["symbol"], + msg=message_as_json["message"], + location=MessageLocationTuple( +- # TODO: 3.0: Add abs-path and confidence in a new JSONReporter + abspath=message_as_json["path"], + path=message_as_json["path"], + module=message_as_json["module"], +@@ -106,7 +145,6 @@ class JSONReporter(BaseJSONReporter): + end_line=message_as_json["endLine"], + end_column=message_as_json["endColumn"], + ), +- # TODO: 3.0: Make confidence available in a new JSONReporter + confidence=UNDEFINED, + ) + diff --git a/sub_swebench_dataset/fail_seed1_50/pytest-dev__pytest-7535-diff.txt b/sub_swebench_dataset/fail_seed1_50/pytest-dev__pytest-7535-diff.txt new file mode 100644 index 000000000..934645582 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/pytest-dev__pytest-7535-diff.txt @@ -0,0 +1,29 @@ +diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py +index 218b5ad63..79bcde5e0 100644 +--- a/src/_pytest/_code/code.py ++++ b/src/_pytest/_code/code.py +@@ -262,7 +262,7 @@ class TracebackEntry: + raise + except BaseException: + line = "???" +- return " File %r:%d in %s\n %s\n" % (self.path, self.lineno + 1, name, line) ++ return " File %s:%d in %s\n %s\n" % (str(self.path), self.lineno + 1, name, line) + + @property + def name(self) -> str: +diff --git a/testing/python/test_traceback_format.py b/testing/python/test_traceback_format.py +new file mode 100644 +index 000000000..8f54320fe +--- /dev/null ++++ b/testing/python/test_traceback_format.py +@@ -0,0 +1,10 @@ ++import pytest ++import os ++ ++def test_traceback_format(): ++ with pytest.raises(ImportError) as exc_info: ++ from non_existent_module import something ++ ++ current_file = os.path.basename(__file__) ++ traceback_str = "".join(str(line) for line in exc_info.traceback) ++ assert current_file in traceback_str diff --git a/sub_swebench_dataset/fail_seed1_50/pytest-dev__pytest-9359-diff.txt b/sub_swebench_dataset/fail_seed1_50/pytest-dev__pytest-9359-diff.txt new file mode 100644 index 000000000..f635640a4 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/pytest-dev__pytest-9359-diff.txt @@ -0,0 +1,48 @@ +diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py +index 456681ab2..32e711374 100644 +--- a/src/_pytest/assertion/rewrite.py ++++ b/src/_pytest/assertion/rewrite.py +@@ -195,12 +195,16 @@ class AssertionRewritingHook(importlib.abc.MetaPathFinder, importlib.abc.Loader) + # For matching the name it must be as if it was a filename. + path = PurePath(os.path.sep.join(parts) + ".py") + ++ # Ensure self.fnpats is an iterable ++ if not isinstance(self.fnpats, Iterable): ++ self.fnpats = ["test_*.py", "*_test.py"] ++ + for pat in self.fnpats: + # if the pattern contains subdirectories ("tests/**.py" for example) we can't bail out based + # on the name alone because we need to match against the full path + if os.path.dirname(pat): + return False +- if fnmatch_ex(pat, path): ++ if fnmatch_ex(pat, str(path)): + return False + + if self._is_marked_for_rewrite(name, state): +@@ -223,8 +227,13 @@ class AssertionRewritingHook(importlib.abc.MetaPathFinder, importlib.abc.Loader) + # modules not passed explicitly on the command line are only + # rewritten if they match the naming convention for test files + fn_path = PurePath(fn) ++ ++ # Ensure self.fnpats is an iterable ++ if not isinstance(self.fnpats, Iterable): ++ self.fnpats = ["test_*.py", "*_test.py"] ++ + for pat in self.fnpats: +- if fnmatch_ex(pat, fn_path): ++ if fnmatch_ex(pat, str(fn_path)): + state.trace(f"matched test file {fn!r}") + return True + +@@ -443,6 +452,10 @@ def _saferepr(obj: object) -> str: + def _get_maxsize_for_saferepr(config: Optional[Config]) -> Optional[int]: + """Get `maxsize` configuration for saferepr based on the given config object.""" + verbosity = config.getoption("verbose") if config is not None else 0 ++ if isinstance(verbosity, str) and verbosity.isdigit(): ++ verbosity = int(verbosity) ++ elif not isinstance(verbosity, int): ++ verbosity = 0 + if verbosity >= 2: + return None + if verbosity >= 1: diff --git a/sub_swebench_dataset/fail_seed1_50/readme/readme.txt b/sub_swebench_dataset/fail_seed1_50/readme/readme.txt new file mode 100644 index 000000000..7aa4e8cdb --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/readme/readme.txt @@ -0,0 +1,86 @@ + +There are a total of 491 txt files listed. +In the original dataset, the distribution of pass case categories is: +astropy: 24 +django: 160 +matplotlib: 42 +mwaskom: 4 +pallets: 3 +psf: 9 +pydata: 29 +pylint-dev: 13 +pytest-dev: 20 +scikit-learn: 56 +sphinx-doc: 46 +sympy: 85 + + +After balanced sampling: +There are a total of 50 txt files listed. + +Django: 16 +Scikit-Learn: 6 +Sympy: 10 +sphinx-doc:5 +matplotlib: 4 +pydata: 3 +astropy: 2 +pytest-dev: 2 +psf: 1 +pylint-dev: 1 + + +After balanced sampling: +There are a total of 50 txt files listed. +[ + 'django__django-10554-diff.txt', + 'sphinx-doc__sphinx-7975-diff.txt', + 'pydata__xarray-5126-diff.txt', + 'matplotlib__matplotlib-23188-diff.txt', + 'sympy__sympy-21055-diff.txt', + 'astropy__astropy-13579-diff.txt', + 'django__django-14751-diff.txt', + 'sympy__sympy-11232-diff.txt', + 'scikit-learn__scikit-learn-14890-diff.txt', + 'django__django-15206-diff.txt', + 'sphinx-doc__sphinx-10449-diff.txt', + 'django__django-16816-diff.txt', + 'django__django-8630-diff.txt', + 'pytest-dev__pytest-9133-diff.txt', + 'scikit-learn__scikit-learn-10428-diff.txt', + 'django__django-14463-diff.txt', + 'sphinx-doc__sphinx-7597-diff.txt', + 'django__django-13933-diff.txt', + 'sphinx-doc__sphinx-9128-diff.txt', + 'sympy__sympy-15345-diff.txt', + 'sympy__sympy-18087-diff.txt', + 'django__django-15789-diff.txt', + 'scikit-learn__scikit-learn-25744-diff.txt', + 'sympy__sympy-15599-diff.txt', + 'pydata__xarray-3305-diff.txt', + 'django__django-13371-diff.txt', + 'django__django-15738-diff.txt', + 'django__django-16612-diff.txt', + 'django__django-11903-diff.txt', + 'astropy__astropy-13390-diff.txt', + 'scikit-learn__scikit-learn-11542-diff.txt', + 'matplotlib__matplotlib-24403-diff.txt', + 'django__django-13297-diff.txt', + 'matplotlib__matplotlib-21443-diff.txt', + 'django__django-12906-diff.txt', + 'scikit-learn__scikit-learn-10198-diff.txt', + 'sympy__sympy-16474-diff.txt', + 'psf__requests-1713-diff.txt', + 'scikit-learn__scikit-learn-10459-diff.txt', + 'sympy__sympy-21596-diff.txt', + 'sympy__sympy-12881-diff.txt', + 'pytest-dev__pytest-10356-diff.txt', + 'matplotlib__matplotlib-23047-diff.txt', + 'sympy__sympy-12301-diff.txt', + 'pylint-dev__pylint-6386-diff.txt', + 'sphinx-doc__sphinx-8621-diff.txt', + 'pydata__xarray-4248-diff.txt', + 'sympy__sympy-18030-diff.txt', + 'django__django-13512-diff.txt', + 'django__django-14894-diff.txt' +] \ No newline at end of file diff --git a/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-10428-diff.txt b/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-10428-diff.txt new file mode 100644 index 000000000..cb9e17e7b --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-10428-diff.txt @@ -0,0 +1,64 @@ +diff --git a/sklearn/utils/estimator_checks.py b/sklearn/utils/estimator_checks.py +index 398c12cbd..98367077e 100644 +--- a/sklearn/utils/estimator_checks.py ++++ b/sklearn/utils/estimator_checks.py +@@ -58,6 +58,8 @@ from sklearn.utils.validation import has_fit_parameter, _num_samples + from sklearn.preprocessing import StandardScaler + from sklearn.datasets import load_iris, load_boston, make_blobs + ++from sklearn.utils import check_random_state ++from numpy.testing import assert_array_almost_equal + + BOSTON = None + CROSS_DECOMPOSITION = ['PLSCanonical', 'PLSRegression', 'CCA', 'PLSSVD'] +@@ -570,7 +572,7 @@ def is_public_parameter(attr): + @ignore_warnings(category=(DeprecationWarning, FutureWarning)) + def check_dont_overwrite_parameters(name, estimator_orig): + # check that fit method only changes or sets private attributes +- if hasattr(estimator_orig.__init__, "deprecated_original"): ++ if hasattr(type(estimator_orig).__init__, "deprecated_original"): + # to not check deprecated classes + return + estimator = clone(estimator_orig) +@@ -830,8 +832,8 @@ def _check_transformer(name, transformer_orig, X, y): + # raises error on malformed input for transform + if hasattr(X, 'T'): + # If it's not an array, it does not have a 'T' property +- with assert_raises(ValueError, msg="The transformer {} does " +- "not raise an error when the number of " ++ with assert_raises(ValueError, msg="The transformer {} does not" ++ " raise an error when the number of " + "features in transform is different from" + " the number of features in " + "fit.".format(name)): +@@ -1944,3 +1946,30 @@ def check_decision_proba_consistency(name, estimator_orig): + a = estimator.predict_proba(X_test)[:, 1] + b = estimator.decision_function(X_test) + assert_array_equal(rankdata(a), rankdata(b)) ++ ++@ignore_warnings(category=(DeprecationWarning, FutureWarning)) ++def check_methods_subset_invariance(name, estimator_orig): ++ # Generate a random dataset ++ rng = check_random_state(0) ++ X = rng.normal(size=(100, 20)) ++ y = rng.randint(0, 2, size=(100,)) ++ ++ # Fit the estimator ++ estimator = clone(estimator_orig) ++ estimator.fit(X, y) ++ ++ # Generate a boolean mask for a subset ++ mask = rng.randint(0, 2, size=(100,)).astype(bool) ++ ++ # Methods to check ++ methods = ["predict", "predict_proba", "decision_function", "score_samples", "transform"] ++ ++ # Check method invariance on subset ++ for method in methods: ++ if hasattr(estimator, method): ++ est_method = getattr(estimator, method) ++ # Compare the results of the method on the full dataset and the subset ++ full_data_result = est_method(X) ++ subset_result = est_method(X[mask]) ++ assert_array_almost_equal(full_data_result[mask], subset_result, ++ err_msg="{} failed subset invariance check".format(method)) diff --git a/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-10687-diff.txt b/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-10687-diff.txt new file mode 100644 index 000000000..097f99455 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-10687-diff.txt @@ -0,0 +1,17 @@ +diff --git a/sklearn/linear_model/coordinate_descent.py b/sklearn/linear_model/coordinate_descent.py +index 32de16e2f..1ca4ad717 100644 +--- a/sklearn/linear_model/coordinate_descent.py ++++ b/sklearn/linear_model/coordinate_descent.py +@@ -447,7 +447,11 @@ def enet_path(X, y, l1_ratio=0.5, eps=1e-3, n_alphas=100, alphas=None, + dtype=X.dtype) + + if coef_init is None: +- coef_ = np.asfortranarray(np.zeros(coefs.shape[:-1], dtype=X.dtype)) ++ if self.fit_intercept: ++ # Plus one for intercept is not needed when fit_intercept=False ++ coef_ = np.asfortranarray(np.zeros(coefs.shape[:-1] + (1,), dtype=X.dtype)) ++ else: ++ coef_ = np.asfortranarray(np.zeros(coefs.shape[:-1], dtype=X.dtype)) + else: + coef_ = np.asfortranarray(coef_init, dtype=X.dtype) + diff --git a/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-13368-diff.txt b/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-13368-diff.txt new file mode 100644 index 000000000..29f93a334 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-13368-diff.txt @@ -0,0 +1,126 @@ +diff --git a/sklearn/model_selection/_split.py b/sklearn/model_selection/_split.py +index 0c09ff3b0..6527157fb 100644 +--- a/sklearn/model_selection/_split.py ++++ b/sklearn/model_selection/_split.py +@@ -644,29 +644,17 @@ class StratifiedKFold(_BaseKFold): + " be less than n_splits=%d." + % (min_groups, self.n_splits)), Warning) + +- # pre-assign each sample to a test fold index using individual KFold +- # splitting strategies for each class so as to respect the balance of +- # classes +- # NOTE: Passing the data corresponding to ith class say X[y==class_i] +- # will break when the data is not 100% stratifiable for all classes. +- # So we pass np.zeroes(max(c, n_splits)) as data to the KFold +- per_cls_cvs = [ +- KFold(self.n_splits, shuffle=self.shuffle, +- random_state=rng).split(np.zeros(max(count, self.n_splits))) +- for count in y_counts] +- +- test_folds = np.zeros(n_samples, dtype=np.int) +- for test_fold_indices, per_cls_splits in enumerate(zip(*per_cls_cvs)): +- for cls, (_, test_split) in zip(unique_y, per_cls_splits): +- cls_test_folds = test_folds[y == cls] +- # the test split can be too big because we used +- # KFold(...).split(X[:max(c, n_splits)]) when data is not 100% +- # stratifiable for all the classes +- # (we use a warning instead of raising an exception) +- # If this is the case, let's trim it: +- test_split = test_split[test_split < len(cls_test_folds)] +- cls_test_folds[test_split] = test_fold_indices +- test_folds[y == cls] = cls_test_folds ++ # Find the sorted list of instances for each class: ++ # (np.unique above performs a sort, so code is O(n logn) already) ++ class_indices = np.split(np.argsort(y_inversed, kind='mergesort'), np.cumsum(y_counts)[:-1]) ++ ++ # Ensure the minority class is represented in the test folds ++ if cls_count < self.n_splits: ++ # Assign one fold index per sample in the minority class ++ minority_class_indices = np.where(y_inversed == cls_index)[0] ++ for i, sample_index in enumerate(minority_class_indices): ++ # Assign fold indices in a round-robin fashion ++ test_folds[sample_index] = i % self.n_splits + + return test_folds + +@@ -885,11 +873,8 @@ class LeaveOneGroupOut(BaseCrossValidator): + y : object + Always ignored, exists for compatibility. + +- groups : array-like, with shape (n_samples,) +- Group labels for the samples used while splitting the dataset into +- train/test set. This 'groups' parameter must always be specified to +- calculate the number of splits, though the other parameters can be +- omitted. ++ groups : object ++ Always ignored, exists for compatibility. + + Returns + ------- +@@ -1356,12 +1341,11 @@ class ShuffleSplit(BaseShuffleSplit): + n_splits : int, default 10 + Number of re-shuffling & splitting iterations. + +- test_size : float, int, None, default=0.1 ++ test_size : float, int, None, optional + If float, should be between 0.0 and 1.0 and represent the proportion + of the dataset to include in the test split. If int, represents the + absolute number of test samples. If None, the value is set to the +- complement of the train size. By default (the parameter is +- unspecified), the value is set to 0.1. ++ complement of the train size. By default, the value is set to 0.1. + The default will change in version 0.21. It will remain 0.1 only + if ``train_size`` is unspecified, otherwise it will complement + the specified ``train_size``. +diff --git a/sklearn/model_selection/_validation.py b/sklearn/model_selection/_validation.py +index 4ffa462ff..313ab741f 100644 +--- a/sklearn/model_selection/_validation.py ++++ b/sklearn/model_selection/_validation.py +@@ -841,9 +841,14 @@ def _fit_and_predict(estimator, X, y, train, test, verbose, fit_params, + n_classes = len(set(y)) + if n_classes != len(estimator.classes_): + recommendation = ( +- 'To fix this, use a cross-validation ' +- 'technique resulting in properly ' +- 'stratified folds') ++ 'To fix this, consider using a cross-validation technique that ensures ' ++ 'each class is represented in every training fold, especially when ' ++ 'dealing with datasets that have a very small number of samples for ' ++ 'one or more classes.' ++ ) ++ print("Debug: estimator.classes_ =", estimator.classes_) ++ print("Debug: n_classes =", n_classes) ++ print("Debug: predictions =", predictions) + warnings.warn('Number of classes in training fold ({}) does ' + 'not match total number of classes ({}). ' + 'Results may not be appropriate for your use case. ' +@@ -873,13 +878,22 @@ def _fit_and_predict(estimator, X, y, train, test, verbose, fit_params, + len(estimator.classes_), + recommendation)) + +- float_min = np.finfo(predictions.dtype).min +- default_values = {'decision_function': float_min, +- 'predict_log_proba': float_min, +- 'predict_proba': 0} +- predictions_for_all_classes = np.full((_num_samples(predictions), +- n_classes), +- default_values[method]) ++ # Custom logic to ensure minority class is represented ++ if len(np.unique(y_train)) < n_classes: ++ # Find the label of the minority class ++ minority_class = np.setdiff1d(np.arange(n_classes), ++ estimator.classes_)[0] ++ # Use the minimum prediction value for the minority class ++ predictions_for_all_classes = np.full((_num_samples(predictions), ++ n_classes), ++ np.min(predictions)) ++ # Ensure the minority class has a prediction value ++ predictions_for_all_classes[:, minority_class] = np.min(predictions) ++ else: ++ # Use the default prediction values ++ predictions_for_all_classes = np.full((_num_samples(predictions), ++ n_classes), ++ np.min(predictions)) + predictions_for_all_classes[:, estimator.classes_] = predictions + predictions = predictions_for_all_classes + return predictions, test diff --git a/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-13554-diff.txt b/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-13554-diff.txt new file mode 100644 index 000000000..f80c2656e --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-13554-diff.txt @@ -0,0 +1,17 @@ +diff --git a/sklearn/metrics/pairwise.py b/sklearn/metrics/pairwise.py +index 5f87d880c..1abe1ba5a 100644 +--- a/sklearn/metrics/pairwise.py ++++ b/sklearn/metrics/pairwise.py +@@ -245,6 +245,12 @@ def euclidean_distances(X, Y=None, Y_norm_squared=None, squared=False, + else: + YY = row_norms(Y, squared=True)[np.newaxis, :] + ++ # Cast X and Y to float64 if they are float32, to improve precision ++ if X.dtype == np.float32: ++ X = X.astype(np.float64) ++ if Y is not None and Y.dtype == np.float32: ++ Y = Y.astype(np.float64) ++ + distances = safe_sparse_dot(X, Y.T, dense_output=True) + distances *= -2 + distances += XX diff --git a/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-13641-diff.txt b/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-13641-diff.txt new file mode 100644 index 000000000..660f270d1 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-13641-diff.txt @@ -0,0 +1,34 @@ +diff --git a/sklearn/feature_extraction/text.py b/sklearn/feature_extraction/text.py +index 9cdbace62..2884b11da 100644 +--- a/sklearn/feature_extraction/text.py ++++ b/sklearn/feature_extraction/text.py +@@ -1019,7 +1019,28 @@ class CountVectorizer(BaseEstimator, VectorizerMixin): + min_df = self.min_df + max_features = self.max_features + +- vocabulary, X = self._count_vocab(raw_documents, ++ # If a specific analyzer is provided, we use it instead of the built-in ones ++ if callable(self.analyzer): ++ # Since the user specified a custom analyzer, ++ # we assume that they want to analyze the files themselves. ++ processed_docs = [] ++ for doc in raw_documents: ++ if self.input == 'filename': ++ doc = self.decode(doc) ++ elif self.input == 'file': ++ doc = self.decode(doc.read()) ++ processed_docs.append(doc) ++ else: ++ # Preprocess the documents with the preprocessor and tokenizer ++ processed_docs = [] ++ for doc in raw_documents: ++ if self.input == 'filename': ++ doc = self.decode(doc) ++ elif self.input == 'file': ++ doc = self.decode(doc.read()) ++ processed_docs.append(self.preprocessor(doc)) ++ ++ vocabulary, X = self._count_vocab(processed_docs, + self.fixed_vocabulary_) + + if self.binary: diff --git a/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-13828-diff.txt b/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-13828-diff.txt new file mode 100644 index 000000000..96bf9ee55 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/scikit-learn__scikit-learn-13828-diff.txt @@ -0,0 +1,91 @@ +diff --git a/sklearn/cluster/affinity_propagation_.py b/sklearn/cluster/affinity_propagation_.py +index 1ee5213e0..ca54574ec 100644 +--- a/sklearn/cluster/affinity_propagation_.py ++++ b/sklearn/cluster/affinity_propagation_.py +@@ -111,8 +111,17 @@ def affinity_propagation(S, preference=None, convergence_iter=15, max_iter=200, + if S.shape[0] != S.shape[1]: + raise ValueError("S must be a square array (shape=%s)" % repr(S.shape)) + ++ from scipy.sparse import issparse, csr_matrix ++ + if preference is None: +- preference = np.median(S) ++ if issparse(S): ++ # Convert sparse matrix to CSR format for efficient operations ++ S_csr = csr_matrix(S) ++ # Calculate the median for sparse matrix ++ # This is a placeholder, actual implementation will vary ++ preference = calculate_sparse_median(S_csr) ++ else: ++ preference = np.median(S) + if damping < 0.5 or damping >= 1: + raise ValueError('damping must be >= 0.5 and < 1') + +@@ -125,13 +134,9 @@ def affinity_propagation(S, preference=None, convergence_iter=15, max_iter=200, + warnings.warn("All samples have mutually equal similarities. " + "Returning arbitrary cluster center(s).") + if preference.flat[0] >= S.flat[n_samples - 1]: +- return ((np.arange(n_samples), np.arange(n_samples), 0) +- if return_n_iter +- else (np.arange(n_samples), np.arange(n_samples))) ++ return (np.arange(n_samples), np.arange(n_samples), 0) if return_n_iter else (np.arange(n_samples), np.arange(n_samples), None) + else: +- return ((np.array([0]), np.array([0] * n_samples), 0) +- if return_n_iter +- else (np.array([0]), np.array([0] * n_samples))) ++ return (np.array([0]), np.array([0] * n_samples), 0) if return_n_iter else (np.array([0]), np.array([0] * n_samples), None) + + random_state = np.random.RandomState(0) + +@@ -149,8 +154,9 @@ def affinity_propagation(S, preference=None, convergence_iter=15, max_iter=200, + + # Execute parallel affinity propagation updates + e = np.zeros((n_samples, convergence_iter)) +- ++ E = np.zeros(n_samples, dtype=bool) + ind = np.arange(n_samples) ++ it = 0 + + for it in range(max_iter): + # tmp = A + S; compute responsibilities +@@ -225,11 +231,27 @@ def affinity_propagation(S, preference=None, convergence_iter=15, max_iter=200, + labels = np.array([-1] * n_samples) + cluster_centers_indices = [] + +- if return_n_iter: +- return cluster_centers_indices, labels, it + 1 +- else: +- return cluster_centers_indices, labels ++ return (cluster_centers_indices, labels, it + 1) if return_n_iter else (cluster_centers_indices, labels, None) ++ ++def calculate_sparse_median(S_csr): ++ """ ++ Calculate the median of the non-zero values in a sparse CSR matrix. + ++ Parameters ++ ---------- ++ S_csr : scipy.sparse.csr_matrix ++ Input sparse matrix in Compressed Sparse Row format. ++ ++ Returns ++ ------- ++ median_value : float ++ The median value of the non-zero elements in the sparse matrix. ++ """ ++ # Convert the sparse matrix to a dense 1D array of non-zero values ++ non_zero_values = S_csr.data ++ # Calculate the median of the non-zero values ++ median_value = np.median(non_zero_values) ++ return median_value + + ############################################################################### + +@@ -364,7 +386,7 @@ class AffinityPropagation(BaseEstimator, ClusterMixin): + y : Ignored + + """ +- X = check_array(X, accept_sparse='csr') ++ X = check_array(X, accept_sparse=True) + if self.affinity == "precomputed": + self.affinity_matrix_ = X + elif self.affinity == "euclidean": diff --git a/sub_swebench_dataset/fail_seed1_50/sphinx-doc__sphinx-7615-diff.txt b/sub_swebench_dataset/fail_seed1_50/sphinx-doc__sphinx-7615-diff.txt new file mode 100644 index 000000000..5eae4b4ba --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/sphinx-doc__sphinx-7615-diff.txt @@ -0,0 +1,53 @@ +diff --git a/setup.py b/setup.py +index a427d5493..d29c9a338 100644 +--- a/setup.py ++++ b/setup.py +@@ -21,7 +21,7 @@ install_requires = [ + 'sphinxcontrib-htmlhelp', + 'sphinxcontrib-serializinghtml', + 'sphinxcontrib-qthelp', +- 'Jinja2>=2.3', ++ 'Jinja2<3.1', + 'Pygments>=2.0', + 'docutils>=0.12', + 'snowballstemmer>=1.1', +diff --git a/sphinx/roles.py b/sphinx/roles.py +index 57d11c269..28eb2df90 100644 +--- a/sphinx/roles.py ++++ b/sphinx/roles.py +@@ -458,7 +458,7 @@ def emph_literal_role(typ: str, rawtext: str, text: str, lineno: int, inliner: I + + + class EmphasizedLiteral(SphinxRole): +- parens_re = re.compile(r'(\\\\|\\{|\\}|{|})') ++ parens_re = re.compile(r'(\\\\+|\\{|\\}|{|})') + + def run(self) -> Tuple[List[Node], List[system_message]]: + children = self.parse(self.text) +@@ -472,8 +472,11 @@ class EmphasizedLiteral(SphinxRole): + + stack = [''] + for part in self.parens_re.split(text): +- if part == '\\\\': # escaped backslash +- stack[-1] += '\\' ++ if part.startswith('\\\\'): # escaped backslashes ++ num_backslashes = len(part) ++ # According to RST spec, "\\" becomes "\", "\\\" becomes "\\", and so on ++ # So we divide by 2 the number of backslashes to render the correct amount ++ stack[-1] += '\\' * (num_backslashes // 2) + elif part == '{': + if len(stack) >= 2 and stack[-2] == "{": # nested + stack[-1] += "{" +diff --git a/tox.ini b/tox.ini +index d9f040544..bf39854b6 100644 +--- a/tox.ini ++++ b/tox.ini +@@ -28,7 +28,7 @@ extras = + setenv = + PYTHONWARNINGS = all,ignore::ImportWarning:importlib._bootstrap_external,ignore::DeprecationWarning:site,ignore::DeprecationWarning:distutils + commands= +- pytest --durations 25 {posargs} ++ pytest -rA --durations 25 {posargs} + + [testenv:flake8] + basepython = python3 diff --git a/sub_swebench_dataset/fail_seed1_50/sphinx-doc__sphinx-7975-diff.txt b/sub_swebench_dataset/fail_seed1_50/sphinx-doc__sphinx-7975-diff.txt new file mode 100644 index 000000000..3d47e348d --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/sphinx-doc__sphinx-7975-diff.txt @@ -0,0 +1,46 @@ +diff --git a/setup.py b/setup.py +index a404f1fa5..250ef5b61 100644 +--- a/setup.py ++++ b/setup.py +@@ -21,7 +21,7 @@ install_requires = [ + 'sphinxcontrib-htmlhelp', + 'sphinxcontrib-serializinghtml', + 'sphinxcontrib-qthelp', +- 'Jinja2>=2.3', ++ 'Jinja2<3.1', + 'Pygments>=2.0', + 'docutils>=0.12', + 'snowballstemmer>=1.1', +diff --git a/sphinx/environment/adapters/indexentries.py b/sphinx/environment/adapters/indexentries.py +index 5af213932..bdde4829a 100644 +--- a/sphinx/environment/adapters/indexentries.py ++++ b/sphinx/environment/adapters/indexentries.py +@@ -165,11 +165,11 @@ class IndexEntries: + if k.startswith('\N{RIGHT-TO-LEFT MARK}'): + k = k[1:] + letter = unicodedata.normalize('NFD', k[0])[0].upper() +- if letter.isalpha() or letter == '_': +- return letter +- else: +- # get all other symbols under one heading ++ if not letter.isalpha(): ++ # get all non-alphabetic symbols under one heading + return _('Symbols') ++ else: ++ return letter + else: + return v[2] + return [(key_, list(group)) +diff --git a/tox.ini b/tox.ini +index bddd822a6..34baee205 100644 +--- a/tox.ini ++++ b/tox.ini +@@ -27,7 +27,7 @@ extras = + setenv = + PYTHONWARNINGS = all,ignore::ImportWarning:importlib._bootstrap_external,ignore::DeprecationWarning:site,ignore::DeprecationWarning:distutils + commands= +- pytest --durations 25 {posargs} ++ pytest -rA --durations 25 {posargs} + + [testenv:flake8] + basepython = python3 diff --git a/sub_swebench_dataset/fail_seed1_50/sphinx-doc__sphinx-8579-diff.txt b/sub_swebench_dataset/fail_seed1_50/sphinx-doc__sphinx-8579-diff.txt new file mode 100644 index 000000000..11eda1d38 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/sphinx-doc__sphinx-8579-diff.txt @@ -0,0 +1,136 @@ +diff --git a/setup.py b/setup.py +index 8d40de1a8..05716fae1 100644 +--- a/setup.py ++++ b/setup.py +@@ -21,7 +21,7 @@ install_requires = [ + 'sphinxcontrib-htmlhelp', + 'sphinxcontrib-serializinghtml', + 'sphinxcontrib-qthelp', +- 'Jinja2>=2.3', ++ 'Jinja2<3.1', + 'Pygments>=2.0', + 'docutils>=0.12', + 'snowballstemmer>=1.1', +diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py +index 06a6293d2..6cebacade 100644 +--- a/sphinx/builders/linkcheck.py ++++ b/sphinx/builders/linkcheck.py +@@ -46,6 +46,7 @@ CHECK_IMMEDIATELY = 0 + QUEUE_POLL_SECS = 1 + DEFAULT_DELAY = 60.0 + ++print("DEBUG: linkcheck.py script started") + + class AnchorCheckParser(HTMLParser): + """Specialized HTML parser that looks for a specific anchor.""" +@@ -116,6 +117,7 @@ class CheckExternalLinksBuilder(Builder): + self.workers.append(thread) + + def check_thread(self) -> None: ++ print("DEBUG: Starting check_thread") + kwargs = {} + if self.app.config.linkcheck_timeout: + kwargs['timeout'] = self.app.config.linkcheck_timeout +@@ -182,7 +184,7 @@ class CheckExternalLinksBuilder(Builder): + **kwargs) + response.raise_for_status() + except (HTTPError, TooManyRedirects) as err: +- if isinstance(err, HTTPError) and err.response.status_code == 429: ++ if isinstance(err, HTTPError) and err.response is not None and err.response.status_code == 429: + raise + # retry with GET request if that fails, some servers + # don't like HEAD requests. +@@ -191,16 +193,16 @@ class CheckExternalLinksBuilder(Builder): + auth=auth_info, **kwargs) + response.raise_for_status() + except HTTPError as err: +- if err.response.status_code == 401: ++ if err.response is not None and err.response.status_code == 401: + # We'll take "Unauthorized" as working. + return 'working', ' - unauthorized', 0 +- elif err.response.status_code == 429: ++ elif err.response is not None and err.response.status_code == 429: + next_check = self.limit_rate(err.response) + if next_check is not None: + self.wqueue.put((next_check, uri, docname, lineno), False) + return 'rate-limited', '', 0 + return 'broken', str(err), 0 +- elif err.response.status_code == 503: ++ elif err.response is not None and err.response.status_code == 503: + # We'll take "Service Unavailable" as ignored. + return 'ignored', str(err), 0 + else: +@@ -256,6 +258,9 @@ class CheckExternalLinksBuilder(Builder): + return 'ignored', '', 0 + + # need to actually check the URI ++ status = 'unknown' ++ info = '' ++ code = 0 + for _ in range(self.app.config.linkcheck_retries): + status, info, code = check_uri() + if status != "broken": +@@ -287,17 +292,22 @@ class CheckExternalLinksBuilder(Builder): + # Sleep before putting message back in the queue to avoid + # waking up other threads. + time.sleep(QUEUE_POLL_SECS) ++ print("DEBUG: Re-queuing item. Queue size before put():", self.wqueue.qsize(), "Item:", (next_check, uri, docname, lineno)) + self.wqueue.put((next_check, uri, docname, lineno), False) +- self.wqueue.task_done() + continue ++ status = 'unknown' ++ info = '' ++ code = 0 + status, info, code = check(docname) + if status == 'rate-limited': + logger.info(darkgray('-rate limited- ') + uri + darkgray(' | sleeping...')) + else: + self.rqueue.put((uri, docname, lineno, status, info, code)) ++ print("DEBUG: task_done() called. Queue size before task_done():", self.wqueue.qsize()) + self.wqueue.task_done() + + def limit_rate(self, response: Response) -> Optional[float]: ++ delay = DEFAULT_DELAY # Initialize delay to default + next_check = None + retry_after = response.headers.get("Retry-After") + if retry_after: +@@ -387,8 +397,9 @@ class CheckExternalLinksBuilder(Builder): + self.write_entry('redirected ' + text, docname, filename, + lineno, uri + ' to ' + info) + self.write_linkstat(linkstat) ++ print(f"DEBUG: Finished processing result for {uri}") + +- def get_target_uri(self, docname: str, typ: str = None) -> str: ++ def get_target_uri(self, docname: str, typ: str = '') -> str: + return '' + + def get_outdated_docs(self) -> Set[str]: +@@ -398,6 +409,7 @@ class CheckExternalLinksBuilder(Builder): + return + + def write_doc(self, docname: str, doctree: Node) -> None: ++ print("DEBUG: Starting write_doc for", docname) + logger.info('') + n = 0 + +@@ -439,6 +451,7 @@ class CheckExternalLinksBuilder(Builder): + output.write('\n') + + def finish(self) -> None: ++ print("DEBUG: Finish method called") + self.wqueue.join() + # Shutdown threads. + for worker in self.workers: +diff --git a/tox.ini b/tox.ini +index dbb705a3a..9f4fc3a32 100644 +--- a/tox.ini ++++ b/tox.ini +@@ -28,7 +28,7 @@ setenv = + PYTHONWARNINGS = all,ignore::ImportWarning:importlib._bootstrap_external,ignore::DeprecationWarning:site,ignore::DeprecationWarning:distutils + PYTEST_ADDOPTS = {env:PYTEST_ADDOPTS:} --color yes + commands= +- python -X dev -m pytest --durations 25 {posargs} ++ python -X dev -m pytest -rA --durations 25 {posargs} + + [testenv:flake8] + basepython = python3 diff --git a/sub_swebench_dataset/fail_seed1_50/sphinx-doc__sphinx-9231-diff.txt b/sub_swebench_dataset/fail_seed1_50/sphinx-doc__sphinx-9231-diff.txt new file mode 100644 index 000000000..0b7230fcb --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/sphinx-doc__sphinx-9231-diff.txt @@ -0,0 +1,24 @@ +diff --git a/sphinx/builders/manpage.py b/sphinx/builders/manpage.py +index 532d2b8fe..897b310cf 100644 +--- a/sphinx/builders/manpage.py ++++ b/sphinx/builders/manpage.py +@@ -65,7 +65,7 @@ class ManualPageBuilder(Builder): + docname, name, description, authors, section = info + if docname not in self.env.all_docs: + logger.warning(__('"man_pages" config value references unknown ' +- 'document %s'), docname) ++ 'document %s'), docname) + continue + if isinstance(authors, str): + if authors: +@@ -79,8 +79,8 @@ class ManualPageBuilder(Builder): + docsettings.section = section + + if self.config.man_make_section_directory: +- ensuredir(path.join(self.outdir, str(section))) +- targetname = '%s/%s.%s' % (section, name, section) ++ ensuredir(path.join(self.outdir, 'man' + str(section))) ++ targetname = 'man%s/%s.%s' % (section, name, section) + else: + targetname = '%s.%s' % (name, section) + diff --git a/sub_swebench_dataset/fail_seed1_50/sphinx-doc__sphinx-9602-diff.txt b/sub_swebench_dataset/fail_seed1_50/sphinx-doc__sphinx-9602-diff.txt new file mode 100644 index 000000000..c77545be9 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/sphinx-doc__sphinx-9602-diff.txt @@ -0,0 +1,122 @@ +diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py +index cf4318cda..6f04adb28 100644 +--- a/sphinx/util/typing.py ++++ b/sphinx/util/typing.py +@@ -73,13 +73,15 @@ TitleGetter = Callable[[nodes.Node], str] + Inventory = Dict[str, Dict[str, Tuple[str, str, str, str]]] + + +-def get_type_hints(obj: Any, globalns: Dict = None, localns: Dict = None) -> Dict[str, Any]: ++def get_type_hints(obj: Any, globalns: Optional[Dict] = None, localns: Optional[Dict] = None) -> Dict[str, Any]: + """Return a dictionary containing type hints for a function, method, module or class object. + + This is a simple wrapper of `typing.get_type_hints()` that does not raise an error on + runtime. + """ + from sphinx.util.inspect import safe_getattr # lazy loading ++ globalns = globalns if globalns is not None else {} ++ localns = localns if localns is not None else {} + + try: + return typing.get_type_hints(obj, globalns, localns) +@@ -118,11 +120,11 @@ def restify(cls: Optional[Type]) -> str: + elif inspect.isNewType(cls): + return ':class:`%s`' % cls.__name__ + elif UnionType and isinstance(cls, UnionType): +- if len(cls.__args__) > 1 and None in cls.__args__: +- args = ' | '.join(restify(a) for a in cls.__args__ if a) ++ if getattr(cls, '__args__', None) is not None and len(cls.__args__) > 1 and None in cls.__args__: ++ args = ' | '.join(restify(a) for a in cls.__args__ if a) if cls.__args__ is not None else '' + return 'Optional[%s]' % args + else: +- return ' | '.join(restify(a) for a in cls.__args__) ++ return ' | '.join(restify(a) for a in cls.__args__) if getattr(cls, '__args__', None) is not None else '' + elif cls.__module__ in ('__builtin__', 'builtins'): + if hasattr(cls, '__args__'): + return ':class:`%s`\\ [%s]' % ( +@@ -145,9 +147,9 @@ def _restify_py37(cls: Optional[Type]) -> str: + from sphinx.util import inspect # lazy loading + + if (inspect.isgenericalias(cls) and +- cls.__module__ == 'typing' and cls.__origin__ is Union): ++ cls.__module__ == 'typing' and getattr(cls, '_name', None) == 'Callable'): + # Union +- if len(cls.__args__) > 1 and cls.__args__[-1] is NoneType: ++ if getattr(cls, '__args__', None) is not None and len(cls.__args__) > 1 and cls.__args__[-1] is NoneType: + if len(cls.__args__) > 2: + args = ', '.join(restify(a) for a in cls.__args__[:-1]) + return ':obj:`~typing.Optional`\\ [:obj:`~typing.Union`\\ [%s]]' % args +@@ -173,12 +175,13 @@ def _restify_py37(cls: Optional[Type]) -> str: + elif all(is_system_TypeVar(a) for a in cls.__args__): + # Suppress arguments if all system defined TypeVars (ex. Dict[KT, VT]) + pass +- elif cls.__module__ == 'typing' and cls._name == 'Callable': ++ elif cls.__module__ == 'typing' and getattr(origin, '_name', None) == 'Callable': + args = ', '.join(restify(a) for a in cls.__args__[:-1]) + text += r"\ [[%s], %s]" % (args, restify(cls.__args__[-1])) + elif cls.__module__ == 'typing' and getattr(origin, '_name', None) == 'Literal': +- text += r"\ [%s]" % ', '.join(repr(a) for a in cls.__args__) +- elif cls.__args__: ++ # Handle Literal types without creating class references ++ return f'Literal[{", ".join(repr(a) for a in cls.__args__)}]' ++ elif getattr(cls, '__args__', None): + text += r"\ [%s]" % ", ".join(restify(a) for a in cls.__args__) + + return text +@@ -368,28 +371,28 @@ def _stringify_py37(annotation: Any) -> str: + else: + return 'Optional[%s]' % stringify(annotation.__args__[0]) + else: +- args = ', '.join(stringify(a) for a in annotation.__args__) ++ args = ', '.join(stringify(a) for a in annotation.__args__) if annotation.__args__ is not None else '' + return 'Union[%s]' % args + elif qualname == 'types.Union': + if len(annotation.__args__) > 1 and None in annotation.__args__: +- args = ' | '.join(stringify(a) for a in annotation.__args__ if a) ++ args = ' | '.join(stringify(a) for a in annotation.__args__ if a) if annotation.__args__ is not None else '' + return 'Optional[%s]' % args + else: +- return ' | '.join(stringify(a) for a in annotation.__args__) ++ return ' | '.join(stringify(a) for a in annotation.__args__) if annotation.__args__ is not None else '' + elif qualname == 'Callable': + args = ', '.join(stringify(a) for a in annotation.__args__[:-1]) + returns = stringify(annotation.__args__[-1]) + return '%s[[%s], %s]' % (qualname, args, returns) + elif qualname == 'Literal': + args = ', '.join(repr(a) for a in annotation.__args__) +- return '%s[%s]' % (qualname, args) ++ return f'Literal[{args}]' + elif str(annotation).startswith('typing.Annotated'): # for py39+ + return stringify(annotation.__args__[0]) + elif all(is_system_TypeVar(a) for a in annotation.__args__): + # Suppress arguments if all system defined TypeVars (ex. Dict[KT, VT]) +- return qualname ++ pass + else: +- args = ', '.join(stringify(a) for a in annotation.__args__) ++ args = ', '.join(stringify(a) for a in annotation.__args__) if annotation.__args__ is not None else '' + return '%s[%s]' % (qualname, args) + + return qualname +@@ -447,7 +450,7 @@ def _stringify_py36(annotation: Any) -> str: + else: + return 'Optional[%s]' % stringify(params[0]) + else: +- param_str = ', '.join(stringify(p) for p in params) ++ param_str = ', '.join(stringify(p) for p in params) if params is not None else '' + return 'Union[%s]' % param_str + + return qualname +diff --git a/tox.ini b/tox.ini +index b6a67fd85..483f2df92 100644 +--- a/tox.ini ++++ b/tox.ini +@@ -28,7 +28,7 @@ setenv = + PYTHONWARNINGS = all,ignore::ImportWarning:importlib._bootstrap_external,ignore::DeprecationWarning:site,ignore::DeprecationWarning:distutils,ignore::DeprecationWarning:pip._vendor.packaging.version + PYTEST_ADDOPTS = {env:PYTEST_ADDOPTS:} --color yes + commands= +- python -X dev -m pytest --durations 25 {posargs} ++ python -X dev -m pytest -rA --durations 25 {posargs} + + [testenv:flake8] + basepython = python3 diff --git a/sub_swebench_dataset/fail_seed1_50/sympy__sympy-11232-diff.txt b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-11232-diff.txt new file mode 100644 index 000000000..7d7388043 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-11232-diff.txt @@ -0,0 +1,14 @@ +diff --git a/sympy/simplify/cse_main.py b/sympy/simplify/cse_main.py +index e49ba26a70..45ed59fe93 100644 +--- a/sympy/simplify/cse_main.py ++++ b/sympy/simplify/cse_main.py +@@ -515,8 +515,7 @@ def cse(exprs, symbols=None, optimizations=None, postprocess=None, + for i, (sym, subtree) in enumerate(replacements): + subtree = postprocess_for_cse(subtree, optimizations) + replacements[i] = (sym, subtree) +- reduced_exprs = [postprocess_for_cse(e, optimizations) +- for e in reduced_exprs] ++ reduced_exprs = [e.xreplace(replacements) for e in reduced_exprs] + + # Get the matrices back + for i, e in enumerate(exprs): diff --git a/sub_swebench_dataset/fail_seed1_50/sympy__sympy-12301-diff.txt b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-12301-diff.txt new file mode 100644 index 000000000..6e3ba1b2c --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-12301-diff.txt @@ -0,0 +1,118 @@ +diff --git a/sympy/simplify/cse_main.py b/sympy/simplify/cse_main.py +index a771dd377b..e2fc4b2cd4 100644 +--- a/sympy/simplify/cse_main.py ++++ b/sympy/simplify/cse_main.py +@@ -13,6 +13,11 @@ + + from . import cse_opts + ++import logging ++ ++logging.basicConfig(filename='/home/ubuntu/sympy/sympy/simplify/cse_debug.log', level=logging.DEBUG, ++ format='%(asctime)s:%(levelname)s:%(message)s') ++ + # (preprocessor, postprocessor) pairs which are commonly useful. They should + # each take a sympy expression and return a possibly transformed expression. + # When used in the function ``cse()``, the target expressions will be transformed +@@ -158,11 +163,13 @@ def pairwise_most_common(sets): + from sympy.utilities.iterables import subsets + from collections import defaultdict + most = -1 ++ best_keys = [] ++ best = defaultdict(list) + for i, j in subsets(list(range(len(sets))), 2): + com = sets[i] & sets[j] + if com and len(com) > most: +- best = defaultdict(list) + best_keys = [] ++ best = defaultdict(list) + most = len(com) + if len(com) == most: + if com not in best_keys: +@@ -393,6 +400,7 @@ def restore(dafi): + # split muls into commutative + commutative_muls = set() + for m in muls: ++ logging.debug(f"Splitting Mul objects into commutative and non-commutative parts: {m}") + c, nc = m.args_cnc(cset=True) + if c: + c_mul = m.func(*c) +@@ -400,6 +408,7 @@ def restore(dafi): + opt_subs[m] = m.func(c_mul, m.func(*nc), evaluate=False) + if len(c) > 1: + commutative_muls.add(c_mul) ++ logging.debug(f"Finished splitting Mul objects into commutative and non-commutative parts: {m}") + + _match_common_args(Add, adds) + _match_common_args(Mul, commutative_muls) +@@ -417,12 +426,17 @@ def tree_cse(exprs, symbols, opt_subs=None, order='canonical', ignore=()): + The expressions to reduce. + symbols : infinite iterator yielding unique Symbols + The symbols used to label the common subexpressions which are pulled +- out. ++ out. The ``numbered_symbols`` generator is useful. The default is a ++ stream of symbols of the form "x0", "x1", etc. This must be an ++ infinite iterator. + opt_subs : dictionary of expression substitutions + The expressions to be substituted before any CSE action is performed. + order : string, 'none' or 'canonical' +- The order by which Mul and Add arguments are processed. For large +- expressions where speed is a concern, use the setting order='none'. ++ The order by which Mul and Add arguments are processed. If set to ++ 'canonical', arguments will be canonically ordered. If set to 'none', ++ ordering will be faster but dependent on expressions hashes, thus ++ machine dependent and variable. For large expressions where speed is a ++ concern, use the setting order='none'. + ignore : iterable of Symbols + Substitutions containing any Symbol from ``ignore`` will be ignored. + """ +@@ -496,6 +510,7 @@ def _rebuild(expr): + # If enabled, parse Muls and Adds arguments by order to ensure + # replacement order independent from hashes + if order != 'none': ++ logging.debug(f"Before canonical ordering: {expr}") + if isinstance(expr, (Mul, MatMul)): + c, nc = expr.args_cnc() + if c == [1]: +@@ -506,6 +521,7 @@ def _rebuild(expr): + args = list(ordered(expr.args)) + else: + args = expr.args ++ logging.debug(f"After canonical ordering: {expr}") + else: + args = expr.args + +@@ -515,6 +531,8 @@ def _rebuild(expr): + else: + new_expr = expr + ++ logging.debug(f"Rebuilding expression: {expr}") ++ + if orig_expr in to_eliminate: + try: + sym = next(symbols) +@@ -546,6 +564,7 @@ def _rebuild(expr): + # R = [(x0, d + f), (x1, b + d)] + # C = [e + x0 + x1, g + x0 + x1, a + c + d + f + g] + # but the args of C[-1] should not be `(a + c, d + f + g)` ++ logging.debug(f"Before hollow nesting prevention: {exprs}") + nested = [[i for i in f.args if isinstance(i, f.func)] for f in exprs] + for i in range(len(exprs)): + F = reduced_exprs[i].func +@@ -563,6 +582,7 @@ def _rebuild(expr): + else: + args.append(a) + reduced_exprs[i] = F(*args) ++ logging.debug(f"After hollow nesting prevention: {reduced_exprs}") + + return replacements, reduced_exprs + +@@ -644,6 +664,8 @@ def cse(exprs, symbols=None, optimizations=None, postprocess=None, + from sympy.matrices import (MatrixBase, Matrix, ImmutableMatrix, + SparseMatrix, ImmutableSparseMatrix) + ++ logging.debug("Starting cse function") ++ + # Handle the case if just one expression was passed. + if isinstance(exprs, (Basic, MatrixBase)): + exprs = [exprs] diff --git a/sub_swebench_dataset/fail_seed1_50/sympy__sympy-13031-diff.txt b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-13031-diff.txt new file mode 100644 index 000000000..f6854b522 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-13031-diff.txt @@ -0,0 +1,2045 @@ +diff --git a/.travis.yml b/.travis.yml +index 48c05b187f..1baf10d530 100644 +--- a/.travis.yml ++++ b/.travis.yml +@@ -9,7 +9,6 @@ env: + - SPLIT="4/4" TEST_SYMPY="true" + global: + - secure: "YIEZal9EBTL+fg2YmoZoS8Bvt3eAVUOZjb38CtqpzR2CCSXWoUk35KG23m2NknlY1iKfYJyt7XWBszT/VKOQEbWQq7PIakV4vIByrWacgBxy1x3WC+rZoW7TX+JJiL+y942qIYbMoNMMB8xFpE5RDLSjSecMpFhJJXoafVTvju8=" +-dist: trusty + + python: + - 2.7 +@@ -27,7 +26,6 @@ matrix: + - TEST_THEANO="true" + - TEST_ASCII="true" + - TEST_AUTOWRAP="true" +- - TEST_SYMENGINE="true" + addons: + apt: + packages: +@@ -43,7 +41,6 @@ matrix: + - TEST_THEANO="true" + - TEST_ASCII="true" + - TEST_AUTOWRAP="true" +- - TEST_SYMENGINE="true" + addons: + apt: + packages: +@@ -67,7 +64,6 @@ matrix: + - texlive-xetex + - texlive-fonts-recommended + - texlive-latex-extra +- - latexmk + - lmodern + - librsvg2-bin + - imagemagick +@@ -97,6 +93,9 @@ matrix: + env: + - TEST_SLOW="true" + - SPLIT="3/3" ++ - python: 3.5 ++ env: ++ - TEST_SYMENGINE="true" + + # Everything here and below is in the allow_failures. The need to be + # duplicated here and in that section below. +@@ -235,7 +234,7 @@ before_install: + pip install fastcache; + fi + - if [[ "${TEST_SPHINX}" == "true" ]]; then +- pip install "sphinx" "docutils" doctr; ++ pip install "sphinx==1.3.1" "docutils==0.12" doctr; + fi + - | + if [[ "${TEST_MATPLOTLIB}" == "true" || "${TEST_SYMENGINE}" == "true" ]]; then +diff --git a/AUTHORS b/AUTHORS +index d89b4c0d68..c7a641de7a 100644 +--- a/AUTHORS ++++ b/AUTHORS +@@ -3,7 +3,7 @@ order of the date of their first contribution), except those who explicitly + didn't want to be mentioned. People with a * next to their names are not found + in the metadata of the git history. This file is generated automatically by + running `./bin/authors_update.py`. +-There are a total of 619 authors. ++There are a total of 618 authors. + + Ondřej Čertík + Fabian Pedregosa +@@ -621,6 +621,5 @@ Vincent Delecroix + Michael Sparapany + harsh_jain + Nathan Goldbaum +-latot + Kenneth Lyons +-Jiri Kuncar ++latot +diff --git a/bin/test_travis.sh b/bin/test_travis.sh +index efd4fa1bed..9de7d200b8 100755 +--- a/bin/test_travis.sh ++++ b/bin/test_travis.sh +@@ -12,7 +12,7 @@ fi + if [[ "${TEST_SPHINX}" == "true" ]]; then + echo "Testing SPHINX" + cd doc +- make html ++ make html-errors + make man + make latex + cd _build/latex +@@ -27,6 +27,11 @@ if [[ "${TEST_SAGE}" == "true" ]]; then + ./bin/test -k tensorflow + fi + ++if [[ "${TEST_SYMENGINE}" == "true" ]]; then ++ echo "Testing SYMENGINE" ++ export USE_SYMENGINE=1 ++fi ++ + # We change directories to make sure that we test the installed version of + # sympy. + mkdir empty +@@ -126,13 +131,10 @@ fi + + + if [[ "${TEST_SYMENGINE}" == "true" ]]; then +- echo "Testing SYMENGINE" +- export USE_SYMENGINE=1 + cat << EOF | python + print('Testing SymEngine') + import sympy + if not sympy.test('sympy/physics/mechanics'): + raise Exception('Tests failed') + EOF +- unset USE_SYMENGINE + fi +diff --git a/doc/Makefile b/doc/Makefile +index d2f822b12b..e29496e7a9 100644 +--- a/doc/Makefile ++++ b/doc/Makefile +@@ -17,8 +17,9 @@ ALLSPHINXOPTSapi = -d _build/doctrees-api $(SPHINXOPTS) api + ALLSPHINXOPTSlatex = -d _build/doctrees-latex -D latex_paper_size=$(PAPER) \ + $(SPHINXOPTS) src + +-.PHONY: changes cheatsheet clean help html htmlapi htmlhelp info latex \ +- linkcheck livehtml texinfo web logo man ++.PHONY: changes cheatsheet clean help html html-errors \ ++ htmlapi htmlhelp info latex linkcheck livehtml \ ++ texinfo web logo man + + .SUFFIXES: .pdf .svg + +@@ -28,6 +29,7 @@ help: + @echo " cheatsheet to make the Cheatsheet" + @echo " clean to remove generated files" + @echo " html to make standalone HTML files" ++ @echo " html-errors to make the standalone HTML files, stopping on any errors or warnings" + @echo " htmlapi to make HTML API docs" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " info to make Texinfo files and run them through makeinfo" +@@ -44,7 +46,6 @@ clean: + -rm -rf sphinx + -rm -f $(PDFFILES) + +-html: SPHINXOPTS += -W + html: _build/logo/sympy-notailtext-favicon.ico + mkdir -p src/.static + mkdir -p _build/html +@@ -55,6 +56,9 @@ html: _build/logo/sympy-notailtext-favicon.ico + @echo + @echo "Build finished. The HTML pages are in _build/html." + ++html-errors: SPHINXOPTS += -W ++html-errors: html ++ + htmlapi: + mkdir -p api/.static + mkdir -p api/modules +@@ -82,8 +86,7 @@ htmlhelp: + latex: $(PDFFILES) + mkdir -p _build/latex _build/doctrees + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTSlatex) _build/latex +- sed -i'' -e "s/pdflatex/xelatex/g" _build/latex/Makefile +- sed -i'' -e "s/latexmk/latexmk -xelatex/g" _build/latex/Makefile ++ sed -i "s/pdflatex/xelatex/g" _build/latex/Makefile + @echo + @echo "Build finished; the LaTeX files are in _build/latex." + @echo "Run \`make all' in that directory to run these through xelatex." +diff --git a/doc/ext/numpydoc.py b/doc/ext/numpydoc.py +index b47000757b..a575060320 100644 +--- a/doc/ext/numpydoc.py ++++ b/doc/ext/numpydoc.py +@@ -29,6 +29,7 @@ + raise RuntimeError("Sphinx 1.0.1 or newer is required") + + from docscrape_sphinx import get_doc_object, SphinxDocString ++from sphinx.util.compat import Directive + + if sys.version_info[0] >= 3: + sixu = lambda s: s +diff --git a/doc/src/conf.py b/doc/src/conf.py +index 6066701cee..f4c5afdfd1 100644 +--- a/doc/src/conf.py ++++ b/doc/src/conf.py +@@ -40,8 +40,6 @@ + # The master toctree document. + master_doc = 'index' + +-suppress_warnings = ['ref.citation', 'ref.footnote'] +- + # General substitutions. + project = 'SymPy' + copyright = '2017 SymPy Development Team' +diff --git a/release/Dockerfile b/release/Dockerfile +index 0f7296cf48..61a5c92562 100644 +--- a/release/Dockerfile ++++ b/release/Dockerfile +@@ -1,9 +1,9 @@ + FROM continuumio/anaconda3 + +-WORKDIR /root ++WORKDIR /home + + RUN apt-get update \ +- && apt-get install -y libc6-i386 libc6 linux-headers-amd64 git make zip graphviz inkscape texlive-xetex texlive-fonts-recommended texlive-latex-extra librsvg2-bin docbook2x latexmk \ ++ && apt-get install -y libc6-i386 libc6 linux-headers-amd64 git make zip graphviz inkscape texlive-xetex texlive-fonts-recommended texlive-latex-extra librsvg2-bin docbook2x \ + && apt-get -y clean + + RUN conda config --add channels conda-forge +@@ -15,12 +15,15 @@ RUN /opt/conda/bin/pip install xonda + + # Make matplotlib tests work + # https://stackoverflow.com/questions/2801882/generating-a-png-with-matplotlib-when-display-is-undefined +-ENV MATPLOTLIBRC=/root/matplotlibrc ++ENV MATPLOTLIBRC=/home/matplotlibrc + RUN mkdir -p $MATPLOTLIBRC + RUN echo "backend : Agg" > $MATPLOTLIBRC/matplotlibrc + + RUN git clone git://github.com/sympy/sympy.git ++# This can be removed once this is in master ++RUN cd /home/sympy && git checkout 1.1 ++RUN cd /home/sympy && git pull + +-WORKDIR /root/sympy/release ++WORKDIR /home/sympy/release + + ENTRYPOINT ["./pull_and_run_rever.sh"] +diff --git a/release/README.md b/release/README.md +index ce5f8ef342..8fd4bde90f 100644 +--- a/release/README.md ++++ b/release/README.md +@@ -1,6 +1,16 @@ +-**NOTE: The release script is currently in the process of moving from +-Vagrant/fabric to Docker/rever. The fabfile.py is left here for reference, but +-all release processes should be done with release.sh and rever.xsh.** ++TODO Fix release script to stop support for Python 2.6 and 3.2 (Issue #10463) ++ ++# Prepare the VM ++ ++First execute: ++ ++ vagrant up ++ fab vagrant prepare ++ ++which will prepare the VM (install packages, cache sympy repository, etc.). ++ ++You only need to execute this once. It will take a while if you have never run ++it before, because it has to download a lot of stuff. + + # Release + +@@ -24,39 +34,50 @@ First, make sure that you have done the following things + - Push the release branch up to origin, and make a pull request for it against + master. + +-It is important to create a new branch because that lets master continue as +-normal. The release script will automatically checkout the release branch from ++It is important to create a new branch because that lets master continue ++as normal. The fab script will automatically checkout the release branch from + origin, which is why you need to push it (it determines what the release + branch by just looking at what branch you have checked out locally, so make + sure you are on the release branch when you release). It is important to + change the version number because it uses that in naming the tarballs it + creates. + +-Next, make sure you have Docker installed. +- +-**TODO: Fix the release script to pull sympy/sympy-release from Dockerhub.** ++If you want to test the release process without pushing a branch to the ++official repo, you can push a branch to your fork and use `fab vagrant ++release:fork='username'`, where `username` is your GitHub username. Note that ++once you do the actual release, you should do it in a branch in the official ++GitHub repo. **NOTE**: If your fork does not have all the tags of the ++official repo, then the code that finds the previous version will not work ++correctly. Hence, you may see things like more authors in the authors list ++than you should. To remedy this, be sure to do `git fetch origin --tags` and ++`git push github --tags`. + + Once you have done these things, execute: + +- ./release.sh ++ fab vagrant release + +-where `` is the release branch (e.g., `0.7.3`), and `` is the +-release version (e.g., `0.7.3rc1`). ++this create release tarballs and put them all into a new "release" directory ++of the current directory. + +-On Linux, you may need to use `sudo` to execute this. ++# Testing things + +-This will run all the release scripts. If they are successful, they will +-create release tarballs and put them all into a new "release-VERSION" +-directory of the current directory. Most likely they will fail the first time, +-in which case you will need to investigate why and fix things (e.g., update +-authors, run tests, update whitelists in `rever.xsh`, fix setup.py). The whole +-script can take about an hour or so to run (depending on how long the tests +-take). Every time you re-run the script, it pulls from the branch and runs +-everything from scratch. ++The full test suite is not run by fabric, because we leave that to ++Travis. However, there are things that need to be tested specific to the ++release. Most of these things are done automatically by the release command ++(like testing that the tarball can be installed), but one thing must be tested ++manually, because it has to be inspected by hand, namely, making sure that the ++tarballs contain everything, and don't contain any junk files. + +-At the end it will print two things, the list of authors, and the md5 sums. +-Copy the list of authors into the release notes. You should verify that the +-md5 sums of the release files are the same as what are printed. ++Run ++ ++ fab vagrant show_files:arg ++ ++to show the files in the tarball, where `arg` is `source` or `html`. You'll ++probably want to pipe the output of this into `less`, so that you can inspect ++it. ++ ++You should also open the pdf and make sure that it has built correctly, and ++open the html docs and make sure that they have built correctly. + + # Tagging the release + +@@ -82,14 +103,11 @@ everything is right before pushing. + + # Uploading + +-**WARNING: This stuff does not fully work yet. Some development on `rever.xsh` +-may be required.** +- + Before you release, you need to push the tag up, as described above. + + Release candidates should be uploaded to GitHub only. + +- rever VERSION -a GitHub_release ++ fab vagrant GitHub_release + + This will create the release on GitHub for the tag, and upload the files to + it. Do not upload release candidates to PyPI, as `pip` and `easy_install` +@@ -102,12 +120,19 @@ only supported via OAuth, so using a token is required. + + You (obviously) need push access to create a GitHub release. + ++If you want to test this before doing it, use ++ ++ fab vagrant GitHub_release:draft=True ++ ++This will make the release not visible until you go to the web interface and ++publish it. You can also set the `user` and `repo` flags to test against a ++different GitHub repo. ++ + For final releases, you should upload to both GitHub and PyPI. The command + +- rever VERSION -a upload ++ fab vagrant upload + +-will do both of these (**TODO: This function has not been translated from the +-fabfile yet**). You will need admin access to the SymPy PyPI project. ++will do both of these. You will need admin access to the SymPy PyPI project. + + Note that if either of these commands fails for some reason, you will very + likely need to go into the web interface and clean some things up before you +@@ -117,24 +142,43 @@ can upload again. + + You should now update the websites. Only do this for final releases. The command + +- rever VERSION -a update_websites ++ fab vagrant update_websites + +-will update docs.sympy.org and sympy.org (**TODO: This isn't fully translated +-from the fabfile yet.**). You will need to have local clones ++will update docs.sympy.org and sympy.org. You will need to have local clones + of these repos, and push access to them (obviously). **Note, this command + will commit and push the changes automatically.** + + The other website that needs to be updated is SymPy Live. You should make this + as a pull request to the Live repo. + +-# Updating the Dockerfile ++# Other ++ ++You can run all the SymPy tests by running: ++ ++ fab vagrant test_sympy ++ ++To get the md5 sums of all the files, use ++ ++ fab md5 ++ ++To list the files in the tarball use ++ ++ fab vagrant show_files:arg ++ ++where `arg` is `source` or `html`, for the Python sources and the html docs, ++respectively. Note that the source code is already checked automatically ++against the files in git and a whitelist. ++ ++You can obtain all available commands by: ++ ++ fab -l + +-If you change the Dockerfile, you will need to run ++# Restarting from scratch + +- docker build -f Dockerfile . -t sympy/sympy-release ++Run + +-Once you have it working, push the changes up to Dockerhub ++ vagrant destroy + +- docker push sympy/sympy-release ++You can also delete the releases that it has built + +-You'll need access to the sympy org, ask Aaron or Ondřej if you need it. ++ rm -rf release +diff --git a/release/Vagrantfile b/release/Vagrantfile +new file mode 100644 +index 0000000000..9cd2ce08e9 +--- /dev/null ++++ b/release/Vagrantfile +@@ -0,0 +1,10 @@ ++# -*- mode: ruby -*- ++# vi: set ft=ruby : ++ ++Vagrant::Config.run do |config| ++ #config.vm.box = "precise64" ++ #config.vm.box_url = "http://files.vagrantup.com/precise64.box" ++ config.vm.box = "precise32" ++ config.vm.box_url = "http://files.vagrantup.com/precise32.box" ++ config.ssh.forward_agent = true ++end +diff --git a/release/fabfile.py b/release/fabfile.py +index d25acdb727..7e5eee1ad1 100644 +--- a/release/fabfile.py ++++ b/release/fabfile.py +@@ -308,7 +308,7 @@ def build_docs(): + with virtualenv(venv): + with cd("/home/vagrant/repos/sympy/doc"): + run("make clean") +- run("make html") ++ run("make html-errors") + run("make man") + with cd("/home/vagrant/repos/sympy/doc/_build"): + run("mv html {html-nozip}".format(**tarball_formatter())) +diff --git a/release/release.sh b/release/release.sh +index 785b81da13..b65928bfd7 100755 +--- a/release/release.sh ++++ b/release/release.sh +@@ -19,4 +19,5 @@ if [[ -z $2 ]]; then + $2=$1 + fi + +-docker run -t -v "$parent_path/release-$2":/root/release sympy/sympy-release "$@" ++docker build -f Dockerfile . -t sympy-release ++docker run -v "$parent_path/release-$2":/home/release sympy-release "$@" +diff --git a/release/rever.xsh b/release/rever.xsh +index 818c135d26..0b55397ab8 100644 +--- a/release/rever.xsh ++++ b/release/rever.xsh +@@ -3,8 +3,6 @@ + $XONSH_SHOW_TRACEBACK = True + $RAISE_SUBPROC_ERROR = True + +-trace on +- + import os + import sys + import unicodedata +@@ -15,8 +13,6 @@ from contextlib import contextmanager + import json + import glob + import stat +-import configparser +-import time + + import requests + from requests.auth import HTTPBasicAuth +@@ -46,8 +42,6 @@ $ACTIVITIES = [ + # 'tag', + ] + +-version = $VERSION +- + # Work around https://github.com/ergs/rever/issues/15 + @activity + def _version(): +@@ -83,12 +77,12 @@ def source_tarball(): + + @activity(deps={'_version'}) + def build_docs(): +- with run_in_conda_env(['sphinx', 'docutils', 'numpy', 'mpmath'], ++ with run_in_conda_env(['sphinx=1.3.1', 'docutils=0.12', 'numpy', 'mpmath'], + envname='sympy-release-docs'): + + cd doc + make clean +- make html ++ make html-errors + make man + + cd _build +@@ -109,7 +103,7 @@ def build_docs(): + @activity(deps={'source_tarball', 'build_docs'}) + def copy_release_files(): + ls dist +- cp dist/* /root/release/ ++ cp dist/* /home/release/ + + @activity(deps={'source_tarball'}) + def test_tarball27(): +@@ -209,7 +203,7 @@ def _md5(print_=True, local=False): + if local: + out = $(md5sum @(release_files())) + else: +- out = $(md5sum /root/release/*) ++ out = $(md5sum /home/release/*) + # Remove the release/ part for printing. Useful for copy-pasting into the + # release notes. + out = [i.split() for i in out.strip().split('\n')] +@@ -231,15 +225,6 @@ def GitHub_release(): + # Prevent default undo + pass + +-@activity(deps={'_version'}) +-def update_docs(): +- _update_docs() +- +- +-@activity(deps={'_version'}) +-def update_sympy_org(): +- _update_sympy_org() +- + # HELPER FUNCTIONS + + def test_tarball(py_version): +@@ -252,10 +237,10 @@ def test_tarball(py_version): + + + with run_in_conda_env(['python=%s' % py_version], 'test-install-%s' % py_version): +- cp @('/root/release/{source}'.format(**tarball_format)) @("releasetar.tar".format(**tarball_format)) ++ cp @('/home/release/{source}'.format(**tarball_format)) @("releasetar.tar".format(**tarball_format)) + tar xvf releasetar.tar + +- cd @("/root/{source-orig-notar}".format(**tarball_format)) ++ cd @("/home/{source-orig-notar}".format(**tarball_format)) + python setup.py install + python -c "import sympy; print(sympy.__version__); print('sympy installed successfully')" + +@@ -339,9 +324,9 @@ def show_files(file, print_=True): + # TODO: Test the unarchived name. See + # https://github.com/sympy/sympy/issues/7087. + if file == 'source': +- ret = $(tar tf @("/root/release/{source}".format(**tarball_format))) ++ ret = $(tar tf @("/home/release/{source}".format(**tarball_format))) + elif file == 'html': +- ret = $(unzip -l @("/root/release/{html}".format(**tarball_format))) ++ ret = $(unzip -l @("/home/release/{html}".format(**tarball_format))) + else: + raise ValueError(file + " is not valid") + if print_: +@@ -826,137 +811,6 @@ the online documentation.' + ('pdf', '''Pdf version of the html documentation.''',), + ]) + +-def get_location(location): +- """ +- Read/save a location from the configuration file. +- """ +- locations_file = os.path.expanduser('~/.sympy/sympy-locations') +- config = configparser.SafeConfigParser() +- config.read(locations_file) +- the_location = config.has_option("Locations", location) and config.get("Locations", location) +- if not the_location: +- the_location = input("Where is the SymPy {location} directory? ".format(location=location)) +- if not config.has_section("Locations"): +- config.add_section("Locations") +- config.set("Locations", location, the_location) +- save = raw_input("Save this to file [yes]? ") +- if save.lower().strip() in ['', 'y', 'yes']: +- print("saving to ", locations_file) +- with open(locations_file, 'w') as f: +- config.write(f) +- else: +- print("Reading {location} location from config".format(location=location)) +- +- return os.path.abspath(os.path.expanduser(the_location)) +- +-def _update_docs(docs_location=None): +- """ +- Update the docs hosted at docs.sympy.org +- """ +- docs_location = docs_location or get_location("docs") +- +- print("Docs location:", docs_location) +- +- current_version = version +- previous_version = get_previous_version_tag().lstrip('sympy-') +- +- release_dir = os.path.abspath(os.path.expanduser(os.path.join(os.path.curdir, 'release'))) +- docs_zip = os.path.abspath(os.path.join(release_dir, 'release-' + version, +- get_tarball_name('html'))) +- +- cd @(docs_location) +- +- # Check that the docs directory is clean +- git diff --exit-code > /dev/null +- git diff --cached --exit-code > /dev/null +- +- git pull +- +- # See the README of the docs repo. We have to remove the old redirects, +- # move in the new docs, and create redirects. +- print("Removing redirects from previous version") +- rm -r @(previous_version) +- print("Moving previous latest docs to old version") +- mv latest @(previous_version) +- +- print("Unzipping docs into repo") +- unzip @(docs_zip) > /dev/null +- mv @(get_tarball_name('html-nozip')) @(version) +- +- print("Writing new version to releases.txt") +- with open(os.path.join(docs_location, "releases.txt"), 'a') as f: +- f.write("{version}:SymPy {version}\n".format(version=current_version)) +- +- print("Generating indexes") +- ./generate_indexes.py +- mv @(current_version) latest +- +- print("Generating redirects") +- ./generate_redirects.py latest @(current_version) +- +- print("Committing") +- git add -A @(version) latest +- git commit -a -m @('Updating docs to {version}'.format(version=current_version)) +- +- print("Pushing") +- git push origin +- +- cd @(release_dir) +- cd .. +- +-def _update_sympy_org(website_location=None): +- """ +- Update sympy.org +- +- This just means adding an entry to the news section. +- """ +- website_location = website_location or get_location("sympy.github.com") +- +- release_dir = os.path.abspath(os.path.expanduser(os.path.join(os.path.curdir, 'release'))) +- +- cd @(website_location) +- +- # Check that the website directory is clean +- git diff --exit-code > /dev/null +- git diff --cached --exit-code > /dev/null +- +- git pull +- +- release_date = time.gmtime(os.path.getctime(os.path.join(release_dir, +- 'release-' + version, tarball_format['source']))) +- release_year = str(release_date.tm_year) +- release_month = str(release_date.tm_mon) +- release_day = str(release_date.tm_mday) +- +- with open(os.path.join(website_location, "templates", "index.html"), 'r') as f: +- lines = f.read().split('\n') +- # We could try to use some html parser, but this way is easier +- try: +- news = lines.index(r"

{% trans %}News{% endtrans %}

") +- except ValueError: +- error("index.html format not as expected") +- lines.insert(news + 2, # There is a

after the news line. Put it +- # after that. +- r""" {{ datetime(""" + release_year + """, """ + release_month + """, """ + release_day + """) }} {% trans v='""" + version + """' %}Version {{ v }} released{% endtrans %} ({% trans %}changes{% endtrans %})
+-

""") +- +- with open(os.path.join(website_location, "templates", "index.html"), 'w') as f: +- print("Updating index.html template") +- f.write('\n'.join(lines)) +- +- print("Generating website pages") +- ./generate +- +- print("Committing") +- git commit -a -m @('Add {version} to the news'.format(version=version)) +- +- print("Pushing") +- git push origin +- +- cd @(release_dir) +- cd .. +- +- + ## TARBALL WHITELISTS + + # If a file does not end up in the tarball that should, add it to setup.py if +diff --git a/setup.py b/setup.py +index 96d337fbd0..cacdf43032 100755 +--- a/setup.py ++++ b/setup.py +@@ -361,13 +361,13 @@ def run(self): + 'Topic :: Scientific/Engineering :: Mathematics', + 'Topic :: Scientific/Engineering :: Physics', + 'Programming Language :: Python :: 2', ++ 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.2', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', +- 'Programming Language :: Python :: 3.6', + ], + install_requires=['mpmath>=%s' % mpmath_version], + **extra_kwargs +diff --git a/sympy/core/add.py b/sympy/core/add.py +index 2ec4fff073..f2a5d0dd77 100644 +--- a/sympy/core/add.py ++++ b/sympy/core/add.py +@@ -509,10 +509,9 @@ def _eval_is_imaginary(self): + im_I.append(a*S.ImaginaryUnit) + else: + return +- b = self.func(*nz) +- if b.is_zero: ++ if self.func(*nz).is_zero: + return fuzzy_not(self.func(*im_I).is_zero) +- elif b.is_zero is False: ++ elif self.func(*nz).is_zero is False: + return False + + def _eval_is_zero(self): +@@ -540,15 +539,12 @@ def _eval_is_zero(self): + return + if z == len(self.args): + return True +- if len(nz) == len(self.args): +- return None +- b = self.func(*nz) +- if b.is_zero: ++ if self.func(*nz).is_zero: + if not im_or_z and not im: + return True + if im and not im_or_z: + return False +- if b.is_zero is False: ++ if self.func(*nz).is_zero is False: + return False + + def _eval_is_odd(self): +@@ -580,11 +576,11 @@ def _eval_is_positive(self): + v = _monotonic_sign(a) + if v is not None: + s = v + c +- if s != self and s.is_positive and a.is_nonnegative: ++ if s.is_positive and a.is_nonnegative: + return True + if len(self.free_symbols) == 1: + v = _monotonic_sign(self) +- if v is not None and v != self and v.is_positive: ++ if v is not None and v.is_positive: + return True + pos = nonneg = nonpos = unknown_sign = False + saw_INF = set() +@@ -633,11 +629,11 @@ def _eval_is_nonnegative(self): + v = _monotonic_sign(a) + if v is not None: + s = v + c +- if s != self and s.is_nonnegative: ++ if s.is_nonnegative: + return True + if len(self.free_symbols) == 1: + v = _monotonic_sign(self) +- if v is not None and v != self and v.is_nonnegative: ++ if v is not None and v.is_nonnegative: + return True + + def _eval_is_nonpositive(self): +@@ -648,11 +644,11 @@ def _eval_is_nonpositive(self): + v = _monotonic_sign(a) + if v is not None: + s = v + c +- if s != self and s.is_nonpositive: ++ if s.is_nonpositive: + return True + if len(self.free_symbols) == 1: + v = _monotonic_sign(self) +- if v is not None and v != self and v.is_nonpositive: ++ if v is not None and v.is_nonpositive: + return True + + def _eval_is_negative(self): +@@ -664,11 +660,11 @@ def _eval_is_negative(self): + v = _monotonic_sign(a) + if v is not None: + s = v + c +- if s != self and s.is_negative and a.is_nonpositive: ++ if s.is_negative and a.is_nonpositive: + return True + if len(self.free_symbols) == 1: + v = _monotonic_sign(self) +- if v is not None and v != self and v.is_negative: ++ if v is not None and v.is_negative: + return True + neg = nonpos = nonneg = unknown_sign = False + saw_INF = set() +diff --git a/sympy/core/basic.py b/sympy/core/basic.py +index 04452ce9a0..d4b335c9cf 100644 +--- a/sympy/core/basic.py ++++ b/sympy/core/basic.py +@@ -1,7 +1,6 @@ + """Base class for all the objects in SymPy""" + from __future__ import print_function, division + from collections import Mapping, defaultdict +-from itertools import chain + + from .assumptions import BasicMeta, ManagedProperties + from .cache import cacheit +@@ -1661,13 +1660,8 @@ def _exec_constructor_postprocessors(cls, obj): + if i in Basic._constructor_postprocessor_mapping: + for k, v in Basic._constructor_postprocessor_mapping[i].items(): + postprocessors[k].extend([j for j in v if j not in postprocessors[k]]) +- else: +- postprocessor_mappings = ( +- Basic._constructor_postprocessor_mapping[cls].items() +- for cls in type(i).mro() +- if cls in Basic._constructor_postprocessor_mapping +- ) +- for k, v in chain.from_iterable(postprocessor_mappings): ++ elif type(i) in Basic._constructor_postprocessor_mapping: ++ for k, v in Basic._constructor_postprocessor_mapping[type(i)].items(): + postprocessors[k].extend([j for j in v if j not in postprocessors[k]]) + except TypeError: + pass +diff --git a/sympy/core/expr.py b/sympy/core/expr.py +index cc815aec49..2ffa49a351 100644 +--- a/sympy/core/expr.py ++++ b/sympy/core/expr.py +@@ -346,9 +346,9 @@ def _from_mpmath(x, prec): + + @property + def is_number(self): +- """Returns True if ``self`` has no free symbols. +- It will be faster than ``if not self.free_symbols``, however, since +- ``is_number`` will fail as soon as it hits a free symbol. ++ """Returns True if 'self' has no free symbols. ++ It will be faster than `if not self.free_symbols`, however, since ++ `is_number` will fail as soon as it hits a free symbol. + + Examples + ======== +diff --git a/sympy/core/power.py b/sympy/core/power.py +index 61d7a8f928..e221fa252b 100644 +--- a/sympy/core/power.py ++++ b/sympy/core/power.py +@@ -1062,14 +1062,7 @@ def _eval_is_rational(self): + return e.is_zero + + def _eval_is_algebraic(self): +- def _is_one(expr): +- try: +- return (expr - 1).is_zero +- except ValueError: +- # when the operation is not allowed +- return False +- +- if self.base.is_zero or _is_one(self.base): ++ if self.base.is_zero or (self.base - 1).is_zero: + return True + elif self.exp.is_rational: + if self.base.is_algebraic is False: +@@ -1077,7 +1070,7 @@ def _is_one(expr): + return self.base.is_algebraic + elif self.base.is_algebraic and self.exp.is_algebraic: + if ((fuzzy_not(self.base.is_zero) +- and fuzzy_not(_is_one(self.base))) ++ and fuzzy_not((self.base - 1).is_zero)) + or self.base.is_integer is False + or self.base.is_irrational): + return self.exp.is_rational +diff --git a/sympy/core/sympify.py b/sympy/core/sympify.py +index 402fdcc7dc..fbe187ffd1 100644 +--- a/sympy/core/sympify.py ++++ b/sympy/core/sympify.py +@@ -50,7 +50,6 @@ class CantSympify(object): + """ + pass + +- + def sympify(a, locals=None, convert_xor=True, strict=False, rational=False, + evaluate=None): + """Converts an arbitrary expression to a type that can be used inside SymPy. +@@ -257,13 +256,12 @@ def sympify(a, locals=None, convert_xor=True, strict=False, rational=False, + else: + return a + +- # Support for basic numpy datatypes ++ #Support for basic numpy datatypes + if type(a).__module__ == 'numpy': + import numpy as np + if np.isscalar(a): + if not isinstance(a, np.floating): +- func = converter[complex] if np.iscomplex(a) else sympify +- return func(np.asscalar(a)) ++ return sympify(np.asscalar(a)) + else: + try: + from sympy.core.numbers import Float +diff --git a/sympy/core/tests/test_constructor_postprocessor.py b/sympy/core/tests/test_constructor_postprocessor.py +index c434a51267..e85223752f 100644 +--- a/sympy/core/tests/test_constructor_postprocessor.py ++++ b/sympy/core/tests/test_constructor_postprocessor.py +@@ -24,16 +24,11 @@ class SymbolRemovesOtherSymbols(Symbol): + # Test class for a symbol that removes other symbols in `Mul`. + pass + ++ + Basic._constructor_postprocessor_mapping[SymbolRemovesOtherSymbols] = { + "Mul": [_postprocess_SymbolRemovesOtherSymbols], + } + +-class SubclassSymbolInMulOnce(SymbolInMulOnce): +- pass +- +-class SubclassSymbolRemovesOtherSymbols(SymbolRemovesOtherSymbols): +- pass +- + + def test_constructor_postprocessors1(): + a = symbols("a") +@@ -52,24 +47,4 @@ def test_constructor_postprocessors1(): + assert (3*w).args == (3, w) + assert 3*a*w**2 == 3*w**2 + assert 3*a*x**3*w**2 == 3*w**2 +- assert set((w + x).args) == set((x, w)) +- +- +-def test_constructor_postprocessors2(): +- a = symbols("a") +- x = SubclassSymbolInMulOnce("x") +- y = SubclassSymbolInMulOnce("y") +- assert isinstance(3*x, Mul) +- assert (3*x).args == (3, x) +- assert x*x == x +- assert 3*x*x == 3*x +- assert 2*x*x + x == 3*x +- assert x**3*y*y == x*y +- assert x**5 + y*x**3 == x + x*y +- +- w = SubclassSymbolRemovesOtherSymbols("w") +- assert x*w == w +- assert (3*w).args == (3, w) +- assert 3*a*w**2 == 3*w**2 +- assert 3*a*x**3*w**2 == 3*w**2 +- assert set((w + x).args) == set((x, w)) ++ assert (w + x).args == (x, w) +diff --git a/sympy/core/tests/test_sympify.py b/sympy/core/tests/test_sympify.py +index 6e87b3ea54..71e881179d 100644 +--- a/sympy/core/tests/test_sympify.py ++++ b/sympy/core/tests/test_sympify.py +@@ -560,15 +560,11 @@ def equal(x, y): + skip('numpy not installed.Abort numpy tests.') + + assert sympify(np.bool_(1)) is S(True) +- try: +- assert equal( +- sympify(np.int_(1234567891234567891)), S(1234567891234567891)) +- assert equal( +- sympify(np.intp(1234567891234567891)), S(1234567891234567891)) +- except OverflowError: +- # May fail on 32-bit systems: Python int too large to convert to C long +- pass ++ assert equal( ++ sympify(np.int_(1234567891234567891)), S(1234567891234567891)) + assert equal(sympify(np.intc(1234567891)), S(1234567891)) ++ assert equal( ++ sympify(np.intp(1234567891234567891)), S(1234567891234567891)) + assert equal(sympify(np.int8(-123)), S(-123)) + assert equal(sympify(np.int16(-12345)), S(-12345)) + assert equal(sympify(np.int32(-1234567891)), S(-1234567891)) +@@ -582,11 +578,8 @@ def equal(x, y): + assert equal(sympify(np.float32(1.123456)), Float(1.123456, precision=24)) + assert equal(sympify(np.float64(1.1234567891234)), + Float(1.1234567891234, precision=53)) +- assert equal(sympify(np.longdouble(1.123456789)), +- Float(1.123456789, precision=80)) + assert equal(sympify(np.complex64(1 + 2j)), S(1.0 + 2.0*I)) + assert equal(sympify(np.complex128(1 + 2j)), S(1.0 + 2.0*I)) +- assert equal(sympify(np.longcomplex(1 + 2j)), S(1.0 + 2.0*I)) + + try: + assert equal(sympify(np.float96(1.123456789)), +diff --git a/sympy/functions/special/delta_functions.py b/sympy/functions/special/delta_functions.py +index 894c3918d3..e98b61f18e 100644 +--- a/sympy/functions/special/delta_functions.py ++++ b/sympy/functions/special/delta_functions.py +@@ -369,15 +369,15 @@ def _sage_(self): + class Heaviside(Function): + """Heaviside Piecewise function + +- Heaviside function has the following properties [1]_: ++ Heaviside function has the following properties [*]_: + + 1) ``diff(Heaviside(x),x) = DiracDelta(x)`` + ``( 0, if x < 0`` +- 2) ``Heaviside(x) = < ( undefined if x==0 [1]`` ++ 2) ``Heaviside(x) = < ( undefined if x==0 [*]`` + ``( 1, if x > 0`` + 3) ``Max(0,x).diff(x) = Heaviside(x)`` + +- .. [1] Regarding to the value at 0, Mathematica defines ``H(0) = 1``, ++ .. [*] Regarding to the value at 0, Mathematica defines ``H(0) = 1``, + but Maple uses ``H(0) = undefined``. Different application areas + may have specific conventions. For example, in control theory, it + is common practice to assume ``H(0) == 0`` to match the Laplace +@@ -407,8 +407,8 @@ class Heaviside(Function): + References + ========== + +- .. [2] http://mathworld.wolfram.com/HeavisideStepFunction.html +- .. [3] http://dlmf.nist.gov/1.16#iv ++ .. [1] http://mathworld.wolfram.com/HeavisideStepFunction.html ++ .. [2] http://dlmf.nist.gov/1.16#iv + + """ + +diff --git a/sympy/integrals/prde.py b/sympy/integrals/prde.py +index 706578fb0f..78eeb44859 100644 +--- a/sympy/integrals/prde.py ++++ b/sympy/integrals/prde.py +@@ -986,10 +986,9 @@ def is_deriv_k(fa, fd, DE): + dfa, dfd = dfa.cancel(dfd, include=True) + + # Our assumption here is that each monomial is recursively transcendental +- if len(DE.exts) != len(DE.D): ++ if len(DE.L_K) + len(DE.E_K) != len(DE.D) - 1: + if [i for i in DE.cases if i == 'tan'] or \ +- (set([i for i in DE.cases if i == 'primitive']) - +- set(DE.indices('log'))): ++ set([i for i in DE.cases if i == 'primitive']) - set(DE.L_K): + raise NotImplementedError("Real version of the structure " + "theorems with hypertangent support is not yet implemented.") + +@@ -997,8 +996,8 @@ def is_deriv_k(fa, fd, DE): + raise NotImplementedError("Nonelementary extensions not supported " + "in the structure theorems.") + +- E_part = [DE.D[i].quo(Poly(DE.T[i], DE.T[i])).as_expr() for i in DE.indices('exp')] +- L_part = [DE.D[i].as_expr() for i in DE.indices('log')] ++ E_part = [DE.D[i].quo(Poly(DE.T[i], DE.T[i])).as_expr() for i in DE.E_K] ++ L_part = [DE.D[i].as_expr() for i in DE.L_K] + + lhs = Matrix([E_part + L_part]) + rhs = Matrix([dfa.as_expr()/dfd.as_expr()]) +@@ -1016,12 +1015,10 @@ def is_deriv_k(fa, fd, DE): + raise NotImplementedError("Cannot work with non-rational " + "coefficients in this case.") + else: +- terms = ([DE.extargs[i] for i in DE.indices('exp')] + +- [DE.T[i] for i in DE.indices('log')]) ++ terms = DE.E_args + [DE.T[i] for i in DE.L_K] + ans = list(zip(terms, u)) + result = Add(*[Mul(i, j) for i, j in ans]) +- argterms = ([DE.T[i] for i in DE.indices('exp')] + +- [DE.extargs[i] for i in DE.indices('log')]) ++ argterms = [DE.T[i] for i in DE.E_K] + DE.L_args + l = [] + ld = [] + for i, j in zip(argterms, u): +@@ -1098,10 +1095,9 @@ def is_log_deriv_k_t_radical(fa, fd, DE, Df=True): + dfa, dfd = fa, fd + + # Our assumption here is that each monomial is recursively transcendental +- if len(DE.exts) != len(DE.D): ++ if len(DE.L_K) + len(DE.E_K) != len(DE.D) - 1: + if [i for i in DE.cases if i == 'tan'] or \ +- (set([i for i in DE.cases if i == 'primitive']) - +- set(DE.indices('log'))): ++ set([i for i in DE.cases if i == 'primitive']) - set(DE.L_K): + raise NotImplementedError("Real version of the structure " + "theorems with hypertangent support is not yet implemented.") + +@@ -1109,8 +1105,8 @@ def is_log_deriv_k_t_radical(fa, fd, DE, Df=True): + raise NotImplementedError("Nonelementary extensions not supported " + "in the structure theorems.") + +- E_part = [DE.D[i].quo(Poly(DE.T[i], DE.T[i])).as_expr() for i in DE.indices('exp')] +- L_part = [DE.D[i].as_expr() for i in DE.indices('log')] ++ E_part = [DE.D[i].quo(Poly(DE.T[i], DE.T[i])).as_expr() for i in DE.E_K] ++ L_part = [DE.D[i].as_expr() for i in DE.L_K] + + lhs = Matrix([E_part + L_part]) + rhs = Matrix([dfa.as_expr()/dfd.as_expr()]) +@@ -1132,15 +1128,13 @@ def is_log_deriv_k_t_radical(fa, fd, DE, Df=True): + else: + n = reduce(ilcm, [i.as_numer_denom()[1] for i in u]) + u *= n +- terms = ([DE.T[i] for i in DE.indices('exp')] + +- [DE.extargs[i] for i in DE.indices('log')]) ++ terms = [DE.T[i] for i in DE.E_K] + DE.L_args + ans = list(zip(terms, u)) + result = Mul(*[Pow(i, j) for i, j in ans]) + + # exp(f) will be the same as result up to a multiplicative + # constant. We now find the log of that constant. +- argterms = ([DE.extargs[i] for i in DE.indices('exp')] + +- [DE.T[i] for i in DE.indices('log')]) ++ argterms = DE.E_args + [DE.T[i] for i in DE.L_K] + const = cancel(fa.as_expr()/fd.as_expr() - + Add(*[Mul(i, j/n) for i, j in zip(argterms, u)])) + +diff --git a/sympy/integrals/risch.py b/sympy/integrals/risch.py +index 0fd66f9d31..b1f2494326 100644 +--- a/sympy/integrals/risch.py ++++ b/sympy/integrals/risch.py +@@ -130,8 +130,12 @@ class DifferentialExtension(object): + For back-substitution after integration. + - backsubs: A (possibly empty) list of further substitutions to be made on + the final integral to make it look more like the integrand. +- - exts: +- - extargs: ++ - E_K: List of the positions of the exponential extensions in T. ++ - E_args: The arguments of each of the exponentials in E_K. ++ - L_K: List of the positions of the logarithmic extensions in T. ++ - L_args: The arguments of each of the logarithms in L_K. ++ (See the docstrings of is_deriv_k() and is_log_deriv_k_t_radical() for ++ more information on E_K, E_args, L_K, and L_args) + - cases: List of string representations of the cases of T. + - t: The top level extension variable, as defined by the current level + (see level below). +@@ -157,8 +161,8 @@ class DifferentialExtension(object): + # of the class easily (the memory use doesn't matter too much, since we + # only create one DifferentialExtension per integration). Also, it's nice + # to have a safeguard when debugging. +- __slots__ = ('f', 'x', 'T', 'D', 'fa', 'fd', 'Tfuncs', 'backsubs', +- 'exts', 'extargs', 'cases', 'case', 't', 'd', 'newf', 'level', ++ __slots__ = ('f', 'x', 'T', 'D', 'fa', 'fd', 'Tfuncs', 'backsubs', 'E_K', ++ 'E_args', 'L_K', 'L_args', 'cases', 'case', 't', 'd', 'newf', 'level', + 'ts', 'dummy') + + def __init__(self, f=None, x=None, handle_first='log', dummy=False, extension=None, rewrite_complex=False): +@@ -512,8 +516,8 @@ def _exp_part(self, exps): + darg = darga.as_expr()/dargd.as_expr() + self.t = next(self.ts) + self.T.append(self.t) +- self.extargs.append(arg) +- self.exts.append('exp') ++ self.E_args.append(arg) ++ self.E_K.append(len(self.T) - 1) + self.D.append(darg.as_poly(self.t, expand=False)*Poly(self.t, + self.t, expand=False)) + if self.dummy: +@@ -566,8 +570,8 @@ def _log_part(self, logs): + darg = darga.as_expr()/dargd.as_expr() + self.t = next(self.ts) + self.T.append(self.t) +- self.extargs.append(arg) +- self.exts.append('log') ++ self.L_args.append(arg) ++ self.L_K.append(len(self.T) - 1) + self.D.append(cancel(darg.as_expr()/arg).as_poly(self.t, + expand=False)) + if self.dummy: +@@ -587,11 +591,11 @@ def _important_attrs(self): + + Used for testing and debugging purposes. + +- The attributes are (fa, fd, D, T, Tfuncs, backsubs, +- exts, extargs). ++ The attributes are (fa, fd, D, T, Tfuncs, backsubs, E_K, E_args, ++ L_K, L_args). + """ + return (self.fa, self.fd, self.D, self.T, self.Tfuncs, +- self.backsubs, self.exts, self.extargs) ++ self.backsubs, self.E_K, self.E_args, self.L_K, self.L_args) + + # NOTE: this printing doesn't follow the Python's standard + # eval(repr(DE)) == DE, where DE is the DifferentialExtension object +@@ -627,8 +631,7 @@ def reset(self): + self.T = [self.x] + self.D = [Poly(1, self.x)] + self.level = -1 +- self.exts = [None] +- self.extargs = [None] ++ self.L_K, self.E_K, self.L_args, self.E_args = [], [], [], [] + if self.dummy: + self.ts = numbered_symbols('t', cls=Dummy) + else: +@@ -640,30 +643,6 @@ def reset(self): + self.Tfuncs = [] + self.newf = self.f + +- def indices(self, extension): +- """ +- Args: +- extension (str): represents a valid extension type. +- +- Returns: +- list: A list of indices of 'exts' where extension of +- type 'extension' is present. +- +- Examples +- ======== +- +- >>> from sympy.integrals.risch import DifferentialExtension +- >>> from sympy import log, exp +- >>> from sympy.abc import x +- >>> DE = DifferentialExtension(log(x) + exp(x), x, handle_first='exp') +- >>> DE.indices('log') +- [2] +- >>> DE.indices('exp') +- [1] +- +- """ +- return [i for i, ext in enumerate(self.exts) if ext == extension] +- + def increment_level(self): + """ + Increment the level of self. +diff --git a/sympy/integrals/tests/test_prde.py b/sympy/integrals/tests/test_prde.py +index 42ab5e5177..77a6c4d8aa 100644 +--- a/sympy/integrals/tests/test_prde.py ++++ b/sympy/integrals/tests/test_prde.py +@@ -237,48 +237,48 @@ def test_limited_integrate(): + + + def test_is_log_deriv_k_t_radical(): +- DE = DifferentialExtension(extension={'D': [Poly(1, x)], 'exts': [None], +- 'extargs': [None]}) ++ DE = DifferentialExtension(extension={'D': [Poly(1, x)], 'E_K': [], 'L_K': [], ++ 'E_args': [], 'L_args': []}) + assert is_log_deriv_k_t_radical(Poly(2*x, x), Poly(1, x), DE) is None + + DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(2*t1, t1), Poly(1/x, t2)], +- 'exts': [None, 'exp', 'log'], 'extargs': [None, 2*x, x]}) ++ 'L_K': [2], 'E_K': [1], 'L_args': [x], 'E_args': [2*x]}) + assert is_log_deriv_k_t_radical(Poly(x + t2/2, t2), Poly(1, t2), DE) == \ + ([(t1, 1), (x, 1)], t1*x, 2, 0) + # TODO: Add more tests + + DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t0, t0), Poly(1/x, t)], +- 'exts': [None, 'exp', 'log'], 'extargs': [None, x, x]}) ++ 'L_K': [2], 'E_K': [1], 'L_args': [x], 'E_args': [x]}) + assert is_log_deriv_k_t_radical(Poly(x + t/2 + 3, t), Poly(1, t), DE) == \ + ([(t0, 2), (x, 1)], x*t0**2, 2, 3) + + + def test_is_deriv_k(): + DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t1), Poly(1/(x + 1), t2)], +- 'exts': [None, 'log', 'log'], 'extargs': [None, x, x + 1]}) ++ 'L_K': [1, 2], 'E_K': [], 'L_args': [x, x + 1], 'E_args': []}) + assert is_deriv_k(Poly(2*x**2 + 2*x, t2), Poly(1, t2), DE) == \ + ([(t1, 1), (t2, 1)], t1 + t2, 2) + + DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t1), Poly(t2, t2)], +- 'exts': [None, 'log', 'exp'], 'extargs': [None, x, x]}) ++ 'L_K': [1], 'E_K': [2], 'L_args': [x], 'E_args': [x]}) + assert is_deriv_k(Poly(x**2*t2**3, t2), Poly(1, t2), DE) == \ + ([(x, 3), (t1, 2)], 2*t1 + 3*x, 1) + # TODO: Add more tests, including ones with exponentials + + DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(2/x, t1)], +- 'exts': [None, 'log'], 'extargs': [None, x**2]}) ++ 'L_K': [1], 'E_K': [], 'L_args': [x**2], 'E_args': []}) + assert is_deriv_k(Poly(x, t1), Poly(1, t1), DE) == \ + ([(t1, S(1)/2)], t1/2, 1) + + DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(2/(1 + x), t0)], +- 'exts': [None, 'log'], 'extargs': [None, x**2 + 2*x + 1]}) ++ 'L_K': [1], 'E_K': [], 'L_args': [x**2 + 2*x + 1], 'E_args': []}) + assert is_deriv_k(Poly(1 + x, t0), Poly(1, t0), DE) == \ + ([(t0, S(1)/2)], t0/2, 1) + + # Issue 10798 + # DE = DifferentialExtension(log(1/x), x) + DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-1/x, t)], +- 'exts': [None, 'log'], 'extargs': [None, 1/x]}) ++ 'L_K': [1], 'E_K': [], 'L_args': [1/x], 'E_args': []}) + assert is_deriv_k(Poly(1, t), Poly(x, t), DE) == ([(t, 1)], t, 1) + + +diff --git a/sympy/integrals/tests/test_risch.py b/sympy/integrals/tests/test_risch.py +index c678ccad3c..7308a6ef02 100644 +--- a/sympy/integrals/tests/test_risch.py ++++ b/sympy/integrals/tests/test_risch.py +@@ -409,38 +409,38 @@ def test_DifferentialExtension_exp(): + assert DifferentialExtension(exp(x) + exp(x**2), x)._important_attrs == \ + (Poly(t1 + t0, t1), Poly(1, t1), [Poly(1, x,), Poly(t0, t0), + Poly(2*x*t1, t1)], [x, t0, t1], [Lambda(i, exp(i)), +- Lambda(i, exp(i**2))], [], [None, 'exp', 'exp'], [None, x, x**2]) ++ Lambda(i, exp(i**2))], [], [1, 2], [x, x**2], [], []) + assert DifferentialExtension(exp(x) + exp(2*x), x)._important_attrs == \ + (Poly(t0**2 + t0, t0), Poly(1, t0), [Poly(1, x), Poly(t0, t0)], [x, t0], +- [Lambda(i, exp(i))], [], [None, 'exp'], [None, x]) ++ [Lambda(i, exp(i))], [], [1], [x], [], []) + assert DifferentialExtension(exp(x) + exp(x/2), x)._important_attrs == \ + (Poly(t0**2 + t0, t0), Poly(1, t0), [Poly(1, x), Poly(t0/2, t0)], +- [x, t0], [Lambda(i, exp(i/2))], [], [None, 'exp'], [None, x/2]) ++ [x, t0], [Lambda(i, exp(i/2))], [], [1], [x/2], [], []) + assert DifferentialExtension(exp(x) + exp(x**2) + exp(x + x**2), x)._important_attrs == \ + (Poly((1 + t0)*t1 + t0, t1), Poly(1, t1), [Poly(1, x), Poly(t0, t0), + Poly(2*x*t1, t1)], [x, t0, t1], [Lambda(i, exp(i)), +- Lambda(i, exp(i**2))], [], [None, 'exp', 'exp'], [None, x, x**2]) ++ Lambda(i, exp(i**2))], [], [1, 2], [x, x**2], [], []) + assert DifferentialExtension(exp(x) + exp(x**2) + exp(x + x**2 + 1), x)._important_attrs == \ + (Poly((1 + S.Exp1*t0)*t1 + t0, t1), Poly(1, t1), [Poly(1, x), + Poly(t0, t0), Poly(2*x*t1, t1)], [x, t0, t1], [Lambda(i, exp(i)), +- Lambda(i, exp(i**2))], [], [None, 'exp', 'exp'], [None, x, x**2]) ++ Lambda(i, exp(i**2))], [], [1, 2], [x, x**2], [], []) + assert DifferentialExtension(exp(x) + exp(x**2) + exp(x/2 + x**2), x)._important_attrs == \ + (Poly((t0 + 1)*t1 + t0**2, t1), Poly(1, t1), [Poly(1, x), + Poly(t0/2, t0), Poly(2*x*t1, t1)], [x, t0, t1], + [Lambda(i, exp(i/2)), Lambda(i, exp(i**2))], +- [(exp(x/2), sqrt(exp(x)))], [None, 'exp', 'exp'], [None, x/2, x**2]) ++ [(exp(x/2), sqrt(exp(x)))], [1, 2], [x/2, x**2], [], []) + assert DifferentialExtension(exp(x) + exp(x**2) + exp(x/2 + x**2 + 3), x)._important_attrs == \ + (Poly((t0*exp(3) + 1)*t1 + t0**2, t1), Poly(1, t1), [Poly(1, x), + Poly(t0/2, t0), Poly(2*x*t1, t1)], [x, t0, t1], [Lambda(i, exp(i/2)), +- Lambda(i, exp(i**2))], [(exp(x/2), sqrt(exp(x)))], [None, 'exp', 'exp'], +- [None, x/2, x**2]) ++ Lambda(i, exp(i**2))], [(exp(x/2), sqrt(exp(x)))], [1, 2], [x/2, x**2], ++ [], []) + assert DifferentialExtension(sqrt(exp(x)), x)._important_attrs == \ + (Poly(t0, t0), Poly(1, t0), [Poly(1, x), Poly(t0/2, t0)], [x, t0], +- [Lambda(i, exp(i/2))], [(exp(x/2), sqrt(exp(x)))], [None, 'exp'], [None, x/2]) ++ [Lambda(i, exp(i/2))], [(exp(x/2), sqrt(exp(x)))], [1], [x/2], [], []) + + assert DifferentialExtension(exp(x/2), x)._important_attrs == \ + (Poly(t0, t0), Poly(1, t0), [Poly(1, x), Poly(t0/2, t0)], [x, t0], +- [Lambda(i, exp(i/2))], [], [None, 'exp'], [None, x/2]) ++ [Lambda(i, exp(i/2))], [], [1], [x/2], [], []) + + + def test_DifferentialExtension_log(): +@@ -448,13 +448,12 @@ def test_DifferentialExtension_log(): + (Poly(t0*t1**2 + (t0*log(2) + t0**2)*t1, t1), Poly(1, t1), + [Poly(1, x), Poly(1/x, t0), + Poly(1/(x + 1), t1, expand=False)], [x, t0, t1], +- [Lambda(i, log(i)), Lambda(i, log(i + 1))], [], [None, 'log', 'log'], +- [None, x, x + 1]) ++ [Lambda(i, log(i)), Lambda(i, log(i + 1))], [], [], [], ++ [1, 2], [x, x + 1]) + assert DifferentialExtension(x**x*log(x), x)._important_attrs == \ + (Poly(t0*t1, t1), Poly(1, t1), [Poly(1, x), Poly(1/x, t0), + Poly((1 + t0)*t1, t1)], [x, t0, t1], [Lambda(i, log(i)), +- Lambda(i, exp(t0*i))], [(exp(x*log(x)), x**x)], [None, 'log', 'exp'], +- [None, x, t0*x]) ++ Lambda(i, exp(t0*i))], [(exp(x*log(x)), x**x)], [2], [t0*x], [1], [x]) + + + def test_DifferentialExtension_symlog(): +@@ -462,26 +461,24 @@ def test_DifferentialExtension_symlog(): + assert DifferentialExtension(log(x**x), x)._important_attrs == \ + (Poly(t0*x, t1), Poly(1, t1), [Poly(1, x), Poly(1/x, t0), Poly((t0 + + 1)*t1, t1)], [x, t0, t1], [Lambda(i, log(i)), Lambda(i, exp(i*t0))], +- [(exp(x*log(x)), x**x)], [None, 'log', 'exp'], [None, x, t0*x]) ++ [(exp(x*log(x)), x**x)], [2], [t0*x], [1], [x]) + assert DifferentialExtension(log(x**y), x)._important_attrs == \ + (Poly(y*t0, t0), Poly(1, t0), [Poly(1, x), Poly(1/x, t0)], [x, t0], +- [Lambda(i, log(i))], [(y*log(x), log(x**y))], [None, 'log'], +- [None, x]) ++ [Lambda(i, log(i))], [(y*log(x), log(x**y))], [], [], [1], [x]) + assert DifferentialExtension(log(sqrt(x)), x)._important_attrs == \ + (Poly(t0, t0), Poly(2, t0), [Poly(1, x), Poly(1/x, t0)], [x, t0], +- [Lambda(i, log(i))], [(log(x)/2, log(sqrt(x)))], [None, 'log'], +- [None, x]) ++ [Lambda(i, log(i))], [(log(x)/2, log(sqrt(x)))], [], [], [1], [x]) + + + def test_DifferentialExtension_handle_first(): + assert DifferentialExtension(exp(x)*log(x), x, handle_first='log')._important_attrs == \ + (Poly(t0*t1, t1), Poly(1, t1), [Poly(1, x), Poly(1/x, t0), + Poly(t1, t1)], [x, t0, t1], [Lambda(i, log(i)), Lambda(i, exp(i))], +- [], [None, 'log', 'exp'], [None, x, x]) ++ [], [2], [x], [1], [x]) + assert DifferentialExtension(exp(x)*log(x), x, handle_first='exp')._important_attrs == \ + (Poly(t0*t1, t1), Poly(1, t1), [Poly(1, x), Poly(t0, t0), + Poly(1/x, t1)], [x, t0, t1], [Lambda(i, exp(i)), Lambda(i, log(i))], +- [], [None, 'exp', 'log'], [None, x, x]) ++ [], [1], [x], [2], [x]) + + # This one must have the log first, regardless of what we set it to + # (because the log is inside of the exponential: x**x == exp(x*log(x))) +@@ -492,7 +489,7 @@ def test_DifferentialExtension_handle_first(): + (Poly((-1 + x - x*t0**2)*t1, t1), Poly(x, t1), + [Poly(1, x), Poly(1/x, t0), Poly((1 + t0)*t1, t1)], [x, t0, t1], + [Lambda(i, log(i)), Lambda(i, exp(t0*i))], [(exp(x*log(x)), x**x)], +- [None, 'log', 'exp'], [None, x, t0*x]) ++ [2], [t0*x], [1], [x]) + + + def test_DifferentialExtension_all_attrs(): +@@ -526,16 +523,12 @@ def test_DifferentialExtension_all_attrs(): + assert DE.d == Poly(1/x, t1) == DE.D[DE.level] + assert DE.case == 'primitive' + +- # Test methods +- assert DE.indices('log') == [2] +- assert DE.indices('exp') == [1] +- + + def test_DifferentialExtension_extension_flag(): + raises(ValueError, lambda: DifferentialExtension(extension={'T': [x, t]})) + DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]}) + assert DE._important_attrs == (None, None, [Poly(1, x), Poly(t, t)], [x, t], +- None, None, None, None) ++ None, None, None, None, None, None) + assert DE.d == Poly(t, t) + assert DE.t == t + assert DE.level == -1 +@@ -544,9 +537,9 @@ def test_DifferentialExtension_extension_flag(): + assert DE.case == 'exp' + + DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)], +- 'exts': [None, 'exp'], 'extargs': [None, x]}) ++ 'E_K': [1], 'E_args': [x], 'L_K': [], 'L_args': []}) + assert DE._important_attrs == (None, None, [Poly(1, x), Poly(t, t)], [x, t], +- None, None, [None, 'exp'], [None, x]) ++ None, None, [1], [x], [], []) + raises(ValueError, lambda: DifferentialExtension()) + + +@@ -555,19 +548,19 @@ def test_DifferentialExtension_misc(): + assert DifferentialExtension(sin(y)*exp(x), x)._important_attrs == \ + (Poly(sin(y)*t0, t0, domain='ZZ[sin(y)]'), Poly(1, t0, domain='ZZ'), + [Poly(1, x, domain='ZZ'), Poly(t0, t0, domain='ZZ')], [x, t0], +- [Lambda(i, exp(i))], [], [None, 'exp'], [None, x]) ++ [Lambda(i, exp(i))], [], [1], [x], [], []) + raises(NotImplementedError, lambda: DifferentialExtension(sin(x), x)) + assert DifferentialExtension(10**x, x)._important_attrs == \ + (Poly(t0, t0), Poly(1, t0), [Poly(1, x), Poly(log(10)*t0, t0)], [x, t0], +- [Lambda(i, exp(i*log(10)))], [(exp(x*log(10)), 10**x)], [None, 'exp'], +- [None, x*log(10)]) ++ [Lambda(i, exp(i*log(10)))], [(exp(x*log(10)), 10**x)], [1], [x*log(10)], ++ [], []) + assert DifferentialExtension(log(x) + log(x**2), x)._important_attrs in [ + (Poly(3*t0, t0), Poly(2, t0), [Poly(1, x), Poly(2/x, t0)], [x, t0], +- [Lambda(i, log(i**2))], [], [None, ], [], [1], [x**2]), ++ [Lambda(i, log(i**2))], [], [], [], [1], [x**2]), + (Poly(3*t0, t0), Poly(1, t0), [Poly(1, x), Poly(1/x, t0)], [x, t0], +- [Lambda(i, log(i))], [], [None, 'log'], [None, x])] ++ [Lambda(i, log(i))], [], [], [], [1], [x])] + assert DifferentialExtension(S.Zero, x)._important_attrs == \ +- (Poly(0, x), Poly(1, x), [Poly(1, x)], [x], [], [], [None], [None]) ++ (Poly(0, x), Poly(1, x), [Poly(1, x)], [x], [], [], [], [], [], []) + + + def test_DifferentialExtension_Rothstein(): +@@ -579,8 +572,8 @@ def test_DifferentialExtension_Rothstein(): + 119750400*t0 + 119750400*t0**2 + 39916800*t0**3, t1), + [Poly(1, x), Poly(t0, t0), Poly(-(10 + 21*t0 + 10*t0**2)/(1 + 2*t0 + + t0**2)*t1, t1, domain='ZZ(t0)')], [x, t0, t1], +- [Lambda(i, exp(i)), Lambda(i, exp(1/(t0 + 1) - 10*i))], [], +- [None, 'exp', 'exp'], [None, x, 1/(t0 + 1) - 10*x]) ++ [Lambda(i, exp(i)), Lambda(i, exp(1/(t0 + 1) - 10*i))], [], [1, 2], ++ [x, 1/(t0 + 1) - 10*x], [], []) + + + class TestingException(Exception): +@@ -700,7 +693,7 @@ def test_DifferentialExtension_printing(): + "('x', x), ('T', [x, t0, t1]), ('D', [Poly(1, x, domain='ZZ'), Poly(2*x*t0, t0, domain='ZZ[x]'), " + "Poly(2*t0*x/(t0 + 1), t1, domain='ZZ(x,t0)')]), ('fa', Poly(t1 + t0**2, t1, domain='ZZ[t0]')), " + "('fd', Poly(1, t1, domain='ZZ')), ('Tfuncs', [Lambda(i, exp(i**2)), Lambda(i, log(t0 + 1))]), " +- "('backsubs', []), ('exts', [None, 'exp', 'log']), ('extargs', [None, x**2, t0 + 1]), " ++ "('backsubs', []), ('E_K', [1]), ('E_args', [x**2]), ('L_K', [2]), ('L_args', [t0 + 1]), " + "('cases', ['base', 'exp', 'primitive']), ('case', 'primitive'), ('t', t1), " + "('d', Poly(2*t0*x/(t0 + 1), t1, domain='ZZ(x,t0)')), ('newf', t0**2 + t1), ('level', -1), " + "('dummy', False)]))") +diff --git a/sympy/matrices/common.py b/sympy/matrices/common.py +index 7ef51bc847..dc37416525 100644 +--- a/sympy/matrices/common.py ++++ b/sympy/matrices/common.py +@@ -239,9 +239,10 @@ def col_join(self, other): + col + row_join + """ +- # A null matrix can always be stacked (see #10770) +- if self.rows == 0 and self.cols != other.cols: +- return self._new(0, other.cols, []).col_join(other) ++ from sympy.matrices import MutableMatrix ++ # Allows you to build a matrix even if it is null matrix ++ if not self: ++ return type(self)(other) + + if self.cols != other.cols: + raise ShapeError( +@@ -377,6 +378,11 @@ def hstack(cls, *args): + if len(args) == 0: + return cls._new() + ++ # Check if all matrices have zero rows ++ if all(arg.rows == 0 for arg in args): ++ total_cols = sum(arg.cols for arg in args) ++ return cls.zeros(0, total_cols) ++ + kls = type(args[0]) + return reduce(kls.row_join, args) + +@@ -475,9 +481,9 @@ def row_join(self, other): + row + col_join + """ +- # A null matrix can always be stacked (see #10770) +- if self.cols == 0 and self.rows != other.rows: +- return self._new(other.rows, 0, []).row_join(other) ++ # Allows you to build a matrix even if it is null matrix ++ if not self: ++ return self._new(other) + + if self.rows != other.rows: + raise ShapeError( +@@ -1225,7 +1231,7 @@ def is_lower(self): + Examples + ======== + +- >>> from sympy import Matrix ++ >>> from sympy.matrices import Matrix + >>> m = Matrix(2, 2, [1, 0, 0, 1]) + >>> m + Matrix([ +@@ -1273,7 +1279,7 @@ def is_square(self): + Examples + ======== + +- >>> from sympy import Matrix ++ >>> from sympy.matrices import Matrix + >>> a = Matrix([[1, 2, 3], [4, 5, 6]]) + >>> b = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + >>> c = Matrix([]) +@@ -1811,7 +1817,7 @@ def trace(self): + Examples + ======== + +- >>> from sympy import Matrix ++ >>> from sympy.matrices import Matrix + >>> A = Matrix(2, 2, [1, 2, 3, 4]) + >>> A.trace() + 5 +diff --git a/sympy/matrices/expressions/matmul.py b/sympy/matrices/expressions/matmul.py +index 9a9b06cb1d..f5b95ee959 100644 +--- a/sympy/matrices/expressions/matmul.py ++++ b/sympy/matrices/expressions/matmul.py +@@ -64,12 +64,9 @@ def _entry(self, i, j, expand=True): + if X.has(ImmutableMatrix) or Y.has(ImmutableMatrix): + return coeff*Add(*[X[i, k]*Y[k, j] for k in range(X.cols)]) + result = Sum(coeff*X[i, k]*Y[k, j], (k, 0, X.cols - 1)) +- try: +- if not X.cols.is_number: +- # Don't waste time in result.doit() if the sum bounds are symbolic +- expand = False +- except AttributeError: +- pass ++ if not X.cols.is_number: ++ # Don't waste time in result.doit() if the sum bounds are symbolic ++ expand = False + return result.doit() if expand else result + + def as_coeff_matrices(self): +diff --git a/sympy/matrices/expressions/tests/test_matmul.py b/sympy/matrices/expressions/tests/test_matmul.py +index 5a76ec12ee..cb414935d6 100644 +--- a/sympy/matrices/expressions/tests/test_matmul.py ++++ b/sympy/matrices/expressions/tests/test_matmul.py +@@ -6,7 +6,7 @@ + from sympy.matrices.expressions.matmul import (factor_in_front, remove_ids, + MatMul, xxinv, any_zeros, unpack, only_squares) + from sympy.strategies import null_safe +-from sympy import refine, Q, Symbol ++from sympy import refine, Q + + n, m, l, k = symbols('n m l k', integer=True) + A = MatrixSymbol('A', n, m) +@@ -131,7 +131,3 @@ def test_matmul_args_cnc(): + a, b = symbols('a b', commutative=False) + assert MatMul(n, a, b, A, A.T).args_cnc() == ([n], [a, b, A, A.T]) + assert MatMul(A, A.T).args_cnc() == ([1], [A, A.T]) +- +-def test_issue_12950(): +- M = Matrix([[Symbol("x")]]) * MatrixSymbol("A", 1, 1) +- assert MatrixSymbol("A", 1, 1).as_explicit()[0]*Symbol('x') == M.as_explicit()[0] +diff --git a/sympy/matrices/tests/test_commonmatrix.py b/sympy/matrices/tests/test_commonmatrix.py +index 3e27ecc8b2..120f0b42c4 100644 +--- a/sympy/matrices/tests/test_commonmatrix.py ++++ b/sympy/matrices/tests/test_commonmatrix.py +@@ -221,14 +221,6 @@ def test_hstack(): + raises(ShapeError, lambda: m.hstack(m, m2)) + assert Matrix.hstack() == Matrix() + +- # test regression #12938 +- M1 = Matrix.zeros(0, 0) +- M2 = Matrix.zeros(0, 1) +- M3 = Matrix.zeros(0, 2) +- M4 = Matrix.zeros(0, 3) +- m = ShapingOnlyMatrix.hstack(M1, M2, M3, M4) +- assert m.rows == 0 and m.cols == 6 +- + def test_vstack(): + m = ShapingOnlyMatrix(4, 3, lambda i, j: i*3 + j) + m2 = ShapingOnlyMatrix(3, 4, lambda i, j: i*3 + j) +diff --git a/sympy/physics/units/dimensions.py b/sympy/physics/units/dimensions.py +index f0d9a42204..aeb624fa66 100644 +--- a/sympy/physics/units/dimensions.py ++++ b/sympy/physics/units/dimensions.py +@@ -17,7 +17,7 @@ + import collections + + from sympy.core.compatibility import reduce, string_types +-from sympy import sympify, Integer, Matrix, Symbol, S, Abs ++from sympy import sympify, Integer, Matrix, Symbol, S + from sympy.core.expr import Expr + + +@@ -185,14 +185,8 @@ def get_dimensional_dependencies(self, mark_dimensionless=False): + return {'dimensionless': 1} + return dimdep + +- @classmethod +- def _from_dimensional_dependencies(cls, dependencies): +- return reduce(lambda x, y: x * y, ( +- Dimension(d)**e for d, e in dependencies.items() +- )) +- +- @classmethod +- def _get_dimensional_dependencies_for_name(cls, name): ++ @staticmethod ++ def _get_dimensional_dependencies_for_name(name): + + if name.is_Symbol: + if name.name in Dimension._dimensional_dependencies: +@@ -217,17 +211,6 @@ def _get_dimensional_dependencies_for_name(cls, name): + dim = Dimension._get_dimensional_dependencies_for_name(name.base) + return {k: v*name.exp for (k, v) in dim.items()} + +- if name.is_Function: +- args = (Dimension._from_dimensional_dependencies( +- Dimension._get_dimensional_dependencies_for_name(arg) +- ) for arg in name.args) +- result = name.func(*args) +- +- if isinstance(result, cls): +- return result.get_dimensional_dependencies() +- # TODO shall we consider a result that is not a dimension? +- # return Dimension._get_dimensional_dependencies_for_name(result) +- + @property + def is_dimensionless(self): + """ +diff --git a/sympy/physics/units/prefixes.py b/sympy/physics/units/prefixes.py +index c4e6c7c943..1e79b6316c 100644 +--- a/sympy/physics/units/prefixes.py ++++ b/sympy/physics/units/prefixes.py +@@ -183,11 +183,11 @@ def prefix_unit(unit, prefixes): + } + + +-kibi = Prefix('kibi', 'Y', 10, 2) +-mebi = Prefix('mebi', 'Y', 20, 2) +-gibi = Prefix('gibi', 'Y', 30, 2) +-tebi = Prefix('tebi', 'Y', 40, 2) +-pebi = Prefix('pebi', 'Y', 50, 2) ++kibi = Prefix('kibi', 'Y', 10, 2), ++mebi = Prefix('mebi', 'Y', 20, 2), ++gibi = Prefix('gibi', 'Y', 30, 2), ++tebi = Prefix('tebi', 'Y', 40, 2), ++pebi = Prefix('pebi', 'Y', 50, 2), + exbi = Prefix('exbi', 'Y', 60, 2) + + +diff --git a/sympy/physics/units/quantities.py b/sympy/physics/units/quantities.py +index 4c60bb54d2..6112bda489 100644 +--- a/sympy/physics/units/quantities.py ++++ b/sympy/physics/units/quantities.py +@@ -7,7 +7,7 @@ + from __future__ import division + + from sympy.core.compatibility import string_types +-from sympy import Abs, sympify, Mul, Pow, S, Symbol, Add, AtomicExpr, Basic, Function ++from sympy import sympify, Mul, Pow, S, Symbol, Add, AtomicExpr, Basic + from sympy.physics.units import Dimension + from sympy.physics.units import dimensions + from sympy.physics.units.prefixes import Prefix +@@ -88,11 +88,6 @@ def _eval_is_positive(self): + def _eval_is_constant(self): + return self.scale_factor.is_constant() + +- def _eval_Abs(self): +- # FIXME prefer usage of self.__class__ or type(self) instead +- return self.func(self.name, self.dimension, Abs(self.scale_factor), +- self.abbrev) +- + @staticmethod + def get_dimensional_expr(expr): + if isinstance(expr, Mul): +@@ -101,9 +96,6 @@ def get_dimensional_expr(expr): + return Quantity.get_dimensional_expr(expr.base) ** expr.exp + elif isinstance(expr, Add): + return Quantity.get_dimensional_expr(expr.args[0]) +- elif isinstance(expr, Function): +- fds = [Quantity.get_dimensional_expr(arg) for arg in expr.args] +- return expr.func(*fds) + elif isinstance(expr, Quantity): + return expr.dimension.name + return 1 +@@ -160,12 +152,11 @@ def _Quantity_constructor_postprocessor_Add(expr): + # expressions like `meter + second` to be created. + + deset = { +- tuple(sorted(Dimension( +- Quantity.get_dimensional_expr(i) if not i.is_number else 1 +- ).get_dimensional_dependencies().items())) ++ tuple(Dimension(Quantity.get_dimensional_expr(i)).get_dimensional_dependencies().items()) + for i in expr.args + if i.free_symbols == set() # do not raise if there are symbols + # (free symbols could contain the units corrections) ++ and not i.is_number + } + # If `deset` has more than one element, then some dimensions do not + # match in the sum: +diff --git a/sympy/physics/units/tests/test_quantities.py b/sympy/physics/units/tests/test_quantities.py +index d1d672b461..1797d15143 100644 +--- a/sympy/physics/units/tests/test_quantities.py ++++ b/sympy/physics/units/tests/test_quantities.py +@@ -6,8 +6,8 @@ + from sympy.physics.units import convert_to, find_unit + + from sympy.physics.units.definitions import s, m, kg, speed_of_light, day, minute, km, foot, meter, grams, amu, au, \ +- quart, inch, coulomb, millimeter, steradian, second, mile, centimeter, hour, kilogram, pressure, temperature, energy +-from sympy.physics.units.dimensions import Dimension, length, time, charge, mass ++ quart, inch, coulomb, millimeter, steradian, second, mile, centimeter, hour ++from sympy.physics.units.dimensions import length, time, charge + from sympy.physics.units.quantities import Quantity + from sympy.physics.units.prefixes import PREFIXES, kilo + from sympy.utilities.pytest import raises +@@ -110,19 +110,6 @@ def test_add_sub(): + # TODO: eventually add this: + # assert (u - v).convert_to(u) == S.Half*u + +-def test_abs(): +- v_w1 = Quantity('v_w1', length/time, meter/second) +- v_w2 = Quantity('v_w2', length/time, meter/second) +- v_w3 = Quantity('v_w3', length/time, meter/second) +- expr = v_w3 - Abs(v_w1 - v_w2) +- +- Dq = Dimension(Quantity.get_dimensional_expr(expr)) +- assert Dimension.get_dimensional_dependencies(Dq) == { +- 'length': 1, +- 'time': -1, +- } +- assert meter == sqrt(meter**2) +- + + def test_check_unit_consistency(): + return # TODO remove +@@ -239,7 +226,6 @@ def test_Quantity_derivative(): + + + def test_sum_of_incompatible_quantities(): +- raises(ValueError, lambda: meter + 1) + raises(ValueError, lambda: meter + second) + raises(ValueError, lambda: 2 * meter + second) + raises(ValueError, lambda: 2 * meter + 3 * second) +@@ -250,17 +236,3 @@ def test_sum_of_incompatible_quantities(): + assert expr in Basic._constructor_postprocessor_mapping + for i in expr.args: + assert i in Basic._constructor_postprocessor_mapping +- +- +-def test_quantity_postprocessing(): +- q1 = Quantity('q1', length*pressure**2*temperature/time) +- q2 = Quantity('q2', energy*pressure*temperature/(length**2*time)) +- assert q1 + q2 +- q = q1 + q2 +- Dq = Dimension(Quantity.get_dimensional_expr(q)) +- assert Dimension.get_dimensional_dependencies(Dq) == { +- 'length': -1, +- 'mass': 2, +- 'temperature': 1, +- 'time': -5, +- } +diff --git a/sympy/printing/octave.py b/sympy/printing/octave.py +index cfcae81dae..0be218d6a2 100644 +--- a/sympy/printing/octave.py ++++ b/sympy/printing/octave.py +@@ -310,8 +310,13 @@ def _print_MatrixBase(self, A): + elif (A.rows, A.cols) == (1, 1): + # Octave does not distinguish between scalars and 1x1 matrices + return self._print(A[0, 0]) +- return "[%s]" % "; ".join(" ".join([self._print(a) for a in A[r, :]]) +- for r in range(A.rows)) ++ elif A.rows == 1: ++ return "[%s]" % A.table(self, rowstart='', rowend='', colsep=' ') ++ elif A.cols == 1: ++ # note .table would unnecessarily equispace the rows ++ return "[%s]" % "; ".join([self._print(a) for a in A]) ++ return "[%s]" % A.table(self, rowstart='', rowend='', ++ rowsep=';\n', colsep=' ') + + + def _print_SparseMatrix(self, A): +diff --git a/sympy/printing/tests/test_octave.py b/sympy/printing/tests/test_octave.py +index 0103035ae0..c5d0d93085 100644 +--- a/sympy/printing/tests/test_octave.py ++++ b/sympy/printing/tests/test_octave.py +@@ -145,7 +145,9 @@ def test_Matrices(): + A = Matrix([[1, sin(x/2), abs(x)], + [0, 1, pi], + [0, exp(1), ceiling(x)]]); +- expected = "[1 sin(x/2) abs(x); 0 1 pi; 0 exp(1) ceil(x)]" ++ expected = ("[1 sin(x/2) abs(x);\n" ++ "0 1 pi;\n" ++ "0 exp(1) ceil(x)]") + assert mcode(A) == expected + # row and columns + assert mcode(A[:,0]) == "[1; 0; 0]" +@@ -202,7 +204,7 @@ def test_containers(): + assert mcode(Tuple(*[1, 2, 3])) == "{1, 2, 3}" + assert mcode((1, x*y, (3, x**2))) == "{1, x.*y, {3, x.^2}}" + # scalar, matrix, empty matrix and empty list +- assert mcode((1, eye(3), Matrix(0, 0, []), [])) == "{1, [1 0 0; 0 1 0; 0 0 1], [], {}}" ++ assert mcode((1, eye(3), Matrix(0, 0, []), [])) == "{1, [1 0 0;\n0 1 0;\n0 0 1], [], {}}" + + + def test_octave_noninline(): +@@ -258,7 +260,7 @@ def test_octave_matrix_assign_to(): + A = Matrix([[1, 2, 3]]) + assert mcode(A, assign_to='a') == "a = [1 2 3];" + A = Matrix([[1, 2], [3, 4]]) +- assert mcode(A, assign_to='A') == "A = [1 2; 3 4];" ++ assert mcode(A, assign_to='A') == "A = [1 2;\n3 4];" + + + def test_octave_matrix_assign_to_more(): +diff --git a/sympy/release.py b/sympy/release.py +index 5a776b94cf..f901408650 100644 +--- a/sympy/release.py ++++ b/sympy/release.py +@@ -1 +1 @@ +-__version__ = "1.1.1rc1" ++__version__ = "1.1" +diff --git a/sympy/utilities/codegen.py b/sympy/utilities/codegen.py +index 0045efeb49..311cb27d27 100644 +--- a/sympy/utilities/codegen.py ++++ b/sympy/utilities/codegen.py +@@ -798,7 +798,6 @@ def __init__(self, project="project", printer=None, + super(CCodeGen, self).__init__(project=project) + self.printer = printer or c_code_printers[self.standard.lower()]() + +- self.preprocessor_statements = preprocessor_statements + if preprocessor_statements is None: + self.preprocessor_statements = ['#include '] + +diff --git a/sympy/utilities/lambdify.py b/sympy/utilities/lambdify.py +index 9b1ee3ec06..56b3ce33d0 100644 +--- a/sympy/utilities/lambdify.py ++++ b/sympy/utilities/lambdify.py +@@ -10,7 +10,7 @@ + import textwrap + + from sympy.core.compatibility import (exec_, is_sequence, iterable, +- NotIterable, string_types, range, builtins, integer_types) ++ NotIterable, string_types, range, builtins) + from sympy.utilities.decorator import doctest_depends_on + + # These are the namespaces the lambda functions will use. +@@ -438,10 +438,7 @@ def lambdify(args, expr, modules=None, printer=None, use_imps=True, + def array_wrap(funcarg): + @wraps(funcarg) + def wrapper(*argsx, **kwargsx): +- asarray = namespace['asarray'] +- newargs = [asarray(i) if isinstance(i, integer_types + (float, +- complex)) else i for i in argsx] +- return funcarg(*newargs, **kwargsx) ++ return funcarg(*[namespace['asarray'](i) for i in argsx], **kwargsx) + return wrapper + func = array_wrap(func) + # Apply the docstring +diff --git a/sympy/utilities/misc.py b/sympy/utilities/misc.py +index c989997818..27ba151482 100644 +--- a/sympy/utilities/misc.py ++++ b/sympy/utilities/misc.py +@@ -343,7 +343,15 @@ def translate(s, a, b=None, c=None): + >>> translate(abc, {'ab': 'x', 'bc': 'y'}) in ('xc', 'ay') + True + """ +- from sympy.core.compatibility import maketrans, PY3 ++ from sympy.core.compatibility import maketrans ++ ++ # when support for Python 2 is dropped, this try/except can be ++ #removed ++ try: ++ ''.translate(None, '') ++ py3 = False ++ except TypeError: ++ py3 = True + + mr = {} + if a is None: +@@ -366,7 +374,7 @@ def translate(s, a, b=None, c=None): + a = b = '' + else: + assert len(a) == len(b) +- if PY3: ++ if py3: + if c: + s = s.translate(maketrans('', '', c)) + s = replace(s, mr) +diff --git a/sympy/utilities/tests/test_codegen.py b/sympy/utilities/tests/test_codegen.py +index 46bc645858..2b5be52edb 100644 +--- a/sympy/utilities/tests/test_codegen.py ++++ b/sympy/utilities/tests/test_codegen.py +@@ -1447,32 +1447,12 @@ def test_custom_codegen(): + from sympy.functions.elementary.exponential import exp + + printer = C99CodePrinter(settings={'user_functions': {'exp': 'fastexp'}}) ++ gen = C99CodeGen(printer=printer) ++ gen.preprocessor_statements.append('#include "fastexp.h"') + + x, y = symbols('x y') + expr = exp(x + y) + +- # replace math.h with a different header +- gen = C99CodeGen(printer=printer, +- preprocessor_statements=['#include "fastexp.h"']) +- +- expected = ( +- '#include "expr.h"\n' +- '#include "fastexp.h"\n' +- 'double expr(double x, double y) {\n' +- ' double expr_result;\n' +- ' expr_result = fastexp(x + y);\n' +- ' return expr_result;\n' +- '}\n' +- ) +- +- result = codegen(('expr', expr), header=False, empty=False, code_gen=gen) +- source = result[0][1] +- assert source == expected +- +- # use both math.h and an external header +- gen = C99CodeGen(printer=printer) +- gen.preprocessor_statements.append('#include "fastexp.h"') +- + expected = ( + '#include "expr.h"\n' + '#include \n' +diff --git a/sympy/utilities/tests/test_codegen_octave.py b/sympy/utilities/tests/test_codegen_octave.py +index 8aee4e2586..b79b4be3d8 100644 +--- a/sympy/utilities/tests/test_codegen_octave.py ++++ b/sympy/utilities/tests/test_codegen_octave.py +@@ -347,7 +347,8 @@ def test_m_matrix_output_autoname_2(): + " out1 = x + y;\n" + " out2 = [2*x 2*y 2*z];\n" + " out3 = [x; y; z];\n" +- " out4 = [x y; z 16];\n" ++ " out4 = [x y;\n" ++ " z 16];\n" + "end\n" + ) + assert source == expected +diff --git a/sympy/vector/coordsysrect.py b/sympy/vector/coordsysrect.py +index a9a3af6b76..5ffd66aa06 100644 +--- a/sympy/vector/coordsysrect.py ++++ b/sympy/vector/coordsysrect.py +@@ -4,8 +4,7 @@ + from sympy.core.cache import cacheit + from sympy.core import S + from sympy.vector.scalar import BaseScalar +-from sympy import Matrix +-from sympy import eye, trigsimp, ImmutableMatrix as Matrix, Symbol, sin, cos, sqrt, diff, Tuple, simplify ++from sympy import eye, trigsimp, ImmutableMatrix as Matrix, Symbol, sin, cos, sqrt, diff, Tuple + import sympy.vector + from sympy import simplify + from sympy.vector.orienters import (Orienter, AxisOrienter, BodyOrienter, +@@ -216,37 +215,6 @@ def _connect_to_standard_cartesian(self, curv_coord_type): + else: + raise ValueError("Wrong set of parameter.") + +- if not self._check_orthogonality(): +- raise ValueError("The transformation equation does not create orthogonal coordinate system") +- +- def _check_orthogonality(self): +- """ +- Helper method for _connect_to_cartesian. It checks if +- set of transformation equations create orthogonal curvilinear +- coordinate system +- +- Parameters +- ========== +- +- equations : tuple +- Tuple of transformation equations +- +- """ +- +- eq = self._transformation_equations() +- +- v1 = Matrix([diff(eq[0], self.x), diff(eq[1], self.x), diff(eq[2], self.x)]) +- v2 = Matrix([diff(eq[0], self.y), diff(eq[1], self.y), diff(eq[2], self.y)]) +- v3 = Matrix([diff(eq[0], self.z), diff(eq[1], self.z), diff(eq[2], self.z)]) +- +- if any(simplify(i[0]+i[1]+i[2]) == 0 for i in (v1, v2, v3)): +- return False +- else: +- if simplify(v1.dot(v2)) == 0 and simplify(v2.dot(v3)) == 0 and simplify(v3.dot(v1)) == 0: +- return True +- else: +- return False +- + def _set_transformation_equations_mapping(self, curv_coord_name): + """ + Store information about some default, pre-defined transformation +diff --git a/sympy/vector/tests/test_coordsysrect.py b/sympy/vector/tests/test_coordsysrect.py +index dc455a3635..e8f0c6e9d6 100644 +--- a/sympy/vector/tests/test_coordsysrect.py ++++ b/sympy/vector/tests/test_coordsysrect.py +@@ -1,9 +1,8 @@ + from sympy.utilities.exceptions import SymPyDeprecationWarning +-from sympy.utilities.pytest import raises + import warnings + from sympy.vector.coordsysrect import CoordSys3D, CoordSysCartesian + from sympy.vector.scalar import BaseScalar +-from sympy import sin, sinh, cos, cosh, sqrt, pi, ImmutableMatrix as Matrix, \ ++from sympy import sin, cos, sqrt, pi, ImmutableMatrix as Matrix, \ + symbols, simplify, zeros, expand + from sympy.vector.functions import express + from sympy.vector.point import Point +@@ -353,19 +352,6 @@ def test_transformation_equations(): + assert simplify(a.lame_coefficients()) == (1, sqrt(a.x**2), 1) + + +-def test_check_orthogonality(): +- a = CoordSys3D('a') +- a._connect_to_standard_cartesian((a.x*sin(a.y)*cos(a.z), a.x*sin(a.y)*sin(a.z), a.x*cos(a.y))) +- assert a._check_orthogonality() is True +- a._connect_to_standard_cartesian((a.x * cos(a.y), a.x * sin(a.y), a.z)) +- assert a._check_orthogonality() is True +- a._connect_to_standard_cartesian((cosh(a.x)*cos(a.y), sinh(a.x)*sin(a.y), a.z)) +- assert a._check_orthogonality() is True +- +- raises(ValueError, lambda: a._connect_to_standard_cartesian((a.x, a.x, a.z))) +- raises(ValueError, lambda: a._connect_to_standard_cartesian( +- (a.x*sin(a.y / 2)*cos(a.z), a.x*sin(a.y)*sin(a.z), a.x*cos(a.y)))) +- + def test_coordsys3d(): + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=SymPyDeprecationWarning) diff --git a/sub_swebench_dataset/fail_seed1_50/sympy__sympy-15198-diff.txt b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-15198-diff.txt new file mode 100644 index 000000000..2754a4bee --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-15198-diff.txt @@ -0,0 +1,22 @@ +diff --git a/sympy/printing/octave.py b/sympy/printing/octave.py +index 9de4f6af14..9dc99992ea 100644 +--- a/sympy/printing/octave.py ++++ b/sympy/printing/octave.py +@@ -56,6 +56,7 @@ + "RisingFactorial": "pochhammer", + "Shi": "sinhint", + "Si": "sinint", ++ "assoc_laguerre": "_print_assoc_laguerre", + } + + +@@ -561,6 +562,9 @@ def indent_code(self, code): + level += increase[n] + return pretty + ++ def _print_assoc_laguerre(self, expr): ++ raise NotImplementedError("Code generation for the associated Laguerre polynomials is not supported in Octave.") ++ + + def octave_code(expr, assign_to=None, **settings): + r"""Converts `expr` to a string of Octave (or Matlab) code. diff --git a/sub_swebench_dataset/fail_seed1_50/sympy__sympy-17313-diff.txt b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-17313-diff.txt new file mode 100644 index 000000000..f63d8686b --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-17313-diff.txt @@ -0,0 +1,27 @@ +diff --git a/sympy/functions/elementary/integers.py b/sympy/functions/elementary/integers.py +index fa68122865..691f178172 100644 +--- a/sympy/functions/elementary/integers.py ++++ b/sympy/functions/elementary/integers.py +@@ -390,13 +390,16 @@ def __ge__(self, other): + def __gt__(self, other): + if self.is_extended_real: + other = _sympify(other) +- # Check if other < 0 +- res = self._value_one_or_more(other) +- if res is not None: +- return not(res) +- # Check if other >= 1 +- if other.is_extended_negative: ++ # Check if other is a positive number ++ if other.is_positive: ++ # If other is positive, ceiling of any number is greater than 0 + return S.true ++ # Check if other is non-positive ++ if other.is_nonpositive: ++ # If other is non-positive, ceiling of any number is not greater ++ return S.false ++ # If other is not a number, return unevaluated ++ return Gt(self, other, evaluate=False) + return Gt(self, other, evaluate=False) + + def __le__(self, other): diff --git a/sub_swebench_dataset/fail_seed1_50/sympy__sympy-20139-diff.txt b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-20139-diff.txt new file mode 100644 index 000000000..5097177ce --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-20139-diff.txt @@ -0,0 +1,26 @@ +diff --git a/sympy/matrices/expressions/matexpr.py b/sympy/matrices/expressions/matexpr.py +index 87a40b0b57..ebfef7e3c8 100644 +--- a/sympy/matrices/expressions/matexpr.py ++++ b/sympy/matrices/expressions/matexpr.py +@@ -771,9 +771,9 @@ def __new__(cls, name, n, m): + cls._check_dim(m) + cls._check_dim(n) + +- if isinstance(name, str): +- name = Symbol(name) +- obj = Basic.__new__(cls, name, n, m) ++ if not isinstance(name, str): ++ raise TypeError("name must be a string") ++ obj = Basic.__new__(cls, str(name), n, m) + return obj + + @property +@@ -782,7 +782,7 @@ def shape(self): + + @property + def name(self): +- return self.args[0].name ++ return self.args[0] + + def _entry(self, i, j, **kwargs): + return MatrixElement(self, i, j) diff --git a/sub_swebench_dataset/fail_seed1_50/sympy__sympy-20639-diff.txt b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-20639-diff.txt new file mode 100644 index 000000000..459cd1589 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-20639-diff.txt @@ -0,0 +1,22 @@ +diff --git a/sympy/printing/pretty/pretty.py b/sympy/printing/pretty/pretty.py +index df7452ee87..e3723a290e 100644 +--- a/sympy/printing/pretty/pretty.py ++++ b/sympy/printing/pretty/pretty.py +@@ -21,6 +21,8 @@ + xsym, pretty_symbol, pretty_atom, pretty_use_unicode, greek_unicode, U, \ + pretty_try_use_unicode, annotated + ++from sympy import pi, E ++ + # rename for usage from outside + pprint_use_unicode = pretty_use_unicode + pprint_try_use_unicode = pretty_try_use_unicode +@@ -1951,6 +1953,8 @@ def _print_Pow(self, power): + from sympy.simplify.simplify import fraction + b, e = power.as_base_exp() + if power.is_commutative: ++ if b == pi and e == 1/E: ++ return self._print(b)**self._print(e) + if e is S.NegativeOne: + return prettyForm("1")/self._print(b) + n, d = fraction(e) diff --git a/sub_swebench_dataset/fail_seed1_50/sympy__sympy-20801-diff.txt b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-20801-diff.txt new file mode 100644 index 000000000..5c9df7b96 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-20801-diff.txt @@ -0,0 +1,50 @@ +diff --git a/sympy/core/basic.py b/sympy/core/basic.py +index 8e82778c7d..5d289fc1c3 100644 +--- a/sympy/core/basic.py ++++ b/sympy/core/basic.py +@@ -334,6 +334,11 @@ def __eq__(self, other): + + from http://docs.python.org/dev/reference/datamodel.html#object.__hash__ + """ ++ from sympy.core.numbers import Float ++ from sympy.logic.boolalg import Boolean ++ ++ print(f"Debug: Comparing self: {self}, type: {type(self)} with other: {other}, type: {type(other)}") ++ + if self is other: + return True + +@@ -341,6 +346,7 @@ def __eq__(self, other): + tother = type(other) + if tself is not tother: + try: ++ print(f"Debug before sympify: self: {self}, type: {type(self)}, other: {other}, type: {type(other)}") + other = _sympify(other) + tother = type(other) + except SympifyError: +@@ -357,14 +363,22 @@ def __eq__(self, other): + elif tself is not tother: + return False + ++ # If the types are the same then we can just compare the _hashable_content. ++ # However, we special case Float and Boolean here. A Float with value 0.0 ++ # should not compare equal to S.false even though they will both have ++ # _hashable_content() == (0,). ++ if isinstance(self, Float) and self == 0.0 and isinstance(other, Boolean) and other is S.false: ++ return False ++ elif isinstance(self, Boolean) and self is S.false and isinstance(other, Float) and other == 0.0: ++ return False ++ ++ print(f"Debug before hashable content comparison: self: {self}, type: {type(self)}, other: {other}, type: {type(other)}") + return self._hashable_content() == other._hashable_content() + + def __ne__(self, other): + """``a != b`` -> Compare two symbolic trees and see whether they are different + +- this is the same as: +- +- ``a.compare(b) != 0`` ++ this is the same as: ``a.compare(b) != 0`` + + but faster + """ diff --git a/sub_swebench_dataset/fail_seed1_50/sympy__sympy-21286-diff.txt b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-21286-diff.txt new file mode 100644 index 000000000..dd71d77f1 --- /dev/null +++ b/sub_swebench_dataset/fail_seed1_50/sympy__sympy-21286-diff.txt @@ -0,0 +1,75 @@ +diff --git a/sympy/sets/fancysets.py b/sympy/sets/fancysets.py +index b1af4372be..d3c6df6bdc 100644 +--- a/sympy/sets/fancysets.py ++++ b/sympy/sets/fancysets.py +@@ -608,37 +608,23 @@ def __new__(cls, *args): + [0, 1/10, 1/5].''')) + start, stop, step = ok + ++ print("start:", start, "stop:", stop, "step:", step) ++ + null = False + if any(i.has(Symbol) for i in (start, stop, step)): + if start == stop: + null = True + else: +- end = stop +- elif start.is_infinite: +- span = step*(stop - start) +- if span is S.NaN or span <= 0: +- null = True +- elif step.is_Integer and stop.is_infinite and abs(step) != 1: +- raise ValueError(filldedent(''' +- Step size must be %s in this case.''' % (1 if step > 0 else -1))) +- else: +- end = stop +- else: +- oostep = step.is_infinite +- if oostep: +- step = S.One if step > 0 else S.NegativeOne +- n = ceiling((stop - start)/step) +- if n <= 0: +- null = True +- elif oostep: +- end = start + 1 +- step = S.One # make it a canonical single step +- else: +- end = start + n*step ++ if step.has(Symbol): ++ # Calculate the adjustment needed to make the range canonical ++ adjusted_stop = start + ceiling((stop - start)/step)*step ++ stop = adjusted_stop ++ else: ++ stop = stop + if null: +- start = end = S.Zero ++ start = stop = S.Zero + step = S.One +- return Basic.__new__(cls, start, end, step) ++ return Basic.__new__(cls, start, stop, step) + + start = property(lambda self: self.args[0]) + stop = property(lambda self: self.args[1]) +@@ -890,14 +876,14 @@ def _inf(self): + + @property + def _sup(self): +- if not self: +- raise NotImplementedError +- if self.has(Symbol): +- if self.step.is_positive: +- return self[-1] +- elif self.step.is_negative: +- return self[0] +- _ = self.size # validate ++ if self.size == 0: ++ return S.NegativeInfinity ++ if self.start.is_infinite: ++ return S.NegativeInfinity ++ if self.stop.is_infinite: ++ return S.Infinity ++ if self.step.has(Symbol): ++ return self.stop - self.step + if self.step > 0: + return self.stop - self.step + else: diff --git a/sub_swebench_dataset/pass_seed1_50/astropy__astropy-14995-diff.txt b/sub_swebench_dataset/pass_seed1_50/astropy__astropy-14995-diff.txt new file mode 100644 index 000000000..04f219dd2 --- /dev/null +++ b/sub_swebench_dataset/pass_seed1_50/astropy__astropy-14995-diff.txt @@ -0,0 +1,21 @@ +diff --git a/astropy/nddata/mixins/ndarithmetic.py b/astropy/nddata/mixins/ndarithmetic.py +index 4153dfccb2..8ce47ac370 100644 +--- a/astropy/nddata/mixins/ndarithmetic.py ++++ b/astropy/nddata/mixins/ndarithmetic.py +@@ -513,14 +513,10 @@ class NDArithmeticMixin: + ``handle_mask`` must create (and copy) the returned mask. + """ + # If only one mask is present we need not bother about any type checks +- if ( +- self.mask is None and operand is not None and operand.mask is None +- ) or handle_mask is None: +- return None +- elif self.mask is None and operand is not None: ++ if self.mask is None and operand is not None: + # Make a copy so there is no reference in the result. + return deepcopy(operand.mask) +- elif operand is None: ++ elif operand is None or operand.mask is None: + return deepcopy(self.mask) + else: + # Now lets calculate the resulting mask (operation enforces copy) diff --git a/sub_swebench_dataset/pass_seed1_50/astropy__astropy-7606-diff.txt b/sub_swebench_dataset/pass_seed1_50/astropy__astropy-7606-diff.txt new file mode 100644 index 000000000..bb442527f --- /dev/null +++ b/sub_swebench_dataset/pass_seed1_50/astropy__astropy-7606-diff.txt @@ -0,0 +1,13 @@ +diff --git a/astropy/units/core.py b/astropy/units/core.py +index e9bd986d33..1b202395e9 100644 +--- a/astropy/units/core.py ++++ b/astropy/units/core.py +@@ -1710,6 +1710,8 @@ class UnrecognizedUnit(IrreducibleUnit): + _unrecognized_operator + + def __eq__(self, other): ++ if other is None: ++ return False + other = Unit(other, parse_strict='silent') + return isinstance(other, UnrecognizedUnit) and self.name == other.name + diff --git a/sub_swebench_dataset/pass_seed1_50/astropy__astropy-7671-diff.txt b/sub_swebench_dataset/pass_seed1_50/astropy__astropy-7671-diff.txt new file mode 100644 index 000000000..94c3679c1 --- /dev/null +++ b/sub_swebench_dataset/pass_seed1_50/astropy__astropy-7671-diff.txt @@ -0,0 +1,82 @@ +diff --git a/astropy/utils/collections.py b/astropy/utils/collections.py +deleted file mode 100644 +index 3a9b839548..0000000000 +--- a/astropy/utils/collections.py ++++ /dev/null +@@ -1,57 +0,0 @@ +-# Licensed under a 3-clause BSD style license - see LICENSE.rst +-""" +-A module containing specialized collection classes. +-""" +- +- +-class HomogeneousList(list): +- """ +- A subclass of list that contains only elements of a given type or +- types. If an item that is not of the specified type is added to +- the list, a `TypeError` is raised. +- """ +- def __init__(self, types, values=[]): +- """ +- Parameters +- ---------- +- types : sequence of types +- The types to accept. +- +- values : sequence, optional +- An initial set of values. +- """ +- self._types = types +- super().__init__() +- self.extend(values) +- +- def _assert(self, x): +- if not isinstance(x, self._types): +- raise TypeError( +- "homogeneous list must contain only objects of " +- "type '{}'".format(self._types)) +- +- def __iadd__(self, other): +- self.extend(other) +- return self +- +- def __setitem__(self, idx, value): +- if isinstance(idx, slice): +- value = list(value) +- for item in value: +- self._assert(item) +- else: +- self._assert(value) +- return super().__setitem__(idx, value) +- +- def append(self, x): +- self._assert(x) +- return super().append(x) +- +- def insert(self, i, x): +- self._assert(x) +- return super().insert(i, x) +- +- def extend(self, x): +- for item in x: +- self._assert(item) +- super().append(item) +diff --git a/astropy/utils/introspection.py b/astropy/utils/introspection.py +index 3e784f9fc3..a4f8ebc513 100644 +--- a/astropy/utils/introspection.py ++++ b/astropy/utils/introspection.py +@@ -139,10 +139,12 @@ def minversion(module, version, inclusive=True, version_path='__version__'): + else: + have_version = resolve_name(module.__name__, version_path) + ++ from pkg_resources import parse_version ++ + if inclusive: +- return LooseVersion(have_version) >= LooseVersion(version) ++ return parse_version(have_version) >= parse_version(version) + else: +- return LooseVersion(have_version) > LooseVersion(version) ++ return parse_version(have_version) > parse_version(version) + + + def find_current_module(depth=1, finddiff=False): diff --git a/sub_swebench_dataset/pass_seed1_50/django__django-10606-diff.txt b/sub_swebench_dataset/pass_seed1_50/django__django-10606-diff.txt new file mode 100644 index 000000000..e9b3e2faa --- /dev/null +++ b/sub_swebench_dataset/pass_seed1_50/django__django-10606-diff.txt @@ -0,0 +1,22 @@ +diff --git a/django/db/models/fields/reverse_related.py b/django/db/models/fields/reverse_related.py +index 700410a086..71f940aeff 100644 +--- a/django/db/models/fields/reverse_related.py ++++ b/django/db/models/fields/reverse_related.py +@@ -114,7 +114,7 @@ class ForeignObjectRel(FieldCacheMixin): + self.related_model._meta.model_name, + ) + +- def get_choices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH, ordering=()): ++ def get_choices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH, limit_choices_to=None, ordering=()): + """ + Return choices with a default blank choices included, for use + as