)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6a30b4b3d26be4ae1e778db711925b148064b599","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"66f9783d_be98ecf4","updated":"2026-08-21 23:10:26.000000000","message":"I think we need to just remove all sysmeta - but we can use the copy hook to do it mw by mw - starting with s3api ... but and THEN SLO?  Like why should s3api have to do SLOs dirty work for it!","commit_id":"828f2f42ef0fabb6c1fa5f5d829e9803609451a6"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6cf815521d07087521b1c87e77b2ee089d371b19","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"77dc646a_3f60a08d","updated":"2026-08-24 16:52:24.000000000","message":"@clay I modified the assertions to match the revised behaviour in s3api: copied mpu\u0027s always have s3 and slo sysmeta stripped, non-mpu SLOs do not have sysmeta stripped (that\u0027s for a future change to SLO)\n\nI also renamed the module and tests to make it less s3api specific.","commit_id":"735847662b790911a84456907339662d2a562e1d"}],"test/probe/test_s3api_copy_sysmeta.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6a30b4b3d26be4ae1e778db711925b148064b599","unresolved":true,"context_lines":[{"line_number":149,"context_line":"        # multipart-manifest\u003dput. SLO generates these values for the new SLO;"},{"line_number":150,"context_line":"        # the identical manifest therefore produces identical values."},{"line_number":151,"context_line":"        # N.B. The s3api copy hook may strip source SLO sysmeta: SLO"},{"line_number":152,"context_line":"        # unconditionally creates these headers for multipart-manifest\u003dput."},{"line_number":153,"context_line":"        self.assertEqual(source_headers[\u0027x-object-sysmeta-slo-etag\u0027],"},{"line_number":154,"context_line":"                         swift_copy_headers[\u0027x-object-sysmeta-slo-etag\u0027])"},{"line_number":155,"context_line":"        self.assertEqual(source_headers[\u0027x-object-sysmeta-slo-size\u0027],"}],"source_content_type":"text/x-python","patch_set":1,"id":"3813f0ed_80e1bbd7","line":152,"updated":"2026-08-21 23:10:26.000000000","message":"the \"may\" here means \"s3api could strip this on swift requests and it wouldn\u0027t break anything\"\n\ni.e.\n\n```\nDIFF STAT:\n swift/common/middleware/s3api/s3api.py          | 2 +-\n swift/common/middleware/s3api/utils.py          | 6 +++---\n test/unit/common/middleware/s3api/test_utils.py | 2 +-\n 3 files changed, 5 insertions(+), 5 deletions(-)\n\nDIFF:\ndiff --git a/swift/common/middleware/s3api/s3api.py b/swift/common/middleware/s3api/s3api.py\nindex 93e7ace24..da5d5860c 100644\n--- a/swift/common/middleware/s3api/s3api.py\n+++ b/swift/common/middleware/s3api/s3api.py\n@@ -456,7 +456,7 @@ class S3ApiMiddleware(object):\n             resp \u003d self.handle_request(req)\n         except NotS3Request:\n             # prevent swift api copying s3api specific sysmeta...\n-            install_copy_hook(env, s3_request\u003dFalse)\n+            install_copy_hook(env)\n             return self.app(env, start_response)\n         except InvalidSubresource as e:\n             self.logger.debug(e.cause)\ndiff --git a/swift/common/middleware/s3api/utils.py b/swift/common/middleware/s3api/utils.py\nindex 7cb20c016..53bb51f35 100644\n--- a/swift/common/middleware/s3api/utils.py\n+++ b/swift/common/middleware/s3api/utils.py\n@@ -436,7 +436,7 @@ class Config(dict):\n             dict.__setitem__(self, key, value)\n \n \n-def install_copy_hook(environ, s3_request\u003dTrue):\n+def install_copy_hook(environ):\n     copy_hook_key \u003d \u0027swift.callback.copy_source_hook\u0027\n     previous_copy_source_hook \u003d environ.get(copy_hook_key)\n \n@@ -453,8 +453,8 @@ def install_copy_hook(environ, s3_request\u003dTrue):\n             if (is_s3api_object_sysmeta(lower_key)\n                     or is_swift3_object_sysmeta(lower_key)):\n                 del sink_req.headers[key]\n-            elif s3_request and lower_key in (\u0027x-object-sysmeta-slo-etag\u0027,\n-                                              \u0027x-object-sysmeta-slo-size\u0027):\n+            elif lower_key in (\u0027x-object-sysmeta-slo-etag\u0027,\n+                               \u0027x-object-sysmeta-slo-size\u0027):\n                 del sink_req.headers[key]\n             elif lower_key \u003d\u003d etag_override_key:\n                 etag, params \u003d parse_header(value)\ndiff --git a/test/unit/common/middleware/s3api/test_utils.py b/test/unit/common/middleware/s3api/test_utils.py\nindex 93645555f..3039cae9b 100644\n--- a/test/unit/common/middleware/s3api/test_utils.py\n+++ b/test/unit/common/middleware/s3api/test_utils.py\n@@ -400,7 +400,7 @@ class TestS3ApiUtils(unittest.TestCase):\n         sink_req \u003d Request.blank(\u0027/v1/AUTH_test/bucket/dest\u0027,\n                                  method\u003d\u0027PUT\u0027, headers\u003dsrc_headers)\n \n-        utils.install_copy_hook(req.environ, s3_request\u003dFalse)\n+        utils.install_copy_hook(req.environ)\n         self.assertIn(\u0027swift.callback.copy_source_hook\u0027, req.environ)\n         req.environ[\u0027swift.callback.copy_source_hook\u0027](\n             req, source_resp, sink_req)\n\nCOMMAND:\ncd /vagrant/swift\npytest -q test/probe/test_s3api_copy_sysmeta.py::TestS3ApiCopySysmeta::test_swift_copy_slo_as_slo test/probe/test_s3api_copy_sysmeta.py::TestS3ApiCopySysmeta::test_swift_copy_mpu_as_slo\n\nOUTPUT:\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d test session starts \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\nplatform linux -- Python 3.10.12, pytest-9.1.1, pluggy-1.6.0\nrootdir: /vagrant/swift\nconfigfile: tox.ini\nplugins: cov-7.1.0\ncollected 2 items\n\ntest/probe/test_s3api_copy_sysmeta.py ..                                 [100%]\n\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d warnings summary \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n../../usr/local/lib/python3.10/dist-packages/boto/plugin.py:40\n  /usr/local/lib/python3.10/dist-packages/boto/plugin.py:40: DeprecationWarning: the imp module is deprecated in favour of importlib and slated for removal in Python 3.12; see the module\u0027s documentation for alternative uses\n    import imp\n\n-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d 2 passed, 1 warning in 26.54s \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n\nEXITCODE:\n0\n```","commit_id":"828f2f42ef0fabb6c1fa5f5d829e9803609451a6"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6a30b4b3d26be4ae1e778db711925b148064b599","unresolved":true,"context_lines":[{"line_number":161,"context_line":"        self._swift_copy(self.swift_slo_source, self.swift_slo_copy)"},{"line_number":162,"context_line":"        swift_copy_headers \u003d self._metadata(self.swift_slo_copy)"},{"line_number":163,"context_line":""},{"line_number":164,"context_line":"        # XXX: Should we REALLY be preserving SLO sysmeta in this case!?"},{"line_number":165,"context_line":"        self.assertEqual(source_headers[\u0027x-object-sysmeta-slo-etag\u0027],"},{"line_number":166,"context_line":"                         swift_copy_headers[\u0027x-object-sysmeta-slo-etag\u0027])"},{"line_number":167,"context_line":"        self.assertEqual(source_headers[\u0027x-object-sysmeta-slo-size\u0027],"}],"source_content_type":"text/x-python","patch_set":1,"id":"e3af8cf5_48e7f3e9","line":164,"updated":"2026-08-21 23:10:26.000000000","message":"think of how great the world would be we just DIDN\u0027T copy sysmeta!?\n\n```\nDIFF STAT:\n swift/common/middleware/s3api/s3api.py          | 2 +-\n swift/common/middleware/s3api/utils.py          | 6 +++---\n test/unit/common/middleware/s3api/test_utils.py | 2 +-\n 3 files changed, 5 insertions(+), 5 deletions(-)\n\nDIFF:\ndiff --git a/swift/common/middleware/s3api/s3api.py b/swift/common/middleware/s3api/s3api.py\nindex 93e7ace24..da5d5860c 100644\n--- a/swift/common/middleware/s3api/s3api.py\n+++ b/swift/common/middleware/s3api/s3api.py\n@@ -456,7 +456,7 @@ class S3ApiMiddleware(object):\n             resp \u003d self.handle_request(req)\n         except NotS3Request:\n             # prevent swift api copying s3api specific sysmeta...\n-            install_copy_hook(env, s3_request\u003dFalse)\n+            install_copy_hook(env)\n             return self.app(env, start_response)\n         except InvalidSubresource as e:\n             self.logger.debug(e.cause)\ndiff --git a/swift/common/middleware/s3api/utils.py b/swift/common/middleware/s3api/utils.py\nindex 7cb20c016..53bb51f35 100644\n--- a/swift/common/middleware/s3api/utils.py\n+++ b/swift/common/middleware/s3api/utils.py\n@@ -436,7 +436,7 @@ class Config(dict):\n             dict.__setitem__(self, key, value)\n \n \n-def install_copy_hook(environ, s3_request\u003dTrue):\n+def install_copy_hook(environ):\n     copy_hook_key \u003d \u0027swift.callback.copy_source_hook\u0027\n     previous_copy_source_hook \u003d environ.get(copy_hook_key)\n \n@@ -453,8 +453,8 @@ def install_copy_hook(environ, s3_request\u003dTrue):\n             if (is_s3api_object_sysmeta(lower_key)\n                     or is_swift3_object_sysmeta(lower_key)):\n                 del sink_req.headers[key]\n-            elif s3_request and lower_key in (\u0027x-object-sysmeta-slo-etag\u0027,\n-                                              \u0027x-object-sysmeta-slo-size\u0027):\n+            elif lower_key in (\u0027x-object-sysmeta-slo-etag\u0027,\n+                               \u0027x-object-sysmeta-slo-size\u0027):\n                 del sink_req.headers[key]\n             elif lower_key \u003d\u003d etag_override_key:\n                 etag, params \u003d parse_header(value)\ndiff --git a/test/unit/common/middleware/s3api/test_utils.py b/test/unit/common/middleware/s3api/test_utils.py\nindex 93645555f..3039cae9b 100644\n--- a/test/unit/common/middleware/s3api/test_utils.py\n+++ b/test/unit/common/middleware/s3api/test_utils.py\n@@ -400,7 +400,7 @@ class TestS3ApiUtils(unittest.TestCase):\n         sink_req \u003d Request.blank(\u0027/v1/AUTH_test/bucket/dest\u0027,\n                                  method\u003d\u0027PUT\u0027, headers\u003dsrc_headers)\n \n-        utils.install_copy_hook(req.environ, s3_request\u003dFalse)\n+        utils.install_copy_hook(req.environ)\n         self.assertIn(\u0027swift.callback.copy_source_hook\u0027, req.environ)\n         req.environ[\u0027swift.callback.copy_source_hook\u0027](\n             req, source_resp, sink_req)\n\nCOMMAND:\ncd /vagrant/swift\npytest -q test/probe/test_s3api_copy_sysmeta.py::TestS3ApiCopySysmeta::test_swift_copy_slo_as_regular_object\n\nOUTPUT:\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d test session starts \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\nplatform linux -- Python 3.10.12, pytest-9.1.1, pluggy-1.6.0\nrootdir: /vagrant/swift\nconfigfile: tox.ini\nplugins: cov-7.1.0\ncollected 1 item\n\ntest/probe/test_s3api_copy_sysmeta.py F                                  [100%]\n\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d FAILURES \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n__________ TestS3ApiCopySysmeta.test_swift_copy_slo_as_regular_object __________\n\nself \u003d \u003ctest.probe.test_s3api_copy_sysmeta.TestS3ApiCopySysmeta testMethod\u003dtest_swift_copy_slo_as_regular_object\u003e\n\n    def test_swift_copy_slo_as_regular_object(self):\n        source_headers \u003d self._assert_source_has_slo_sysmeta(\n            self.swift_slo_source)\n        self._swift_copy(self.swift_slo_source, self.swift_slo_copy)\n        swift_copy_headers \u003d self._metadata(self.swift_slo_copy)\n    \n        # XXX: Should we REALLY be preserving SLO sysmeta in this case!?\n        self.assertEqual(source_headers[\u0027x-object-sysmeta-slo-etag\u0027],\n\u003e                        swift_copy_headers[\u0027x-object-sysmeta-slo-etag\u0027])\nE       KeyError: \u0027x-object-sysmeta-slo-etag\u0027\n\ntest/probe/test_s3api_copy_sysmeta.py:166: KeyError\n```","commit_id":"828f2f42ef0fabb6c1fa5f5d829e9803609451a6"}]}
