dyyyyyyyy/swe-rebench-filtered-1150 huggingface dataset:
task: metadata: install: pip install -e .
patch: diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 12a5d4f..178f172 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,10 @@
 CHANGE LOG
 ==========
 
+0.3.5
+-----
+- Update the sql.Transpiler to collect namedtuples rather than tuples for attr paths
+
 0.3.4
 -----
 - Update tox.ini and clean up linting errors
diff --git a/setup.py b/setup.py
index bbf57bf..bd16f70 100644
--- a/setup.py
+++ b/setup.py
@@ -14,7 +14,7 @@ def long_description():
 
 setup(
     name='scim2-filter-parser',
-    version='0.3.4',
+    version='0.3.5',
     description='A customizable parser/transpiler for SCIM2.0 filters',
     url='https://github.com/15five/scim2-filter-parser',
     maintainer='Paul Logston',
diff --git a/src/scim2_filter_parser/transpilers/sql.py b/src/scim2_filter_parser/transpilers/sql.py
index 6254f1e..2107758 100644
--- a/src/scim2_filter_parser/transpilers/sql.py
+++ b/src/scim2_filter_parser/transpilers/sql.py
@@ -4,9 +4,12 @@ clause based on a SCIM filter.
 """
 import ast
 import string
+import collections
 
 from .. import ast as scim2ast
 
+AttrPath = collections.namedtuple('AttrPath', ['attr_name', 'sub_attr', 'uri'])
+
 
 class Transpiler(ast.NodeTransformer):
     """
@@ -145,7 +148,7 @@ class Transpiler(ast.NodeTransformer):
 
         # Convert attr_name to another value based on map.
         # Otherwise, return None.
-        attr_path_tuple = (attr_name_value, sub_attr_value, uri_value)
+        attr_path_tuple = AttrPath(attr_name_value, sub_attr_value, uri_value)
         self.attr_paths.append(attr_path_tuple)
         return self.attr_map.get(attr_path_tuple)
 

problem_statement: Return NamedTuple rather than tuple.
It would be nice to return a NamedTuple instead of a tuple here: 

https://github.com/15five/scim2-filter-parser/blob/7ddc216f8c3dd1cdb2152944187e8f7f5ee07be2/src/scim2_filter_parser/transpilers/sql.py#L148

This way parts of each path could be accessed by name rather than by index in the tuple.
repo: 15five/scim2-filter-parser
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_transpiler.py b/tests/test_transpiler.py
index b8e1bb4..280c2d3 100644
--- a/tests/test_transpiler.py
+++ b/tests/test_transpiler.py
@@ -36,6 +36,16 @@ class RFCExamples(TestCase):
         self.assertEqual(expected_sql, sql, query)
         self.assertEqual(expected_params, params, query)
 
+    def test_attr_paths_are_created(self):
+        query = 'userName eq "bjensen"'
+        tokens = self.lexer.tokenize(query)
+        ast = self.parser.parse(tokens)
+        self.transpiler.transpile(ast)
+
+        self.assertEqual(len(self.transpiler.attr_paths), 1)
+        for path in self.transpiler.attr_paths:
+            self.assertTrue(isinstance(path, transpile_sql.AttrPath))
+
     def test_username_eq(self):
         query = 'userName eq "bjensen"'
         sql = "username = {a}"
task: metadata: install: pip install -e .[dev]
patch: diff --git a/news/66.bugfix b/news/66.bugfix
new file mode 100644
index 0000000..f920f1e
--- /dev/null
+++ b/news/66.bugfix
@@ -0,0 +1,1 @@
+Fix https to ssh redirection
diff --git a/src/mbed_tools/project/_internal/libraries.py b/src/mbed_tools/project/_internal/libraries.py
index cc417bf..abc4ccb 100644
--- a/src/mbed_tools/project/_internal/libraries.py
+++ b/src/mbed_tools/project/_internal/libraries.py
@@ -42,6 +42,10 @@ class MbedLibReference:
         """
         raw_ref = self.reference_file.read_text().strip()
         url, sep, ref = raw_ref.partition("#")
+
+        if url.endswith("/"):
+            url = url[:-1]
+
         return git_utils.GitReference(repo_url=url, ref=ref)
 
 

problem_statement: mbedtools clone <example> fails
### Description

<!--
A detailed description of what is being reported. Please include steps to reproduce the problem.

Things to consider sharing:
- What version of the package is being used (pip show mbed-tools)?
- What is the host platform and version (e.g. macOS 10.15.2, Windows 10, Ubuntu 18.04 LTS)?
-->
The clone command `mbedtools clone https://github.com/ARMmbed/mbed-os-example-blinky` fails with following error:
```
Cloning Mbed program 'https://github.com/ARMmbed/mbed-os-example-blinky'
Resolving program library dependencies.
ERROR: Cloning git repository from url 'https://github.com/ARMmbed/mbed-os/' failed. Error from VCS:

More information may be available by using the command line option '-v'.
```

### Issue request type

<!--
Please add only one `x` to one of the following types. Do not fill multiple types (split the issue otherwise).


For questions please use https://forums.mbed.com/
-->

- [ ] Enhancement
- [x] Bug

repo: ARMmbed/mbed-tools
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/project/_internal/test_project_data.py b/tests/project/_internal/test_project_data.py
index 51c0fad..6be1510 100644
--- a/tests/project/_internal/test_project_data.py
+++ b/tests/project/_internal/test_project_data.py
@@ -108,13 +108,15 @@ class TestMbedLibReference(TestCase):
         root = pathlib.Path(fs, "foo")
         url = "https://github.com/mylibrepo"
         ref = "latest"
-        full_ref = f"{url}#{ref}"
-        lib = make_mbed_lib_reference(root, ref_url=full_ref)
+        references = [f"{url}#{ref}", f"{url}/#{ref}"]
 
-        reference = lib.get_git_reference()
+        for full_ref in references:
+            lib = make_mbed_lib_reference(root, ref_url=full_ref)
 
-        self.assertEqual(reference.repo_url, url)
-        self.assertEqual(reference.ref, ref)
+            reference = lib.get_git_reference()
+
+            self.assertEqual(reference.repo_url, url)
+            self.assertEqual(reference.ref, ref)
 
 
 class TestMbedOS(TestCase):
task: metadata: install: pip install -e .[dev]
patch: diff --git a/msal/managed_identity.py b/msal/managed_identity.py
index ec032ca..6f85571 100644
--- a/msal/managed_identity.py
+++ b/msal/managed_identity.py
@@ -448,7 +448,9 @@ def _obtain_token_on_azure_vm(http_client, managed_identity, resource):
         }
     _adjust_param(params, managed_identity)
     resp = http_client.get(
-        "http://169.254.169.254/metadata/identity/oauth2/token",
+        os.getenv(
+            "AZURE_POD_IDENTITY_AUTHORITY_HOST", "http://169.254.169.254"
+            ).strip("/") + "/metadata/identity/oauth2/token",
         params=params,
         headers={"Metadata": "true"},
         )

problem_statement: [Bug] Msal does not honor environment variable `AZURE_POD_IDENTITY_AUTHORITY_HOST` in IMDS
We used to honor environment variable `AZURE_POD_IDENTITY_AUTHORITY_HOST` in IMDS

https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/identity/azure-identity/azure/identity/_credentials/imds.py#L36

Seems like MSAL changed the behavior which is a regression.
repo: AzureAD/microsoft-authentication-library-for-python
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_mi.py b/tests/test_mi.py
index c5a99ae..a7c2cb6 100644
--- a/tests/test_mi.py
+++ b/tests/test_mi.py
@@ -121,13 +121,29 @@ class ClientTestCase(unittest.TestCase):
 
 class VmTestCase(ClientTestCase):
 
-    def test_happy_path(self):
+    def _test_happy_path(self) -> callable:
         expires_in = 7890  # We test a bigger than 7200 value here
         with patch.object(self.app._http_client, "get", return_value=MinimalResponse(
             status_code=200,
             text='{"access_token": "AT", "expires_in": "%s", "resource": "R"}' % expires_in,
         )) as mocked_method:
-            self._test_happy_path(self.app, mocked_method, expires_in)
+            super(VmTestCase, self)._test_happy_path(self.app, mocked_method, expires_in)
+            return mocked_method
+
+    def test_happy_path_of_vm(self):
+        self._test_happy_path().assert_called_with(
+            'http://169.254.169.254/metadata/identity/oauth2/token',
+            params={'api-version': '2018-02-01', 'resource': 'R'},
+            headers={'Metadata': 'true'},
+            )
+
+    @patch.dict(os.environ, {"AZURE_POD_IDENTITY_AUTHORITY_HOST": "http://localhost:1234//"})
+    def test_happy_path_of_pod_identity(self):
+        self._test_happy_path().assert_called_with(
+            'http://localhost:1234/metadata/identity/oauth2/token',
+            params={'api-version': '2018-02-01', 'resource': 'R'},
+            headers={'Metadata': 'true'},
+            )
 
     def test_vm_error_should_be_returned_as_is(self):
         raw_error = '{"raw": "error format is undefined"}'
task: metadata: install: pip install -e .[dev]
patch: diff --git a/bqskit/qis/unitary/unitary.py b/bqskit/qis/unitary/unitary.py
index fb797ec..b9f9966 100644
--- a/bqskit/qis/unitary/unitary.py
+++ b/bqskit/qis/unitary/unitary.py
@@ -54,7 +54,14 @@ class Unitary(metaclass=UnitaryMeta):
         if hasattr(self, '_dim'):
             return self._dim
 
-        return int(np.prod(self.radixes))
+        # return int(np.prod(self.radixes))
+        # Above line removed due to failure to handle overflow and
+        # underflows for large dimensions.
+
+        acm = 1
+        for radix in self.radixes:
+            acm *= int(radix)
+        return acm
 
     @abc.abstractmethod
     def get_unitary(self, params: RealVector = []) -> UnitaryMatrix:

problem_statement: `circuit.dim` is 0 for large circuits
If you print `circuit.dim` for a large (e.g. 1024 qubit) circuit, you will get 0.  The 0 is coming from an integer overflow that numpy does not report.

I don't expect the correct answer (2^1024 is absurdly large), but some feedback (an error or warning) would be nice.  Since numpy silently ignores the issue, BQSKit will have to detect the problem.

Some ideas on where to detect the issue:
- In the implementation of `dim` in `UnitaryMatrix`

Some ideas on how to detect the issue:
- check that `np.prod(self.radixes) >= self.radixes[0]`
- find a way to make numpy raise an error or warning
- do the product more manually than using `np.prod`
repo: BQSKit/bqskit
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/qis/unitary/test_props.py b/tests/qis/unitary/test_props.py
new file mode 100644
index 0000000..2df433a
--- /dev/null
+++ b/tests/qis/unitary/test_props.py
@@ -0,0 +1,8 @@
+from __future__ import annotations
+
+from bqskit.ir.circuit import Circuit
+
+
+def test_circuit_dim_overflow() -> None:
+    c = Circuit(1024)
+    assert c.dim != 0
task: metadata: install: pip install -e .
patch: diff --git a/setup.py b/setup.py
index 1e62eb5..afb9bf4 100644
--- a/setup.py
+++ b/setup.py
@@ -22,7 +22,7 @@ with open('README.md') as readme:
 setup(
   name='exchange-metadata-converter',
   packages=find_packages(),
-  version='0.0.8',
+  version='0.0.9',
   license='Apache-2.0',
   description='exchange metadata converters',
   long_description=README,
diff --git a/templates/dlf_out.yaml b/templates/dlf_out.yaml
index b440965..0e8427a 100644
--- a/templates/dlf_out.yaml
+++ b/templates/dlf_out.yaml
@@ -14,7 +14,7 @@
 apiVersion: com.ie.ibm.hpsys/v1alpha1
 kind: Dataset
 metadata:
-  name: '{{name}}'
+  name: '{{id}}'
   labels:
     version: '{{version}}'
 spec:

problem_statement: Non-compliant metadata.name in the generated DLF YAML
The `metadata.name` in the generated DLF YAML does not comply with the Kubernetes spec for DNS-1123 subdomain names.


```JSON
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "Dataset.com.ie.ibm.hpsys \"Finance Proposition Bank\" is invalid: metadata.name: Invalid value: \"Finance Proposition Bank\": a DNS-1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')",
  "reason": "Invalid",
  "details": {
    "name": "Finance Proposition Bank",
    "group": "com.ie.ibm.hpsys",
    "kind": "Dataset",
    "causes": [
      {
        "reason": "FieldValueInvalid",
        "message": "Invalid value: \"Finance Proposition Bank\": a DNS-1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')",
        "field": "metadata.name"
      }
    ]
  },
  "code": 422
}
```

@ptitzler 
repo: CODAIT/exchange-metadata-converter
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_dlf.py b/tests/test_dlf.py
index 9e37f60..e593f79 100644
--- a/tests/test_dlf.py
+++ b/tests/test_dlf.py
@@ -48,7 +48,7 @@ class TestDLF(unittest.TestCase):
                              'com.ie.ibm.hpsys/v1alpha1')
             self.assertEqual(out_dict['kind'], 'Dataset')
             self.assertEqual(out_dict['metadata']['name'],
-                             self.in_yamls['name'])
+                             self.in_yamls['id'])
             self.assertEqual(out_dict['metadata']['labels']['version'],
                              self.in_yamls['version'])
             self.assertEqual(out_dict['spec']['type'],
task: metadata: install: pip install -e .[dev]
patch: diff --git a/ffmpy/__init__.py b/ffmpy/__init__.py
new file mode 100644
index 0000000..fc682bb
--- /dev/null
+++ b/ffmpy/__init__.py
@@ -0,0 +1,3 @@
+from .ffmpy import FFExecutableNotFoundError, FFmpeg, FFprobe, FFRuntimeError
+
+__all__ = ["FFmpeg", "FFprobe", "FFExecutableNotFoundError", "FFRuntimeError"]
diff --git a/ffmpy.py b/ffmpy/ffmpy.py
similarity index 100%
rename from ffmpy.py
rename to ffmpy/ffmpy.py
diff --git a/py.typed b/ffmpy/py.typed
similarity index 100%
rename from py.typed
rename to ffmpy/py.typed
diff --git a/pyproject.toml b/pyproject.toml
index 01e7dfc..bce62a5 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -40,7 +40,7 @@ classifiers = [
   "Operating System :: POSIX :: Linux",
   "Operating System :: MacOS :: MacOS X",
 ]
-packages = [{ include = "ffmpy.py" }, { include = "py.typed" }]
+packages = [{ include = "ffmpy" }]
 
 [tool.poetry.dependencies]
 python = "^3.8"

problem_statement: Bug: ffmpy breaks all typedefs in some situations
Hi there 👋  Great package thanks for your work :)

I recently spent several hours dealing with an issue in VSCode where all type annotations were broken and the root cause was the `py.typed` file that this package puts into the root of `site-packages` (see https://github.com/microsoft/pylance-release/issues/4844#issuecomment-2491843821).

It definitely seems accidental to express typedef readiness for _all_ site packages. Would you be willing to restructure this into a `ffmpy/` directory package instead of the single file, so this doesn't happen to others?


repo: Ch00k/ffmpy
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_cmd_execution.py b/tests/test_cmd_execution.py
index fd9f559..576e242 100644
--- a/tests/test_cmd_execution.py
+++ b/tests/test_cmd_execution.py
@@ -202,7 +202,7 @@ def test_terminate_process() -> None:
     assert ff.process.returncode == -15
 
 
-@mock.patch("ffmpy.subprocess.Popen")
+@mock.patch("ffmpy.ffmpy.subprocess.Popen")
 def test_custom_env(popen_mock: mock.MagicMock) -> None:
     ff = FFmpeg()
     popen_mock.return_value.communicate.return_value = ("output", "error")
@@ -213,7 +213,7 @@ def test_custom_env(popen_mock: mock.MagicMock) -> None:
     )
 
 
-@mock.patch("ffmpy.subprocess.Popen")
+@mock.patch("ffmpy.ffmpy.subprocess.Popen")
 def test_arbitraty_popen_kwargs(popen_mock: mock.MagicMock) -> None:
     ff = FFmpeg()
     popen_mock.return_value.communicate.return_value = ("output", "error")
task: metadata: install: pip install -e .[dev]
patch: diff --git a/HISTORY.rst b/HISTORY.rst
index 796bf32..608aaa0 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -3,6 +3,14 @@ History
 =======
 
 
+0.9.4 (2017-04-20)
+------------------
+
+* Fixed major bug where activate/deactivate scripts were not being generated (`#49`_).
+
+.. _`#49`: https://github.com/ESSS/conda-devenv/issues/49
+
+
 0.9.3 (2017-04-10)
 ------------------
 
diff --git a/conda_devenv/devenv.py b/conda_devenv/devenv.py
index 66b6bf9..16d174c 100644
--- a/conda_devenv/devenv.py
+++ b/conda_devenv/devenv.py
@@ -269,7 +269,10 @@ def __call_conda_env_update(args, output_filename):
     try:
         del command[0]
         sys.argv = command
-        return _call_conda()
+        try:
+            return _call_conda()
+        except SystemExit as e:
+            return e.code
     finally:
         sys.argv = old_argv
 

problem_statement: 0.9.3 broken: no longer generates activate/deactivate scripts
#46 introduced a bug: `conda-devenv` now calls `conda_env.main` directly, which probably calls `sys.exit()`, which skips activate/deactivate scripts generation.
repo: ESSS/conda-devenv
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_main.py b/tests/test_main.py
index 3fd56e2..4f0db10 100644
--- a/tests/test_main.py
+++ b/tests/test_main.py
@@ -17,19 +17,20 @@ def patch_conda_calls(mocker):
     mocker.patch.object(devenv, 'write_activate_deactivate_scripts', autospec=True)
 
 
-@pytest.mark.parametrize('input_name, expected_output_name', [
-    ('environment.devenv.yml', 'environment.yml'),
-    ('environment.yml', 'environment.yml'),
+@pytest.mark.parametrize('input_name, write_scripts_call_count', [
+    ('environment.devenv.yml', 1),
+    ('environment.yml', 0),
 ])
 @pytest.mark.usefixtures('patch_conda_calls')
-def test_handle_input_file(tmpdir, input_name, expected_output_name):
+def test_handle_input_file(tmpdir, input_name, write_scripts_call_count):
     """
     Test how conda-devenv handles input files: devenv.yml and pure .yml files.
     """
     argv = []
     def call_conda_mock():
         argv[:] = sys.argv[:]
-        return 0
+        # simulate that we actually called conda's main, which calls sys.exit()
+        sys.exit(0)
 
     devenv._call_conda.side_effect = call_conda_mock
     
@@ -41,8 +42,9 @@ def test_handle_input_file(tmpdir, input_name, expected_output_name):
     '''))
     assert devenv.main(['--file', str(filename), '--quiet']) == 0
     assert devenv._call_conda.call_count == 1
-    cmdline = 'env update --file {} --prune --quiet'.format(tmpdir.join(expected_output_name))
+    cmdline = 'env update --file {} --prune --quiet'.format(tmpdir.join('environment.yml'))
     assert argv == cmdline.split()
+    assert devenv.write_activate_deactivate_scripts.call_count == write_scripts_call_count
 
 
 @pytest.mark.parametrize('input_name', ['environment.devenv.yml', 'environment.yml'])
task: metadata: install: pip install -e .
patch: diff --git a/conllu/parser.py b/conllu/parser.py
index 16ec94b..7456879 100644
--- a/conllu/parser.py
+++ b/conllu/parser.py
@@ -141,7 +141,7 @@ def parse_id_value(value):
 
 
 ANY_ID = re.compile(ID_SINGLE.pattern + "|" + ID_RANGE.pattern + "|" + ID_DOT_ID.pattern)
-DEPS_RE = re.compile("(" + ANY_ID.pattern + r"):[a-z][a-z_-]*(\:[a-z][a-z_-]*)?")
+DEPS_RE = re.compile("(" + ANY_ID.pattern + r"):[a-zA-Z][a-zA-Z0-9_-]*(\:[a-zA-Z][a-zA-Z0-9_-]*)?")
 MULTI_DEPS_PATTERN = re.compile(r"{}(\|{})*".format(DEPS_RE.pattern, DEPS_RE.pattern))
 
 def parse_paired_list_value(value):

problem_statement: Column 'deps' is not being parsed most of the time
Given the following sentence:

```
Removed.
```

The code at `parser.py:152` looks like this:

```python
def parse_paired_list_value(value):
    if fullmatch(MULTI_DEPS_PATTERN, value):
        return [
            (part.split(":", 1)[1], parse_id_value(part.split(":")[0]))
            for part in value.split("|")
        ]

    return parse_nullable_value(value)
```

Is seems like the definition of `MULTI_DEPS_PATTERN` is not correct. Most `deps` values are returned as strings instead of a list of tuples, because the parsing fails. For example `'1:compound|6:ARG1|9:ARG1'` is considered bad, but according to [the specification](https://universaldependencies.org/format.html#syntactic-annotation) this should be alright. Actually the code for parsing inside of the if-statement works perfectly on this line. `'4:ARG1'` is also being considered flawed, but `'5:measure'` is being considered okay.
repo: EmilStenstrom/conllu
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_parser.py b/tests/test_parser.py
index 0e13a77..2733b58 100644
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -361,6 +361,14 @@ class TestParsePairedListValue(unittest.TestCase):
             parse_paired_list_value("5:conj:and|8.1:nsubj:pass|9:nsubj:xsubj"),
             [("conj:and", 5), ("nsubj:pass", (8, ".", 1)), ("nsubj:xsubj", 9)]
         )
+        self.assertEqual(
+            parse_paired_list_value("1:compound|6:ARG|9:ARG1|10:ARG2"),
+            [('compound', 1), ('ARG', 6), ('ARG1', 9), ('ARG2', 10)]
+        )
+        self.assertNotEqual(
+            parse_paired_list_value("1:compound|6:ARG|9:ARG1|10:2ARG"),
+            [('compound', 1), ('ARG', 6), ('ARG1', 9), ('2ARG', 10)]
+        )
 
     def test_parse_empty(self):
         testcases = [
task: metadata: install: pip install -e .[dev]
patch: diff --git a/google/cloud/sql/connector/connector.py b/google/cloud/sql/connector/connector.py
index ada14cb..5160513 100755
--- a/google/cloud/sql/connector/connector.py
+++ b/google/cloud/sql/connector/connector.py
@@ -19,6 +19,7 @@ from __future__ import annotations
 import asyncio
 from functools import partial
 import logging
+import os
 from threading import Thread
 from types import TracebackType
 from typing import Any, Optional, Union
@@ -171,7 +172,11 @@ class Connector:
         if isinstance(ip_type, str):
             ip_type = IPTypes._from_str(ip_type)
         self._ip_type = ip_type
-        self._universe_domain = universe_domain
+        # check for universe domain arg and then env var
+        if universe_domain:
+            self._universe_domain = universe_domain
+        else:
+            self._universe_domain = os.environ.get("GOOGLE_CLOUD_UNIVERSE_DOMAIN")  # type: ignore
         # construct service endpoint for Cloud SQL Admin API calls
         if not sqladmin_api_endpoint:
             self._sqladmin_api_endpoint = (

problem_statement: Add support for `GOOGLE_CLOUD_UNIVERSE_DOMAIN` env variable
Google Client libraries should check the env variable `GOOGLE_CLOUD_UNIVERSE_DOMAIN` as a secondary way of setting the TPC universe.

Priority should be as follows:

1. Use `universe_domain` param of `Connector` if set
2. Use `GOOGLE_CLOUD_UNIVERSE_DOMAIN` env variable if set
3. Default to `googleapis.com`
repo: GoogleCloudPlatform/cloud-sql-python-connector
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/unit/test_connector.py b/tests/unit/test_connector.py
index d4f53ed..eaf188c 100644
--- a/tests/unit/test_connector.py
+++ b/tests/unit/test_connector.py
@@ -15,6 +15,7 @@ limitations under the License.
 """
 
 import asyncio
+import os
 from typing import Union
 
 from aiohttp import ClientResponseError
@@ -428,3 +429,25 @@ def test_configured_universe_domain_mismatched_credentials(
         "is the default."
     )
     assert exc_info.value.args[0] == err_msg
+
+
+def test_configured_universe_domain_env_var(
+    fake_credentials: Credentials,
+) -> None:
+    """Test that configured universe domain succeeds with universe
+    domain set via GOOGLE_CLOUD_UNIVERSE_DOMAIN env var.
+    """
+    universe_domain = "test-universe.test"
+    # set fake credentials to be configured for the universe domain
+    fake_credentials._universe_domain = universe_domain
+    # set environment variable
+    os.environ["GOOGLE_CLOUD_UNIVERSE_DOMAIN"] = universe_domain
+    # Note: we are not passing universe_domain arg, env var should set it
+    with Connector(credentials=fake_credentials) as connector:
+        # test universe domain was configured
+        assert connector._universe_domain == universe_domain
+        # test property and service endpoint construction
+        assert connector.universe_domain == universe_domain
+        assert connector._sqladmin_api_endpoint == f"https://sqladmin.{universe_domain}"
+    # unset env var
+    del os.environ["GOOGLE_CLOUD_UNIVERSE_DOMAIN"]
task: metadata: install: pip install -e .[dev]
patch: diff --git a/CHANGELOG b/CHANGELOG
index 62b8063..3d37564 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,4 +1,5 @@
 unreleased
+- Preserve literal newlines in docstrings
 - Fix decompilation of complex infinity
 - Add support for Python 3.10 pattern matching
 - Fix incorrect decompilation of lambdas in comprehension guards on Python 3.9 and higher
diff --git a/ast_decompiler/decompiler.py b/ast_decompiler/decompiler.py
index d21c412..e642df8 100644
--- a/ast_decompiler/decompiler.py
+++ b/ast_decompiler/decompiler.py
@@ -834,13 +834,21 @@ class Decompiler(ast.NodeVisitor):
     def write_string(self, string_value: str, kind: Optional[str] = None) -> None:
         if kind is not None:
             self.write(kind)
+        if isinstance(self.get_parent_node(), ast.Expr) and '"""' not in string_value:
+            self.write('"""')
+            s = string_value.encode("unicode-escape").decode("ascii")
+            s = s.replace("\\n", "\n").replace("\\r", "\r")
+            self.write(s)
+            self.write('"""')
+            return
         if self.has_parent_of_type(ast.FormattedValue):
             delimiter = '"'
         else:
             delimiter = "'"
         self.write(delimiter)
         s = string_value.encode("unicode-escape").decode("ascii")
-        self.write(s.replace(delimiter, "\\" + delimiter))
+        s = s.replace(delimiter, "\\" + delimiter)
+        self.write(s)
         self.write(delimiter)
 
     def visit_FormattedValue(self, node: ast.FormattedValue) -> None:

problem_statement: Docstrings are not preserved correctly.
Currently it's impossible to correctly preserve docstrings. This test shows the issue:
```
from .tests import assert_decompiles


def test_docstrings():
    assert_decompiles('''
def a():
    """
    Docstring.
    """
    return 1
''', '''def a():
 """
 Docstring.
 """
 return 1
''', indentation=1)
```

Result:
```
>>> expected
def a():
 """
 Docstring.
 """
 return 1

>>> actual
def a():
 '\n    Docstring.\n    '
 return 1
```

Thoughts: when processing the function body in `write_function_def` we should look at the very first node in the function's body. If the node is of type Expr, and contains a string, then it's most likely docstring of this function and should be processed accordingly.
repo: JelleZijlstra/ast_decompiler
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_basic.py b/tests/test_basic.py
index 5b39dbc..72a8ecb 100644
--- a/tests/test_basic.py
+++ b/tests/test_basic.py
@@ -1,6 +1,6 @@
 import ast
 from ast_decompiler import decompile
-from .tests import check, only_on_version
+from .tests import assert_decompiles, check, only_on_version
 
 
 def test_non_module() -> None:
@@ -380,6 +380,24 @@ def test_Str() -> None:
 b'foo'
 """
     )
+    check('"a\\nb"')
+    assert_decompiles(
+        '''def f():
+    """Doc.
+
+    String.
+
+    """
+''',
+        '''
+def f():
+    """Doc.
+
+    String.
+
+    """
+''',
+    )
 
 
 def test_Attribute() -> None:
task: metadata: install: pip install -e .[test]
patch: diff --git a/src/julia/options.py b/src/julia/options.py
index 5b2728b..52d9364 100644
--- a/src/julia/options.py
+++ b/src/julia/options.py
@@ -134,7 +134,7 @@ class JuliaOptions(object):
     compile = Choices("compile", yes_no_etc("all", "min"))
     depwarn = Choices("depwarn", yes_no_etc("error"))
     warn_overwrite = Choices("warn_overwrite", yes_no_etc())
-    optimize = Choices("optimize", dict(zip(range(4), range(4))))
+    optimize = Choices("optimize", dict(zip(range(4), map(str, range(4)))))
     inline = Choices("inline", yes_no_etc())
     check_bounds = Choices("check_bounds", yes_no_etc())
 

problem_statement: Failure when setting optimize option
This is because pyjulia uses ArgumentsParser to parse --home & --sysimage, but it get the optimize value as an int instead of a string.

I'll submit a PR
repo: JuliaPy/pyjulia
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/src/julia/tests/test_juliaoptions.py b/src/julia/tests/test_juliaoptions.py
index 931438f..b793e73 100644
--- a/src/julia/tests/test_juliaoptions.py
+++ b/src/julia/tests/test_juliaoptions.py
@@ -12,6 +12,7 @@ from julia.core import JuliaOptions
     (dict(depwarn="error"), ["--depwarn", "error"]),
     (dict(sysimage="PATH"), ["--sysimage", "PATH"]),
     (dict(bindir="PATH"), ["--home", "PATH"]),
+    (dict(optimize=3), ["--optimize", "3"]),
 ])
 # fmt: on
 def test_as_args(kwargs, args):
diff --git a/src/julia/tests/test_options.py b/src/julia/tests/test_options.py
index c11e4bd..1ab9cb8 100644
--- a/src/julia/tests/test_options.py
+++ b/src/julia/tests/test_options.py
@@ -1,4 +1,4 @@
-from julia.options import JuliaOptions, options_docs
+from julia.options import JuliaOptions, options_docs, parse_jl_options
 
 
 def parse_options_docs(docs):
@@ -23,3 +23,11 @@ def test_options_docs():
         odef = optdefs.pop(desc.name)
         assert odef["domain"] == desc._domain()
     assert not optdefs
+
+
+def test_parse_jl_options():
+    opts = parse_jl_options(
+        ["--home", "/home", "--sysimage", "/sys/image", "--optimize", "3"]
+    )
+    assert opts.home == "/home"
+    assert opts.sysimage == "/sys/image"
task: metadata: install: pip install -e .
patch: diff --git a/sacc/sacc.py b/sacc/sacc.py
index fcf963d..1cebbba 100644
--- a/sacc/sacc.py
+++ b/sacc/sacc.py
@@ -198,7 +198,7 @@ class Sacc:
         d = DataPoint(data_type, tracers, value, **tags)
         self.data.append(d)
 
-    def add_covariance(self, covariance):
+    def add_covariance(self, covariance, overwrite=False):
         """
         Once you have finished adding data points, add a covariance
         for the entire set.
@@ -208,11 +208,19 @@ class Sacc:
         covariance: array or list
             2x2 numpy array containing the covariance of the added data points
             OR a list of blocks
+        overwrite: bool
+            If True, it overwrites the stored covariance matrix with the given
+            one.
 
         Returns
         -------
         None
         """
+        if self.has_covariance() and not overwrite:
+            raise RuntimeError("This sacc file already contains a covariance"
+                               "matrix. Use overwrite=True if you want to "
+                               "replace it for the new one")
+
         if isinstance(covariance, BaseCovariance):
             cov = covariance
         else:

problem_statement: add_covariance confusing
I find `add_covariance` a bit confusing. From time to time, I find myself rechecking whether `add_covariance` overwrites the current covariance or if it adds the new covariance to the previous one. I think it would be great to check if `has_covariance` is `True` and, if so, raise an Error unless an optional argument `overwrite=True` is given. 
repo: LSSTDESC/sacc
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/test/test_sacc2.py b/test/test_sacc2.py
index 771d6c6..3d79d3f 100644
--- a/test/test_sacc2.py
+++ b/test/test_sacc2.py
@@ -66,6 +66,18 @@ def get_filled_sacc():
     return s
 
 
+def test_add_covariance():
+    s = get_filled_sacc()
+    cov = np.ones((s.mean.size, s.mean.size))
+    s.add_covariance(cov)
+
+    with pytest.raises(RuntimeError):
+        s.add_covariance(cov)
+
+    s.add_covariance(0 * cov, overwrite=True)
+    assert np.all(s.covariance.covmat == 0 * cov)
+
+
 def test_quantity_warning():
     s = sacc.Sacc()
     with pytest.warns(UserWarning):
task: metadata: install: pip install -e .
patch: diff --git a/sqf/analyzer.py b/sqf/analyzer.py
index 1c55885..b4ceea7 100644
--- a/sqf/analyzer.py
+++ b/sqf/analyzer.py
@@ -426,7 +426,7 @@ class Analyzer(BaseInterpreter):
             elif case_found.keyword == Keyword('catch'):
                 extra_scope = {'_exception': Anything()}
             elif case_found.keyword == Keyword('spawn'):
-                extra_scope = {'_thisScript': Script()}
+                extra_scope = {'_thisScript': Script(), '_this': values[0]}
             elif case_found.keyword == Keyword('do') and type(values[0]) == ForType:
                 extra_scope = {values[0].variable.value: Number()}
             for value, t_or_v in zip(values, case_found.types_or_values):

problem_statement: scope warning when using _this in spawned code block
`[2,13]:warning:Local variable "_this" is not from this scope (not private)` when running sqflint over

```sqf
_this spawn {
    hint str _this;
};
```
it does *not* complain when the code block is *call*ed, though.

repo: LordGolias/sqf
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_analyzer.py b/tests/test_analyzer.py
index b12b769..91bc548 100644
--- a/tests/test_analyzer.py
+++ b/tests/test_analyzer.py
@@ -1052,11 +1052,21 @@ class SpecialContext(TestCase):
         analyzer = analyze(parse(code))
         self.assertEqual(analyzer.exceptions, [])
 
-    def test_spawn(self):
+    def test_spawn_thisScript(self):
         code = '[] spawn {x = _thisScript}'
         analyzer = analyze(parse(code))
         self.assertEqual(len(analyzer.exceptions), 0)
 
+    def test_spawn_this_typing_correct(self):
+        code = '"" spawn {hint _this}'
+        analyzer = analyze(parse(code))
+        self.assertEqual(len(analyzer.exceptions), 0)
+
+    def test_spawn_this_typing_error(self):
+        code = '[] spawn {hint _this}'
+        analyzer = analyze(parse(code))
+        self.assertEqual(len(analyzer.exceptions), 1)
+
     def test_spawn_local_vars(self):
         # spawn should not use local variables because they may become undefined (error 1). Likewise,
         # the local variable becomes unused (error 2).
task: metadata: install: pip install -e .
patch: diff --git a/lingua_franca/lang/parse_en.py b/lingua_franca/lang/parse_en.py
index 872c478..2136423 100644
--- a/lingua_franca/lang/parse_en.py
+++ b/lingua_franca/lang/parse_en.py
@@ -1363,7 +1363,7 @@ def extract_datetime_en(string, dateNow, default_time):
             idx += used - 1
             found = True
     # check that we found a date
-    if not date_found:
+    if not date_found():
         return None
 
     if dayOffset is False:

problem_statement: extract_datetime(" ") returns today not None
Clearly this is my favourite method looking at the issues list :yum: 

An empty string passed to `extract_datetime("")` correctly returns `None`.
However a non-empty string that does not contain a date eg `extract_datetime(" ")` returns a datetime of the current day at midnight.

Documentation for the method:
https://mycroft-core.readthedocs.io/en/stable/source/mycroft.util.html#extract-datetime
repo: MycroftAI/lingua-franca
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/test/test_parse.py b/test/test_parse.py
index a6533cf..c1510d9 100644
--- a/test/test_parse.py
+++ b/test/test_parse.py
@@ -481,6 +481,10 @@ class TestNormalize(unittest.TestCase):
         morning = datetime(2017, 6, 27, 8, 1, 2)
         evening = datetime(2017, 6, 27, 20, 1, 2)
         noonish = datetime(2017, 6, 27, 12, 1, 2)
+        self.assertEqual(
+            extract_datetime('feed the fish'), None)
+        self.assertEqual(
+            extract_datetime(' '), None)
         self.assertEqual(
             extract_datetime('feed fish at 10 o\'clock', morning)[0],
             datetime(2017, 6, 27, 10, 0, 0))
task: metadata: install: pip install -e .
patch: diff --git a/Changelog.rst b/Changelog.rst
index f16852e30..5f750fc13 100644
--- a/Changelog.rst
+++ b/Changelog.rst
@@ -1,3 +1,12 @@
+Version 1.10.0.1
+----------------
+
+**2022-??-??**
+
+* Fixed bug that caused a failure when printing date-time data with
+  the first element masked
+  (https://github.com/NCAS-CMS/cfdm/issues/211)
+
 Version 1.10.0.0
 ----------------
 
diff --git a/cfdm/data/data.py b/cfdm/data/data.py
index a48650843..d0c428873 100644
--- a/cfdm/data/data.py
+++ b/cfdm/data/data.py
@@ -506,13 +506,13 @@ class Data(Container, NetCDFHDF5, core.Data):
 
         mask = [False, False, False]
 
+        if isreftime and first is np.ma.masked:
+            first = 0
+            mask[0] = True
+
         if size == 1:
             if isreftime:
                 # Convert reference time to date-time
-                if first is numpy.ma.masked:
-                    first = 0
-                    mask[0] = True
-
                 try:
                     first = type(self)(
                         numpy.ma.array(first, mask=mask[0]), units, calendar

problem_statement: `Data.__str__` fails when the data contains date-times with the first element masked
At cfdm v1.10.0.0 we have:

```python
>>> # v1.10.0.0
>>> import cfdm
>>> import numpy as 
>>> dt = np.ma.array([10, 20], mask=[True, False])
>>> d = cfdm.Data(dt, units='days since 2000-01-01')
>>> str(d)
Traceback
    ...
TypeError: unsupported operand type(s) for +: 'cftime._cftime.DatetimeGregorian' and 'NoneType'
```
but what we expect is 
```python
>>> # Expected behaviour:
>>> d = cfdm.Data(dt, units='days since 2000-01-01')
>>> str(d)
'[--, 2000-01-21 00:00:00]'

```
repo: NCAS-CMS/cfdm
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/cfdm/test/test_Data.py b/cfdm/test/test_Data.py
index fd1a15182..4960a4f9b 100644
--- a/cfdm/test/test_Data.py
+++ b/cfdm/test/test_Data.py
@@ -68,6 +68,13 @@ class DataTest(unittest.TestCase):
             _ = repr(d)
             _ = str(d)
 
+        # Test when the data contains date-times with the first
+        # element masked
+        dt = numpy.ma.array([10, 20], mask=[True, False])
+        d = cfdm.Data(dt, units="days since 2000-01-01")
+        self.assertTrue(str(d) == "[--, 2000-01-21 00:00:00]")
+        self.assertTrue(repr(d) == "<Data(2): [--, 2000-01-21 00:00:00]>")
+
     #    def test_Data__getitem__(self):
     def test_Data__setitem__(self):
         """Test the assignment of data items on Data."""
task: metadata: install: pip install -e .
patch: diff --git a/src/pynwb/ogen.py b/src/pynwb/ogen.py
index d05832fd..a4a21f9c 100644
--- a/src/pynwb/ogen.py
+++ b/src/pynwb/ogen.py
@@ -5,6 +5,7 @@ from .form.utils import docval, popargs, fmt_docval_args
 from . import register_class, CORE_NAMESPACE
 from .base import TimeSeries, _default_resolution, _default_conversion
 from .core import NWBContainer
+from .ecephys import Device
 
 
 @register_class('OptogeneticStimulusSite', CORE_NAMESPACE)
@@ -19,7 +20,7 @@ class OptogeneticStimulusSite(NWBContainer):
 
     @docval({'name': 'name', 'type': str, 'doc': 'The name of this stimulus site'},
             {'name': 'source', 'type': str, 'doc': 'the source of the data'},
-            {'name': 'device', 'type': str, 'doc': 'Name of device in /general/devices'},
+            {'name': 'device', 'type': Device, 'doc': 'the device that was used'},
             {'name': 'description', 'type': str, 'doc': 'Description of site.'},
             {'name': 'excitation_lambda', 'type': str, 'doc': 'Excitation wavelength.'},
             {'name': 'location', 'type': str, 'doc': 'Location of stimulation site.'})

problem_statement: `nwbfile.create_ogen_site` device argument expects string
the `device` argument of `nwbfile.create_ogen_site` takes a string that is the name of the device. I think it should also take the device object. This will make usage more consistent with `nwbfile.create_electrode_group` and `nwbfile.add_electrode` (with `electrode_group`) where the object is given, not the name of the object. Is there a reason the name of the device is used here?
repo: NeurodataWithoutBorders/pynwb
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/unit/pynwb_tests/test_ogen.py b/tests/unit/pynwb_tests/test_ogen.py
index bee99992..b80243d4 100644
--- a/tests/unit/pynwb_tests/test_ogen.py
+++ b/tests/unit/pynwb_tests/test_ogen.py
@@ -1,14 +1,16 @@
 import unittest
 
 from pynwb.ogen import OptogeneticSeries, OptogeneticStimulusSite
+from pynwb.ecephys import Device
 
 
 class OptogeneticSeriesConstructor(unittest.TestCase):
 
     def test_init(self):
-        oS = OptogeneticStimulusSite('site1', 'a test source', 'device', 'description', 'excitation_lambda', 'location')
+        device = Device('name', 'source')
+        oS = OptogeneticStimulusSite('site1', 'a test source', device, 'description', 'excitation_lambda', 'location')
         self.assertEqual(oS.name, 'site1')
-        self.assertEqual(oS.device, 'device')
+        self.assertEqual(oS.device, device)
         self.assertEqual(oS.description, 'description')
         self.assertEqual(oS.excitation_lambda, 'excitation_lambda')
         self.assertEqual(oS.location, 'location')
task: metadata: install: pip install -e .[dev]
patch: diff --git a/HISTORY.rst b/HISTORY.rst
index 66f7cba4..556b131c 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -5,6 +5,7 @@ History
 0.13.x (2020-01-10)
 -------------------
 * Reverted #311, removing the `_rolling` util function. Added optimal keywords to `rolling()` calls.
+* Fixed `ensembles.create_ensemble` errors for builds against xarray master branch.
 
 0.12.x-beta (2019-11-18)
 ------------------------
diff --git a/xclim/ensembles.py b/xclim/ensembles.py
index ab602bc4..8080f212 100644
--- a/xclim/ensembles.py
+++ b/xclim/ensembles.py
@@ -7,7 +7,6 @@ from typing import Union
 
 import numpy as np
 import pandas as pd
-import scipy
 import scipy.stats
 import xarray as xr
 from sklearn.cluster import KMeans
@@ -314,15 +313,16 @@ def _ens_align_datasets(
 
         if time_flag:
 
-            ds["time"] = xr.decode_cf(ds).time
-
-            ds["time"].values = pd.to_datetime(
+            cal1 = xr.decode_cf(ds).time
+            ds.drop_vars("time")
+            ds["time"] = pd.to_datetime(
                 {
-                    "year": ds.time.dt.year,
-                    "month": ds.time.dt.month,
-                    "day": ds.time.dt.day,
+                    "year": cal1.time.dt.year,
+                    "month": cal1.time.dt.month,
+                    "day": cal1.time.dt.day,
                 }
-            )
+            ).values
+
             # if dataset does not have the same time steps pad with nans
             if ds.time.min() > time_all.min() or ds.time.max() < time_all.max():
                 coords = {}

problem_statement: build failing against xarray master
ensembles creation tests seems to be failing with the travis build w/ xarray@master

We might want to take a minute to try to see why and try to get ahead of this... 
repo: Ouranosinc/xclim
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/test_ensembles.py b/tests/test_ensembles.py
index 55d11020..3bd9d27f 100644
--- a/tests/test_ensembles.py
+++ b/tests/test_ensembles.py
@@ -58,6 +58,7 @@ class TestEnsembleStats:
     def test_create_ensemble(self):
         ens = ensembles.create_ensemble(self.nc_files_simple)
         assert len(ens.realization) == len(self.nc_files_simple)
+        assert len(ens.time) == 151
 
         # create again using xr.Dataset objects
         ds_all = []
@@ -94,6 +95,7 @@ class TestEnsembleStats:
         assert len(ens.realization) == len(self.nc_files)
         assert ens.time.dt.year.min() == 1950
         assert ens.time.dt.year.max() == 2100
+        assert len(ens.time) == 151
 
         ii = [i for i, s in enumerate(self.nc_files) if "1970-2050" in s]
         # assert padded with nans
task: metadata: install: pip install -e .[dev]
patch: diff --git a/fmralign/preprocessing.py b/fmralign/preprocessing.py
index 63521e8..0cc4a0a 100644
--- a/fmralign/preprocessing.py
+++ b/fmralign/preprocessing.py
@@ -123,6 +123,14 @@ class ParcellationMasker(BaseEstimator, TransformerMixin):
 
         if isinstance(imgs, Nifti1Image):
             imgs = [imgs]
+        # If images are 3D, add a fourth dimension
+        for i, img in enumerate(imgs):
+            if len(img.shape) == 3:
+                imgs[i] = Nifti1Image(
+                    np.expand_dims(img.get_fdata(), axis=-1),
+                    img.affine,
+                    img.header,
+                )
         # Assert that all images have the same shape
         if len(set([img.shape for img in imgs])) > 1:
             raise NotImplementedError(

problem_statement: [BUG] Inconsistence between 3D inputs and 4D templates
When dealing with one contrast, input images are usually 3D however the template is initialized as a 1 sample 4D image which raises an error when comparing the shapes during preprocessing.
repo: Parietal-INRIA/fmralign
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/fmralign/tests/test_preprocessing.py b/fmralign/tests/test_preprocessing.py
index 1c39e46..970c008 100644
--- a/fmralign/tests/test_preprocessing.py
+++ b/fmralign/tests/test_preprocessing.py
@@ -181,6 +181,15 @@ def test_standardization():
     assert np.abs(np.std(data_array) - 1.0) < 1e-5
 
 
+def test_one_contrast():
+    """Test that ParcellationMasker handles both 3D and\n
+    4D images in the case of one contrast"""
+    img1, _ = random_niimg((8, 7, 6))
+    img2, _ = random_niimg((8, 7, 6, 1))
+    pmasker = ParcellationMasker()
+    pmasker.fit([img1, img2])
+
+
 def test_get_parcellation():
     """Test that ParcellationMasker returns the parcellation mask"""
     n_pieces = 2
@@ -198,3 +207,4 @@ def test_get_parcellation():
 
     assert np.allclose(data, labels)
     assert len(np.unique(data)) == n_pieces
+