diff --git a/docs/API.md b/docs/API.md
index 38016f55a..d2cfb6a74 100644
--- a/docs/API.md
+++ b/docs/API.md
@@ -37,8 +37,8 @@ s3Client = Minio(
| [`bucket_exists`](#bucket_exists) | [`copy_object`](#copy_object) | [`presigned_post_policy`](#presigned_post_policy) | [`delete_bucket_policy`](#delete_bucket_policy) |
| [`remove_bucket`](#remove_bucket) | [`stat_object`](#stat_object) | | [`get_bucket_notification`](#get_bucket_notification) |
| [`list_objects`](#list_objects) | [`remove_object`](#remove_object) | | [`set_bucket_notification`](#set_bucket_notification) |
-| [`enable_bucket_versioning`](#enable_bucket_versioning) | [`remove_objects`](#remove_objects) | | [`remove_all_bucket_notification`](#remove_all_bucket_notification) |
-| [`disable_bucket_versioning`](#disable_bucket_versioning) | [`fput_object`](#fput_object) | | [`listen_bucket_notification`](#listen_bucket_notification) |
+| [`get_bucket_versioning`](#get_bucket_versioning) | [`remove_objects`](#remove_objects) | | [`remove_all_bucket_notification`](#remove_all_bucket_notification) |
+| [`set_bucket_versioning`](#set_bucket_versioning) | [`fput_object`](#fput_object) | | [`listen_bucket_notification`](#listen_bucket_notification) |
| | [`fget_object`](#fget_object) | | [`get_bucket_encryption`](#get_bucket_encryption) |
| | [`select_object_content`](#select_object_content) | | [`put_bucket_encryption`](#put_bucket_encryption) |
| | | | [`delete_bucket_encryption`](#delete_bucket_encryption) |
@@ -570,11 +570,11 @@ __Example__
minio.delete_bucket_encryption("my-bucketname")
```
-
+
-### enable_bucket_versioning(bucket_name)
+### get_bucket_versioning(bucket_name)
-Enable object versioning feature in a bucket.
+Get versioning configuration of a bucket.
__Parameters__
@@ -585,25 +585,27 @@ __Parameters__
__Example__
```py
-minio.enable_bucket_versioning("my-bucketname")
+config = minio.get_bucket_versioning("my-bucketname")
+print(config.status)
```
-
+
-### disable_bucket_versioning(bucket_name)
+### set_bucket_versioning(bucket_name, config)
-Disable object versioning feature in a bucket.
+Set versioning configuration to a bucket.
__Parameters__
-| Param | Type | Description |
-|:----------------|:------|:--------------------|
-| ``bucket_name`` | _str_ | Name of the bucket. |
+| Param | Type | Description |
+|:----------------|:-------------------|:--------------------------|
+| ``bucket_name`` | _str_ | Name of the bucket. |
+| ``config`` | _VersioningConfig_ | Versioning configuration. |
__Example__
```py
-minio.disable_bucket_versioning("my-bucketname")
+minio.set_bucket_versioning("my-bucketname", VersioningConfig("Enabled"))
```
## 3. Object operations
diff --git a/minio/__init__.py b/minio/__init__.py
index bf0925cfd..290667516 100644
--- a/minio/__init__.py
+++ b/minio/__init__.py
@@ -36,6 +36,6 @@
# pylint: disable=unused-import
from .api import Minio
from .copy_conditions import CopyConditions
-from .definitions import Bucket, Object
+from .definitions import Bucket, Object, VersioningConfig
from .error import InvalidResponseError, S3Error, ServerError
from .post_policy import PostPolicy
diff --git a/minio/api.py b/minio/api.py
index 517fd4ebb..bb055bf92 100644
--- a/minio/api.py
+++ b/minio/api.py
@@ -58,7 +58,7 @@
parse_list_parts, parse_location_constraint,
parse_multi_delete_response,
parse_multipart_upload_result,
- parse_new_multipart_upload)
+ parse_new_multipart_upload, parse_versioning_config)
from .select import SelectObjectReader
from .signer import (AMZ_DATE_FORMAT, SIGN_V4_ALGORITHM, get_credential_string,
post_presign_v4, presign_v4, sign_v4_s3)
@@ -66,6 +66,7 @@
from .thread_pool import ThreadPool
from .xml_marshal import (marshal_bucket_notifications,
marshal_complete_multipart,
+ marshal_versioning_config,
xml_marshal_bucket_constraint,
xml_marshal_bucket_encryption,
xml_marshal_delete_objects, xml_marshal_select,
@@ -864,14 +865,20 @@ def listen_bucket_notification(self, bucket_name, prefix='', suffix='',
response.close()
response.release_conn()
- def _do_bucket_versioning(self, bucket_name, status):
- """Do versioning support in a bucket."""
+ def set_bucket_versioning(self, bucket_name, config):
+ """
+ Set versioning configuration to a bucket.
+
+ :param bucket_name: Name of the bucket.
+ :param config: :class:`VersioningConfig `.
+
+ Example::
+ minio.set_bucket_versioning(
+ "my-bucketname", VersioningConfig("Enabled"),
+ )
+ """
check_bucket_name(bucket_name)
- body = (
- ''
- '{0}'
- ).format(status).encode()
+ body = marshal_versioning_config(config)
self._execute(
"PUT",
bucket_name,
@@ -880,27 +887,25 @@ def _do_bucket_versioning(self, bucket_name, status):
query_params={"versioning": ""},
)
- def enable_bucket_versioning(self, bucket_name):
+ def get_bucket_versioning(self, bucket_name):
"""
- Enable object versioning feature in a bucket.
+ Get versioning configuration of a bucket.
:param bucket_name: Name of the bucket.
+ :return: :class:`VersioningConfig `.
Example::
- minio.enable_bucket_versioning("my-bucketname")
- """
- self._do_bucket_versioning(bucket_name, "Enabled")
-
- def disable_bucket_versioning(self, bucket_name):
+ config minio.get_bucket_versioning("my-bucketname")
+ print(config.status)
"""
- Disable object versioning feature in a bucket.
-
- :param bucket_name: Name of the bucket.
+ check_bucket_name(bucket_name)
+ response = self._execute(
+ "GET",
+ bucket_name,
+ query_params={"versioning": ""},
+ )
- Example::
- minio.disable_bucket_versioning("my-bucketname")
- """
- self._do_bucket_versioning(bucket_name, "Suspended")
+ return parse_versioning_config(response.data)
def fput_object(self, bucket_name, object_name, file_path,
content_type='application/octet-stream',
diff --git a/minio/definitions.py b/minio/definitions.py
index af4e142d4..be135c934 100644
--- a/minio/definitions.py
+++ b/minio/definitions.py
@@ -472,3 +472,25 @@ def __init__(self, root):
self.parts = [
Part(part_element) for part_element in root.findall("Part")
]
+
+
+class VersioningConfig:
+ """Bucket versioning configuration."""
+
+ def __init__(self, status, mfa_delete=None):
+ if status:
+ status = status.title()
+ if status not in ["", "Enabled", "Suspended"]:
+ raise ValueError("status must be empty, Enabled or Suspended.")
+ self._status = status
+ self._mfa_delete = mfa_delete
+
+ @property
+ def status(self):
+ """Get status."""
+ return self._status or "Off"
+
+ @property
+ def mfa_delete(self):
+ """Get MFA delete."""
+ return self._mfa_delete
diff --git a/minio/parsers.py b/minio/parsers.py
index 1a1da9aed..94d3bee7b 100644
--- a/minio/parsers.py
+++ b/minio/parsers.py
@@ -31,7 +31,8 @@
from xml.etree.ElementTree import ParseError
from .definitions import (Bucket, CopyObjectResult, ListMultipartUploadsResult,
- ListPartsResult, MultipartUploadResult, Object)
+ ListPartsResult, MultipartUploadResult, Object,
+ VersioningConfig)
# minio specific.
from .error import MultiDeleteError, S3Error
from .helpers import RFC3339, RFC3339NANO
@@ -487,3 +488,12 @@ def parse_list_multipart_uploads(data):
def parse_list_parts(data):
"""Parse ListParts API resppnse XML."""
return ListPartsResult(S3Element.fromstring("ListPartsResult", data))
+
+
+def parse_versioning_config(data):
+ """Decode XML data into :class:`VersioningConfig `"""
+ root = S3Element.fromstring("VersioningConfiguration", data)
+ return VersioningConfig(
+ root.get_child_text("Status"),
+ root.get_child_text("MFADelete"),
+ )
diff --git a/minio/xml_marshal.py b/minio/xml_marshal.py
index da922cec4..969212b87 100644
--- a/minio/xml_marshal.py
+++ b/minio/xml_marshal.py
@@ -409,3 +409,14 @@ def xml_marshal_delete_objects(keys):
SubElement(element, "VersionId", version_id)
return _get_xml_data(root)
+
+
+def marshal_versioning_config(config):
+ """Encode versioning configuration to XML bytes."""
+ root = Element("VersioningConfiguration", with_namespace=True)
+ SubElement(root, "Status", config.status)
+ if config.mfa_delete is not None:
+ SubElement(
+ root, "MFADelete", "Enabled" if config.mfa_delete else "Disabled",
+ )
+ return _get_xml_data(root)
diff --git a/tests/functional/tests.py b/tests/functional/tests.py
index 25fd83df3..91cf0ae69 100644
--- a/tests/functional/tests.py
+++ b/tests/functional/tests.py
@@ -38,7 +38,7 @@
import certifi
import urllib3
-from minio import CopyConditions, Minio, PostPolicy
+from minio import CopyConditions, Minio, PostPolicy, VersioningConfig
from minio.error import S3Error
from minio.select.helpers import calculate_crc
from minio.select.options import (CSVInput, CSVOutput, InputSerialization,
@@ -807,7 +807,9 @@ def _test_stat_object(log_entry, sse=None, version_check=False):
_CLIENT.make_bucket(bucket_name)
try:
if version_check:
- _CLIENT.enable_bucket_versioning(bucket_name)
+ _CLIENT.set_bucket_versioning(
+ bucket_name, VersioningConfig("Enabled"),
+ )
# Put/Upload a streaming object of 1 MiB
reader = LimitedRandomReader(length)
_, version_id1 = _CLIENT.put_object(
@@ -875,7 +877,9 @@ def _test_remove_object(log_entry, version_check=False):
_CLIENT.make_bucket(bucket_name)
try:
if version_check:
- _CLIENT.enable_bucket_versioning(bucket_name)
+ _CLIENT.set_bucket_versioning(
+ bucket_name, VersioningConfig("Enabled"),
+ )
_, version_id = _CLIENT.put_object(
bucket_name, object_name, LimitedRandomReader(length), length,
)
@@ -914,7 +918,9 @@ def _test_get_object(log_entry, sse=None, version_check=False):
version_id = None
try:
if version_check:
- _CLIENT.enable_bucket_versioning(bucket_name)
+ _CLIENT.set_bucket_versioning(
+ bucket_name, VersioningConfig("Enabled"),
+ )
_, version_id = _CLIENT.put_object(
bucket_name, object_name, LimitedRandomReader(length),
length, sse=sse,
@@ -965,7 +971,9 @@ def _test_fget_object(log_entry, sse=None, version_check=False):
version_id = None
try:
if version_check:
- _CLIENT.enable_bucket_versioning(bucket_name)
+ _CLIENT.set_bucket_versioning(
+ bucket_name, VersioningConfig("Enabled"),
+ )
_, version_id = _CLIENT.put_object(
bucket_name, object_name, LimitedRandomReader(length),
length, sse=sse,
@@ -1090,7 +1098,9 @@ def _test_list_objects(log_entry, use_api_v1=False, version_check=False):
version_id2 = None
try:
if version_check:
- _CLIENT.enable_bucket_versioning(bucket_name)
+ _CLIENT.set_bucket_versioning(
+ bucket_name, VersioningConfig("Enabled"),
+ )
size = 1 * KB
_, version_id1 = _CLIENT.put_object(
bucket_name, object_name + "-1", LimitedRandomReader(size), size,
@@ -1469,7 +1479,7 @@ def test_presigned_get_object_version( # pylint: disable=invalid-name
_CLIENT.make_bucket(bucket_name)
version_id = None
try:
- _CLIENT.enable_bucket_versioning(bucket_name)
+ _CLIENT.set_bucket_versioning(bucket_name, VersioningConfig("Enabled"))
size = 1 * KB
_, version_id = _CLIENT.put_object(
bucket_name, object_name, LimitedRandomReader(size), size,
@@ -1835,7 +1845,9 @@ def _test_remove_objects(log_entry, version_check=False):
object_names = []
try:
if version_check:
- _CLIENT.enable_bucket_versioning(bucket_name)
+ _CLIENT.set_bucket_versioning(
+ bucket_name, VersioningConfig("Enabled"),
+ )
size = 1 * KB
# Upload some new objects to prepare for multi-object delete test.
for i in range(10):