def delete_with_retention(self, num_to_retain):
base_backup_sentinel_depth = self.layout.basebackups().count('<STR_LIT:/>') + <NUM_LIT:1><EOL>completed_basebackups = []<EOL>for key in self._backup_list(prefix=self.layout.basebackups()):<EOL><INDENT>key_name = self.layout.key_name(key)<EOL>key_parts = key_name.split('<STR_LIT:/>')<EOL>key_depth = len(key_parts)<EOL>url = '<STR_LIT>'.format(<EOL>scheme=self.layout.scheme,<EOL>bucket=self._container_name(key),<EOL>name=key_name)<EOL>if key_depth == base_backup_sentinel_depth:<EOL><INDENT>match = re.match(storage.COMPLETE_BASE_BACKUP_REGEXP,<EOL>key_parts[-<NUM_LIT:1>])<EOL>if match is None:<EOL><INDENT>continue<EOL><DEDENT>scanned_sn =self._groupdict_to_segment_number(match.groupdict())<EOL>completed_basebackups.append(dict(<EOL>scanned_sn=scanned_sn,<EOL>url=url))<EOL><DEDENT><DEDENT>basebackups = sorted(<EOL>completed_basebackups,<EOL>key=lambda backup: backup['<STR_LIT>'].as_an_integer,<EOL>reverse=True)<EOL>last_retained = None<EOL>if len(basebackups) <= num_to_retain:<EOL><INDENT>detail = None<EOL>if len(basebackups) == <NUM_LIT:0>:<EOL><INDENT>msg = '<STR_LIT>'<EOL>detail = '<STR_LIT>'<EOL><DEDENT>elif len(basebackups) == <NUM_LIT:1>:<EOL><INDENT>last_retained = basebackups[-<NUM_LIT:1>]<EOL>msg = '<STR_LIT>'<EOL><DEDENT>else:<EOL><INDENT>last_retained = basebackups[-<NUM_LIT:1>]<EOL>msg = "<STR_LIT>" % len(basebackups)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>last_retained = basebackups[num_to_retain - <NUM_LIT:1>]<EOL>num_deleting = len(basebackups) - num_to_retain<EOL>msg = "<STR_LIT>" % num_deleting<EOL>detail = "<STR_LIT>" % len(basebackups)<EOL><DEDENT>log_message = dict(msg=msg)<EOL>if detail is not None:<EOL><INDENT>log_message['<STR_LIT>'] = detail<EOL><DEDENT>if last_retained is not None:<EOL><INDENT>log_message['<STR_LIT>'] ="<STR_LIT>" % last_retained['<STR_LIT:url>']<EOL><DEDENT>logger.info(**log_message)<EOL>if last_retained is not None:<EOL><INDENT>self._delete_base_backups_before(last_retained['<STR_LIT>'])<EOL>self._delete_wals_before(last_retained['<STR_LIT>'])<EOL><DEDENT>if self.deleter:<EOL><INDENT>self.deleter.close()<EOL><DEDENT>
Retain the num_to_retain most recent backups and delete all data
before them.