Merge branch '15000-config-api'
[arvados.git] / sdk / python / arvados / commands / put.py
index defd3c3fd5463760bc9836ae9d79f4473d53df85..5773cb4f98792354c671a3cfb3ecb90f7f92f0f9 100644 (file)
@@ -1002,6 +1002,9 @@ class ArvPutUploadJob(object):
     def collection_name(self):
         return self._my_collection().api_response()['name'] if self._my_collection().api_response() else None
 
+    def collection_trash_at(self):
+        return self._my_collection().get_trash_at()
+
     def manifest_locator(self):
         return self._my_collection().manifest_locator()
 
@@ -1120,6 +1123,14 @@ def main(arguments=None, stdout=sys.stdout, stderr=sys.stderr,
     # Trash arguments validation
     trash_at = None
     if args.trash_at is not None:
+        # ciso8601 considers YYYYMM as invalid but YYYY-MM as valid, so here we
+        # make sure the user provides a complete YYYY-MM-DD date.
+        if not re.match(r'^\d{4}(?P<dash>-?)\d{2}?(?P=dash)\d{2}', args.trash_at):
+            logger.error("--trash-at argument format invalid, use --help to see examples.")
+            sys.exit(1)
+        # Check if no time information was provided. In that case, assume end-of-day.
+        if re.match(r'^\d{4}(?P<dash>-?)\d{2}?(?P=dash)\d{2}$', args.trash_at):
+            args.trash_at += 'T23:59:59'
         try:
             trash_at = ciso8601.parse_datetime(args.trash_at)
         except:
@@ -1128,19 +1139,22 @@ def main(arguments=None, stdout=sys.stdout, stderr=sys.stderr,
         else:
             if trash_at.tzinfo is not None:
                 # Timezone aware datetime provided.
-                utcoffset = trash_at.utcoffset()
+                utcoffset = -trash_at.utcoffset()
             else:
                 # Timezone naive datetime provided. Assume is local.
-                utcoffset = datetime.timedelta(hours=-time.timezone/3600)
+                if time.daylight:
+                    utcoffset = datetime.timedelta(seconds=time.altzone)
+                else:
+                    utcoffset = datetime.timedelta(seconds=time.timezone)
             # Convert to UTC timezone naive datetime.
-            trash_at = trash_at.replace(tzinfo=None) - utcoffset
+            trash_at = trash_at.replace(tzinfo=None) + utcoffset
 
         if trash_at <= datetime.datetime.utcnow():
-            logger.error("--trash-at argument should be set in the future")
+            logger.error("--trash-at argument must be set in the future")
             sys.exit(1)
     if args.trash_after is not None:
         if args.trash_after < 1:
-            logger.error("--trash-after argument should be >= 1")
+            logger.error("--trash-after argument must be >= 1")
             sys.exit(1)
         trash_at = datetime.timedelta(seconds=(args.trash_after * 24 * 60 * 60))
 
@@ -1302,10 +1316,21 @@ def main(arguments=None, stdout=sys.stdout, stderr=sys.stderr,
         output = ','.join(writer.data_locators())
     else:
         try:
+            expiration_notice = ""
+            if writer.collection_trash_at() is not None:
+                # Get the local timezone-naive version, and log it with timezone information.
+                if time.daylight:
+                    local_trash_at = writer.collection_trash_at().replace(tzinfo=None) - datetime.timedelta(seconds=time.altzone)
+                else:
+                    local_trash_at = writer.collection_trash_at().replace(tzinfo=None) - datetime.timedelta(seconds=time.timezone)
+                expiration_notice = ". It will expire on {} {}.".format(
+                    local_trash_at.strftime("%Y-%m-%d %H:%M:%S"), time.strftime("%z"))
             if args.update_collection:
-                logger.info(u"Collection updated: '{}'".format(writer.collection_name()))
+                logger.info(u"Collection updated: '{}'{}".format(
+                    writer.collection_name(), expiration_notice))
             else:
-                logger.info(u"Collection saved as '{}'".format(writer.collection_name()))
+                logger.info(u"Collection saved as '{}'{}".format(
+                    writer.collection_name(), expiration_notice))
             if args.portable_data_hash:
                 output = writer.portable_data_hash()
             else: