docs: def update_bucket(self, bucket_name, access_control='private', version_control=False, log_destination=None, lifecycle_rules=None, tag_list=None, notification_settings=None, region_replication=None, access_policy=None):
  
          '''
              a method for updating the properties of a bucket in S3
  
          :param bucket_name: string with name of bucket
          :param access_control: string with type of access control policy
          :param version_control: [optional] boolean to enable versioning of records
          :param log_destination: [optional] dictionary with bucket name and prefix of log bucket
          :param lifecycle_rules: [optional] list of dictionaries with rules for aging data
          :param tag_list: [optional] list of dictionaries with key and value for tag
          :param notification_settings: [optional] list of dictionaries with notification details
          :param region_replication: [optional] dictionary with replication settings (WIP)
          :param access_policy: [optional] dictionary with policy for user access (WIP)
          :return: list of dictionaries with changes to bucket
          '''
  
          title = '%s.update_bucket' % self.__class__.__name__
          
      # validate inputs
          input_fields = {
              'bucket_name': bucket_name,
              'access_control': access_control,
              'version_control': version_control,
              'log_destination': log_destination,
              'lifecycle_rules': lifecycle_rules,
              'tag_list': tag_list,
              'notification_settings': notification_settings,
              'region_replication': region_replication,
              'access_policy': access_policy
          }
          for key, value in input_fields.items():
              if value:
                  object_title = '%s(%s=%s)' % (title, key, str(value))
                  self.fields.validate(value, '.%s' % key, object_title)
          if log_destination == None:
              input_fields['log_destination'] = {}
          if lifecycle_rules == None:
              input_fields['lifecycle_rules'] = []
          if tag_list == None:
              input_fields['tag_list'] = []
          if notification_settings == None:
              input_fields['notification_settings'] = []
          if region_replication == None:
              input_fields['region_replication'] = {}
          if access_policy == None:
              input_fields['access_policy'] = {}
  
      # verify requirements and limits
          self.list_buckets()
          if not bucket_name in self.bucket_list:
              raise ValueError('S3 bucket "%s" does not exist in aws region %s. Update not applicable.' % (bucket_name, self.iam.region_name))
          if log_destination:
              log_name = log_destination['name']
              if not log_name in self.bucket_list:
                  raise ValueError('S3 Bucket "%s" for logging does not exist in aws region %s.' % (log_name, self.iam.region_name))
              else:
                  log_details = self.read_bucket(log_name)
                  if log_details['access_control'] != 'log-delivery-write':
                      raise ValueError('S3 Bucket "%s" for logging does not have "log-delivery-write" access control.' % log_name)
              if not 'prefix' in log_destination.keys():
                  input_fields['log_destination']['prefix'] = ''
  
      # TODO: check to see if required notification arns exist
          if notification_settings:
              for notification in notification_settings:
                  arn_id = notification['arn']
      
      # retrieve existing bucket fields
          existing_fields = self.read_bucket(bucket_name)
  
      # alphabetize tag list
          if existing_fields['tag_list']:
              existing_fields['tag_list'] = sorted(existing_fields['tag_list'], key=lambda k: k['key'])
          if input_fields['tag_list']:
              input_fields['tag_list'] = sorted(input_fields['tag_list'], key=lambda k: k['key'])
  
      # determine difference between new and old versions
          from labpack.parsing.comparison import compare_records
          change_list = compare_records(input_fields, existing_fields)
          if not change_list:
              self.iam.printer('There are no changes to make to bucket "%s".' % bucket_name)
              return change_list
          
      # process changes
          self.iam.printer('Updating bucket "%s".' % bucket_name, flush=True)
          processed_list = []
          for change in change_list:
  
      # replace access control
              if change['path'][0] == 'access_control' and 'access_control' not in processed_list:
                  kw_args = {
                      'Bucket': bucket_name,
                      'ACL': input_fields['access_control']
                  }
                  try:
                      self.connection.put_bucket_acl(**kw_args)
                      self.iam.printer('.', flush=True)
                  except:
                      raise AWSConnectionError(title)
              processed_list.append('access_control')
  
      # replace version control
              if change['path'][0] == 'version_control' and 'version_control' not in processed_list:
                  if input_fields['version_control']:
                      try:
                          self.connection.put_bucket_versioning(
                              Bucket=bucket_name,
                              VersioningConfiguration={ 'Status': 'Enabled' }
                          )
                          self.iam.printer('.', flush=True)
                      except:
                          raise AWSConnectionError(title)
                  else:
                      try:
                          self.connection.put_bucket_versioning(
                              Bucket=bucket_name,
                              VersioningConfiguration={ 'Status': 'Suspended' }
                          )
                          self.iam.printer('.', flush=True)
                      except:
                          raise AWSConnectionError(title)
                  processed_list.append('version_control')
  
      # replace log destination
              if change['path'][0] == 'log_destination' and 'log_destination' not in processed_list:
                  if input_fields['log_destination']:
                      log_name = input_fields['log_destination']['name']
                      log_prefix = input_fields['log_destination']['prefix']
                      kw_args = {
                          'Bucket': bucket_name,
                          'BucketLoggingStatus': {
                              'LoggingEnabled': {
                                  'TargetBucket': log_name
                              }
                          }
                      }
                      if log_prefix:
                          kw_args['BucketLoggingStatus']['LoggingEnabled']['TargetPrefix'] = log_prefix
                  else:
                      kw_args = {
                          'Bucket': bucket_name,
                          'BucketLoggingStatus': {}
                      }
                  try:
                      self.connection.put_bucket_logging(**kw_args)
                      self.iam.printer('.', flush=True)
                  except:
                      raise AWSConnectionError(title)
                  processed_list.append('log_destination')
  
      # replace lifecycle rules
              if change['path'][0] == 'lifecycle_rules' and 'lifecycle_rules' not in processed_list:
                  if input_fields['lifecycle_rules']:
                      kw_args = {
                          'Bucket': bucket_name,
                          'LifecycleConfiguration': { 'Rules': [ ] }
                      }
                      for rule in input_fields['lifecycle_rules']:
                          details = {
                              'Prefix': rule['prefix'],
                              'Status': 'Enabled'
                          }
                          if rule['action'] == 'archive':
                              if rule['current_version']:
                                  details['Transition'] = {
                                      'Days': rule['longevity'],
                                      'StorageClass': 'GLACIER'
                                  }
                              else:
                                  details['NoncurrentVersionTransition'] = {
                                      'NoncurrentDays': rule['longevity'],
                                      'StorageClass': 'GLACIER'
                                  }
                          else:
                              if rule['current_version']:
                                  details['Expiration'] = { 'Days': rule['longevity'] }
                              else:
                                  details['NoncurrentVersionExpiration'] = { 'NoncurrentDays': rule['longevity'] }
                          kw_args['LifecycleConfiguration']['Rules'].append(details)
                      try:
                          self.connection.put_bucket_lifecycle(**kw_args)
                          self.iam.printer('.', flush=True)
                      except:
                          raise AWSConnectionError(title)
                  else:
                      try:
                          self.connection.delete_bucket_lifecycle( Bucket=bucket_name )
                          self.iam.printer('.', flush=True)
                      except:
                          raise AWSConnectionError(title)
                  processed_list.append('lifecycle_rules')
  
      # replace bucket tags
              if change['path'][0] == 'tag_list' and 'tag_list' not in processed_list:
                  if input_fields['tag_list']:
                      try:
                          self.connection.put_bucket_tagging(
                              Bucket=bucket_name,
                              Tagging={ 'TagSet': self.iam.prepare(input_fields['tag_list']) }
                          )
                          self.iam.printer('.', flush=True)
                      except:
                          raise AWSConnectionError(title)
                  else:
                      try:
                          self.connection.delete_bucket_tagging( Bucket=bucket_name )
                          self.iam.printer('.', flush=True)
                      except:
                          raise AWSConnectionError(title)
                  processed_list.append('tag_list')
  
      # replace notification settings
              if change['path'][0] == 'notification_settings' and 'notification_settings' not in processed_list:
                  kw_args = {
                      'Bucket': bucket_name,
                      'NotificationConfiguration': {}
                  }
                  if input_fields['notification_settings']:
                      for notification in input_fields['notification_settings']:
                          details = {
                              'Events': [],
                              'Filter': { 'Key': { 'FilterRules': [] } }
                          }
                          details['Events'].append(notification['event'])
                          if notification['filters']:
                              for key, value in notification['filters'].items():
                                  filter_details = {
                                      'Name': key,
                                      'Value': value
                                  }
                                  details['Filter']['Key']['FilterRules'].append(filter_details)
                          if notification['service'] == 'sns':
                              details['TopicArn'] = notification['arn']
                              if not 'TopicConfigurations' in kw_args['NotificationConfiguration']:
                                  kw_args['NotificationConfiguration']['TopicConfigurations'] = []
                              kw_args['NotificationConfiguration']['TopicConfigurations'].append(details)
                          elif notification['service'] == 'sqs':
                              details['QueueArn'] = notification['arn']
                              if not 'QueueConfigurations' in kw_args['NotificationConfiguration']:
                                  kw_args['NotificationConfiguration']['QueueConfigurations'] = []
                              kw_args['NotificationConfiguration']['QueueConfigurations'].append(details)
                          elif notification['service'] == 'lambda':
                              if not 'LambdaFunctionConfigurations' in kw_args['NotificationConfiguration']:
                                  kw_args['NotificationConfiguration']['LambdaFunctionConfigurations'] = []
                              details['LambdaFunctionArn'] = notification['arn']
                              kw_args['NotificationConfiguration']['LambdaFunctionConfigurations'].append(details)
                  try:
                      # TODO: response = self.connection.put_bucket_notification_configuration(**kw_args)
                      self.iam.printer('.', flush=True)
                  except:
                      raise AWSConnectionError(title)
                  processed_list.append('notification_settings')
  
      # TODO: replace region replication
              if change['path'][0] == 'region_replication' and 'region_replication' not in processed_list:
                  if input_fields['region_replication']:
                      pass
                  else:
                      pass
                  processed_list.append('region_replication')
  
      # TODO: replace access policy
              if change['path'][0] == 'access_policy' and 'access_policy' not in processed_list:
                  if input_fields['access_policy']:
                      pass
                  else:
                      pass
                  processed_list.append('access_policy')
  
      # report and return change list
          self.iam.printer(' done.')
          return change_list