internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: TencentBlueKing/bk-user

Issue:
2.5.2 登录审计-登录时间不对
<img width="1035" alt="image" src="https://user-images.githubusercontent.com/2002216/211273856-e3ddfb38-29ba-4ce3-a5f3-f735e98ef555.png">


可能跟时间国际化有关系


Discussion:

Resolving patch:
diff --git a/src/api/bkuser_core/api/web/audit/serializers.py b/src/api/bkuser_core/api/web/audit/serializers.py
--- a/src/api/bkuser_core/api/web/audit/serializers.py
+++ b/src/api/bkuser_core/api/web/audit/serializers.py
@@ -11,6 +11,7 @@
 import datetime
 from typing import Optional
 
+from django.utils import timezone
 from django.utils.translation import ugettext_lazy as _
 from rest_framework import serializers
 
@@ -91,7 +92,9 @@ class LoginLogOutputSLZ(serializers.Serializer):
     reason = serializers.SerializerMethodField(help_text=_("失败原因"), required=False)
 
     def get_datetime(self, obj):
-        return obj.create_time
+        # 转换成本地时间
+        local_time = timezone.localtime(obj.create_time)
+        return local_time.strftime("%Y-%m-%d %H:%M:%S")
 
     def get_reason(self, obj) -> Optional[str]:
         """get reason display name"""


Test patch:
Repository: TencentBlueKing/bk-user

Issue:
【安全】安全漏洞扫描，生产环境下能访问后台swagger
**用文字描述你遇到的问题**

生产环境，swagger未屏蔽可访问

**重现方法**
![image](https://user-images.githubusercontent.com/49228807/221740484-96ab7d07-ba5c-44c6-bc2f-420f9de733ed.png)

对应源码未屏蔽
https://github.com/TencentBlueKing/bk-user/blob/40ee56ed90d47b214274819394aa21ec7459b970/src/api/bkuser_core/apis/urls.py#L45

**预期行为**

预期的正常行为

**版本**
- 2.5.2
- 是否是企业版问题？
是

**如果是 SaaS 页面问题，请提供使用的操作系统和浏览器信息**
 - OS: [e.g. iOS]
 - Browser [e.g. chrome, safari]
 - Version [e.g. 22]

**额外信息**

任何你觉得有助于问题解决的内容



Discussion:

Resolving patch:
diff --git a/src/api/bkuser_core/apis/urls.py b/src/api/bkuser_core/apis/urls.py
--- a/src/api/bkuser_core/apis/urls.py
+++ b/src/api/bkuser_core/apis/urls.py
@@ -8,6 +8,7 @@
 an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 specific language governing permissions and limitations under the License.
 """
+from django.conf import settings
 from django.conf.urls import include, url
 from drf_yasg import openapi
 from drf_yasg.generators import OpenAPISchemaGenerator
@@ -41,9 +42,10 @@ def get_schema(self, request=None, public=False):
     ],
 )
 
-
-urlpatterns = [
-    url(r"^swagger(?P<format>\.json|\.yaml)$", schema_view.without_ui(cache_timeout=0), name="schema-json"),
-    url(r"^swagger/$", schema_view.with_ui("swagger", cache_timeout=0), name="schema-swagger-ui"),
-    url(r"^redoc/$", schema_view.with_ui("redoc", cache_timeout=0), name="schema-redoc"),
-]
+urlpatterns = []
+if settings.DEBUG:
+    urlpatterns += [
+        url(r"^swagger(?P<format>\.json|\.yaml)$", schema_view.without_ui(cache_timeout=0), name="schema-json"),
+        url(r"^swagger/$", schema_view.with_ui("swagger", cache_timeout=0), name="schema-swagger-ui"),
+        url(r"^redoc/$", schema_view.with_ui("redoc", cache_timeout=0), name="schema-redoc"),
+    ]


Test patch:
Repository: TencentBlueKing/bk-user

Issue:
编辑用户唯一属性自定义字段冲突报错，返回异常，非正常的响应
**用文字描述你遇到的问题**

编辑用用户唯一性字段，冲突报错，非正常的异常响应

**重现方法**

请描述问题重现的方法，如果不方便描述，可以通过截图或者视频辅助。

**预期行为**

预期的正常行为

**版本**
- 提供用户管理的具体版本号
- 是否是企业版问题？

**如果是 SaaS 页面问题，请提供使用的操作系统和浏览器信息**
 - OS: [e.g. iOS]
 - Browser [e.g. chrome, safari]
 - Version [e.g. 22]

**额外信息**

任何你觉得有助于问题解决的内容



Discussion:

Resolving patch:
diff --git a/src/api/bkuser_core/api/web/profile/views.py b/src/api/bkuser_core/api/web/profile/views.py
--- a/src/api/bkuser_core/api/web/profile/views.py
+++ b/src/api/bkuser_core/api/web/profile/views.py
@@ -194,7 +194,7 @@ def _update(self, request, partial):
             instance.save()
         except Exception:  # pylint: disable=broad-except
             logger.exception("failed to update profile")
-            return error_codes.SAVE_USER_INFO_FAILED
+            raise error_codes.SAVE_USER_INFO_FAILED
 
         post_profile_update.send(
             sender=self,
diff --git a/src/api/bkuser_core/profiles/v2/views.py b/src/api/bkuser_core/profiles/v2/views.py
--- a/src/api/bkuser_core/profiles/v2/views.py
+++ b/src/api/bkuser_core/profiles/v2/views.py
@@ -376,7 +376,7 @@ def _update(self, request, partial):
             instance.save()
         except Exception:  # pylint: disable=broad-except
             logger.exception("failed to update profile")
-            return error_codes.SAVE_USER_INFO_FAILED
+            raise error_codes.SAVE_USER_INFO_FAILED
 
         post_profile_update.send(
             sender=self,


Test patch:
Repository: TencentBlueKing/bk-user

Issue:
【BUG】更新自定义字段的名称和属性（可编辑）未生效
**用文字描述你遇到的问题**

用户管理Saas页面，字段设置，更新自定义字段的名称，可编辑属性。并没有更新成功

**重现方法**
用户管理Saas，字段设置页面创建测试字段test
![image](https://github.com/TencentBlueKing/bk-user/assets/49228807/064ad99b-7ce0-4997-8c55-c1fc652e24b5)
更新test字段，变更字段名称为test2，以及属性（可编辑）
![image](https://github.com/TencentBlueKing/bk-user/assets/49228807/00431d94-ef77-4e45-9ab5-ee6b2ae5c599)
点击保存后，更新内容并未生效

**预期行为**

正常更新字段

**版本**
- 提供用户管理的具体版本号
- 2.5.3
- 是否是企业版问题？
否

**如果是 SaaS 页面问题，请提供使用的操作系统和浏览器信息**
 - OS: [e.g. iOS]
 - Browser [e.g. chrome, safari]
 - Version [e.g. 22]

**额外信息**

任何你觉得有助于问题解决的内容



Discussion:

Resolving patch:
diff --git a/src/api/bkuser_core/api/web/field/serializers.py b/src/api/bkuser_core/api/web/field/serializers.py
--- a/src/api/bkuser_core/api/web/field/serializers.py
+++ b/src/api/bkuser_core/api/web/field/serializers.py
@@ -67,9 +67,10 @@ def validate(self, attrs):
 
 
 class DynamicFieldUpdateInputSLZ(serializers.Serializer):
-    display_name = serializers.CharField(required=False)
+    name = serializers.CharField(required=False)
     require = serializers.BooleanField(required=False, default=False)
     unique = serializers.BooleanField(required=False, default=False)
+    editable = serializers.BooleanField(required=False, default=False)
     options = serializers.JSONField(required=False)
     order = serializers.IntegerField(required=False)
     default = serializers.JSONField(required=False)


Test patch:
Repository: TencentBlueKing/bk-user

Issue:
feat: add SKIP_INIT_DEFAULT_TENANT options



Discussion:

Resolving patch:
diff --git a/src/bk-user/bkuser/apps/tenant/migrations/0003_init_default_tenant.py b/src/bk-user/bkuser/apps/tenant/migrations/0003_init_default_tenant.py
--- a/src/bk-user/bkuser/apps/tenant/migrations/0003_init_default_tenant.py
+++ b/src/bk-user/bkuser/apps/tenant/migrations/0003_init_default_tenant.py
@@ -29,8 +29,12 @@
 
 def forwards_func(apps, schema_editor):
     """初始化本地数据源插件"""
-    admin_username = os.environ.get("INITIAL_ADMIN_USERNAME")
-    admin_password = os.environ.get("INITIAL_ADMIN_PASSWORD")
+    if os.getenv("SKIP_INIT_DEFAULT_TENANT", "false").lower() == "true":
+        logger.info("skip initialize default tenant & data source")
+        return
+
+    admin_username = os.getenv("INITIAL_ADMIN_USERNAME")
+    admin_password = os.getenv("INITIAL_ADMIN_PASSWORD")
     if not (admin_username and admin_password):
         raise RuntimeError("INITIAL_ADMIN_USERNAME and INITIAL_ADMIN_PASSWORD must be set in environment variables")
 


Test patch:
Repository: TencentBlueKing/bk-user

Issue:
产品首页前端 console 支持查看版本信息
参考效果：

![image](https://github.com/TencentBlueKing/bk-user/assets/37054728/fb8be06c-cd8e-4654-b099-e0a2a22efa09)


参考实现：

https://github.com/TencentBlueKing/blueking-paas/pull/1117/files



Discussion:

Resolving patch:
diff --git a/src/bk-user/bkuser/common/views.py b/src/bk-user/bkuser/common/views.py
--- a/src/bk-user/bkuser/common/views.py
+++ b/src/bk-user/bkuser/common/views.py
@@ -189,6 +189,8 @@ def get(self, request, *args, **kwargs):
                 "BK_USER_FEEDBACK_URL": settings.BK_USER_FEEDBACK_URL,
                 # 是否启用蓝鲸通知中心功能
                 "ENABLE_BK_NOTICE": settings.ENABLE_BK_NOTICE,
+                # 前端 console 展示版本信息
+                "BK_BUILD_VERSION": settings.BK_BUILD_VERSION,
             }
 
         except Exception:  # pylint: disable=broad-except
diff --git a/src/bk-user/bkuser/settings.py b/src/bk-user/bkuser/settings.py
--- a/src/bk-user/bkuser/settings.py
+++ b/src/bk-user/bkuser/settings.py
@@ -220,6 +220,8 @@
 BK_USER_DOC_URL = f"{BK_DOCS_URL_PREFIX}/markdown/UserManage/UserGuide/Introduce/README.md"
 # 反馈问题链接
 BK_USER_FEEDBACK_URL = env.str("BK_USER_FEEDBACK_URL", default="https://bk.tencent.com/s-mart/community/")
+# 前端展示信息
+BK_BUILD_VERSION = env.str("BK_BUILD_VERSION", default="unset")
 
 # ------------------------------------------ Celery 配置 ------------------------------------------
 


Test patch:
Repository: facebookresearch/mmf

Issue:
ERROR: 'BaseTrainer' object has no attribute 'args'
I followed the instructions on the https://learnpythia.readthedocs.io/ to setup. I seem to have everything installed, and I could run the collab notebook locally. 

However, when I am trying to run the below command to try out inferences:

python tools/run.py --tasks vqa --datasets textvqa --model lorra --config configs/vqa/textvqa/lorra.yml \
--run_type val --evalai_inference 1 --resume_file data/models/lorra_best.pth

I am getting below error:


}
2019-05-29T20:25:41 INFO: Loading tasks and data
2019-05-29T20:25:44 INFO: CUDA Device 0 is: GeForce GTX 1080 Ti
2019-05-29T20:25:46 INFO: Torch version is: 1.0.0
2019-05-29T20:25:46 ERROR: 'BaseTrainer' object has no attribute 'args'
Traceback (most recent call last):
  File "tools/run.py", line 94, in <module>
    run()
  File "tools/run.py", line 82, in run
    trainer.load()
  File "/root/pythia/pythia/trainers/base_trainer.py", line 46, in load
    self.load_extras()
  File "/root/pythia/pythia/trainers/base_trainer.py", line 139, in load_extras
    self.checkpoint = Checkpoint(self)
  File "/root/pythia/pythia/utils/checkpoint.py", line 28, in __init__
    self.ckpt_foldername += foldername_from_config_override(self.trainer.args)
AttributeError: 'BaseTrainer' object has no attribute 'args'


I seem to be doing something wrong, any help would be great. I didn't change any code or config yet.


Discussion:

Resolving patch:
diff --git a/pythia/utils/build_utils.py b/pythia/utils/build_utils.py
--- a/pythia/utils/build_utils.py
+++ b/pythia/utils/build_utils.py
@@ -27,7 +27,12 @@ def build_trainer(args, *rest, **kwargs):
 
     trainer_type = config.training_parameters.trainer
     trainer_cls = registry.get_trainer_class(trainer_type)
-    return trainer_cls(config)
+    trainer_obj = trainer_cls(config)
+
+    # Set args as an attribute for future use
+    setattr(trainer_obj, 'args', args)
+
+    return trainer_obj
 
 
 def build_model(config):


Test patch:
Repository: facebookresearch/mmf

Issue:
[bug] Distributed Training doesn't converge
## 🐛 Bug

Distributed training in Pythia currently doesn't converge perfectly for Pythia. The issue occurs due to https://github.com/facebookresearch/pythia/blob/master/pythia/utils/general.py#L115 where we don't check if model is instance of `DistributedDataParallel`.

## Command

```
python -u -m torch.distributed.launch --nproc_per_node 2 tools/run.py --tasks vqa --datasets vqa2  --model pythia --config configs/vqa/vqa2/pythia.yml --batch_size 256  --num_workers 4 --run_type train training_parameters.distributed True training_parameters.seed 1234
```

## To Reproduce

Steps to reproduce the behavior:

1. Run the command above and compare with the results of the following command:

```
python -u tools/run.py --tasks vqa --datasets vqa2  --model pythia --config configs/vqa/vqa2/pythia.yml --batch_size 256  --num_workers 4 --run_type train --seed 1234 training_parameters.data_parallel True
```


## Expected behavior

The distributed setup should converge.



Discussion:

Resolving patch:
diff --git a/pythia/utils/checkpoint.py b/pythia/utils/checkpoint.py
--- a/pythia/utils/checkpoint.py
+++ b/pythia/utils/checkpoint.py
@@ -202,9 +202,6 @@ def _get_vcs_fields(self):
         }
 
     def save(self, iteration, update_best=False):
-        # Sync all models before we start the save process
-        synchronize()
-
         # Only save in main process
         if not is_main_process():
             return
diff --git a/pythia/utils/general.py b/pythia/utils/general.py
--- a/pythia/utils/general.py
+++ b/pythia/utils/general.py
@@ -119,7 +119,8 @@ def get_optimizer_parameters(model, config):
     if has_custom:
         parameters = model.get_optimizer_parameters(config)
 
-    is_parallel = isinstance(model, nn.DataParallel)
+    is_parallel = (isinstance(model, nn.DataParallel) or
+        isinstance(model, nn.parallel.DistributedDataParallel))
 
     if is_parallel and hasattr(model.module, "get_optimizer_parameters"):
         parameters = model.module.get_optimizer_parameters(config)


Test patch:
Repository: facebookresearch/mmf

Issue:
Minor bug in object detections in extract_features_vmb.py
## 🐛 Bug

<!-- A clear and concise description of what the bug is. -->

I believe this was introduced by the #127, but there's a slight numpy indexing issue that causes the objects to still be detected incorrectly. 

The line in question is [here](https://github.com/facebookresearch/pythia/blob/12f67cd4f67499814bb0b3665ff14dd635800f63/pythia/scripts/features/extract_features_vmb.py#L165). It currently reads

```python
objects = torch.argmax(scores[keep_boxes][start_index:], dim=1)
```

However, `scores` is a tensor of `[num_objects,  object_classes]`, so `start_index` should be indexing the second dimension. The updated line should be

```python
objects = torch.argmax(scores[keep_boxes][:, start_index:], dim=1)
```

I can submit a pull request.


Discussion:

Resolving patch:
diff --git a/pythia/scripts/features/extract_features_vmb.py b/pythia/scripts/features/extract_features_vmb.py
--- a/pythia/scripts/features/extract_features_vmb.py
+++ b/pythia/scripts/features/extract_features_vmb.py
@@ -162,7 +162,7 @@ def _process_feature_extraction(
             feat_list.append(feats[i][keep_boxes])
             bbox = output[0]["proposals"][i][keep_boxes].bbox / im_scales[i]
             # Predict the class label using the scores
-            objects = torch.argmax(scores[keep_boxes][start_index:], dim=1)
+            objects = torch.argmax(scores[keep_boxes][:, start_index:], dim=1)
 
             info_list.append(
                 {


Test patch:
Repository: team-ocean/veros

Issue:
Allow for custom setup folders



Discussion:

Resolving patch:
diff --git a/veros/cli/veros_copy_setup.py b/veros/cli/veros_copy_setup.py
--- a/veros/cli/veros_copy_setup.py
+++ b/veros/cli/veros_copy_setup.py
@@ -7,35 +7,69 @@
 
 import click
 
-SETUPDIR = pkg_resources.resource_filename('veros', 'setup')
-SETUPS = sorted([
-    setup for setup in os.listdir(SETUPDIR)
-    if os.path.isdir(os.path.join(SETUPDIR, setup))
-    and not setup.startswith('_')
-])
+SETUPDIR_ENVVAR = 'VEROS_SETUP_DIR'
 IGNORE_PATTERNS = ['__init__.py', '*.pyc', '__pycache__/']
+SETUPS = {}
+
+setup_dirs = [pkg_resources.resource_filename('veros', 'setup')]
+
+for setup_dir in os.environ.get(SETUPDIR_ENVVAR, '').split(';'):
+    if os.path.isdir(setup_dir):
+        setup_dirs.append(setup_dir)
+
+# populate {setup_name: path} mapping
+for setup_dir in setup_dirs:
+    for setup in os.listdir(setup_dir):
+        setup_path = os.path.join(setup_dir, setup)
+        if not os.path.isdir(setup_path):
+            continue
+        if setup.startswith(('_', '.')):
+            continue
+        SETUPS[setup] = setup_path
+
+SETUP_NAMES = sorted(SETUPS.keys())
 
 
 def copy_setup(setup, to=None):
-    """Copy a standard setup to another directory"""
+    """Copy a standard setup to another directory.
+
+    Argument must be one of: {setups}
+
+    Example:
+
+        $ veros copy-setup global_4deg --to ~/veros-setups/4deg-lowfric
+
+    Further directories containing setup templates can be added to this command
+    via the {setup_envvar} environment variable.
+    """
     if to is None:
         to = os.path.join(os.getcwd(), setup)
 
-    parent = os.path.dirname(os.path.realpath(to))
+    if os.path.exists(to):
+        raise RuntimeError('Target directory must not exist')
+
+    to_parent = os.path.dirname(os.path.realpath(to))
 
-    if not os.path.exists(parent):
-        os.makedirs(parent)
+    if not os.path.exists(to_parent):
+        os.makedirs(to_parent)
 
     ignore = shutil.ignore_patterns(*IGNORE_PATTERNS)
     shutil.copytree(
-        os.path.join(SETUPDIR, setup), to, ignore=ignore
+        SETUPS[setup], to, ignore=ignore
     )
 
 
+copy_setup.__doc__ = copy_setup.__doc__.format(
+    setups=', '.join(SETUP_NAMES), setup_envvar=SETUPDIR_ENVVAR
+)
+
+
 @click.command('veros-copy-setup')
-@click.argument('setup', type=click.Choice(SETUPS), metavar='SETUP')
-@click.option('--to', type=click.Path(dir_okay=False, file_okay=False), required=False,
-              default=None, help='Target directory (default: copy to current working directory)')
+@click.argument('setup', type=click.Choice(SETUP_NAMES), metavar='SETUP')
+@click.option('--to', required=False, default=None,
+              type=click.Path(dir_okay=False, file_okay=False, writable=True),
+              help=('Target directory, must not exist '
+                    '(default: copy to current working directory)'))
 @functools.wraps(copy_setup)
 def cli(*args, **kwargs):
     copy_setup(*args, **kwargs)


Test patch:
Repository: lhotse-speech/lhotse

Issue:
Directory structure of features
I notice that by default lhotse seems to put all the .llc files in one directory.
On many (maybe even most) file systems this scales very poorly because you spend too much time manipulating the meta-info of the directory- particularly when writing.
I think a better default would be to use the first few characters of the hash as a sub-directory name.
Was thinking of making this dependent on how much data there is to process, but I'm concerned people will write their own scripts that assume a certain directory structure, and then get surprised when things are not as they expect.


Discussion:
Yeah, that sounds like a good addition. I'm less concerned about the directory structure assumption because we store paths in the manifests anyway (i.e. I don't see the reason to assume a specific structure when working with the manifests).

Resolving patch:
diff --git a/lhotse/features/io.py b/lhotse/features/io.py
--- a/lhotse/features/io.py
+++ b/lhotse/features/io.py
@@ -203,11 +203,17 @@ def storage_path(self) -> str:
         return self.storage_path_
 
     def write(self, key: str, value: np.ndarray) -> str:
-        output_features_path = (self.storage_path_ / key).with_suffix('.llc')
+        # Introduce a sub-directory that starts with the first 3 characters of the key, that is typically
+        # an auto-generated hash. This allows to avoid filesystem performance problems related to storing
+        # too many files in a single directory.
+        subdir = self.storage_path_ / key[:3]
+        subdir.mkdir(exist_ok=True)
+        output_features_path = (subdir / key).with_suffix('.llc')
         serialized_feats = lilcom.compress(value, tick_power=self.tick_power)
         with open(output_features_path, 'wb') as f:
             f.write(serialized_feats)
-        return output_features_path.name
+        # Include sub-directory in the key, e.g. "abc/abcdef.llc"
+        return str(output_features_path.parent / output_features_path.name)
 
 
 """
@@ -257,9 +263,15 @@ def storage_path(self) -> str:
         return self.storage_path_
 
     def write(self, key: str, value: np.ndarray) -> str:
-        output_features_path = (self.storage_path_ / key).with_suffix('.npy')
+        # Introduce a sub-directory that starts with the first 3 characters of the key, that is typically
+        # an auto-generated hash. This allows to avoid filesystem performance problems related to storing
+        # too many files in a single directory.
+        subdir = self.storage_path_ / key[:3]
+        subdir.mkdir(exist_ok=True)
+        output_features_path = (subdir / key).with_suffix('.npy')
         np.save(output_features_path, value, allow_pickle=False)
-        return output_features_path.name
+        # Include sub-directory in the key, e.g. "abc/abcdef.npy"
+        return str(output_features_path.parent / output_features_path.name)
 
 
 """


Test patch:
Repository: lhotse-speech/lhotse

Issue:
Bug: broken import from augmentations
Hi I installed the latest pip version of lhotse and I am getting an import error when using the lhotse CLI:

Setup:
```
python3.7.0 
lhotse==0.2.0
```

To reproduce, try either from the following lines:
```
lhotse convert-kaldi <data-dir> 16000 <other-data-dir>
python -c "from lhotse.augmentation import available_wav_augmentations"
```


Discussion:

Resolving patch:
diff --git a/lhotse/augmentation/__init__.py b/lhotse/augmentation/__init__.py
--- a/lhotse/augmentation/__init__.py
+++ b/lhotse/augmentation/__init__.py
@@ -1,3 +1,3 @@
 from .common import AugmentFn
 from .torchaudio import *
-from .wavaugment import WavAugmenter, is_wav_augment_available
+from .wavaugment import WavAugmenter, is_wav_augment_available, available_wav_augmentations
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -19,7 +19,7 @@
 
 setup(
     name='lhotse',
-    version='0.2.0',
+    version='0.2.1',
     python_requires='>=3.7.0',
     description='Data preparation for speech processing models training.',
     author='The Lhotse Development Team',


Test patch:
Repository: lhotse-speech/lhotse

Issue:
Cut concatenate doesn't consider the first sample in each batch
Found in #234 


Discussion:

Resolving patch:
diff --git a/lhotse/dataset/cut_transforms/concatenate.py b/lhotse/dataset/cut_transforms/concatenate.py
--- a/lhotse/dataset/cut_transforms/concatenate.py
+++ b/lhotse/dataset/cut_transforms/concatenate.py
@@ -62,7 +62,7 @@ def concat_cuts(
         return CutSet.from_cuts(cuts)
     cuts = sorted(cuts, key=lambda c: c.duration, reverse=True)
     max_duration = cuts[0].duration if max_duration is None else max_duration
-    current_idx = 1
+    current_idx = 0
     while True:
         can_fit = False
         shortest = cuts[-1]


Test patch:
diff --git a/test/dataset/test_sampling.py b/test/dataset/test_sampling.py
--- a/test/dataset/test_sampling.py
+++ b/test/dataset/test_sampling.py
@@ -296,6 +296,24 @@ def test_concat_cuts():
     ]
 
 
+def test_concat_cuts_with_duration_factor():
+    cuts = [
+        dummy_cut(0, duration=10.0),
+        dummy_cut(1, duration=8.0),
+        dummy_cut(2, duration=6.0),
+        dummy_cut(3, duration=5.0),
+        dummy_cut(4, duration=4.0),
+        dummy_cut(5, duration=3.0),
+        dummy_cut(6, duration=2.0),
+    ]
+    concat = concat_cuts(cuts, gap=1.0, max_duration=20.0)
+    assert [c.duration for c in concat] == [
+        10.0 + 1.0 + 2.0 + 1.0 + 3.0,  # == 17.0
+        8.0 + 1.0 + 4.0 + 1.0 + 5.0,  # == 19.0
+        6.0,  # == 6.0
+    ]
+
+
 def test_bucketing_sampler_single_cuts():
     cut_set = DummyManifest(CutSet, begin_id=0, end_id=1000)
     sampler = BucketingSampler(cut_set, sampler_type=SingleCutSampler)