Helper to create a tar file with specific contents Usage: with ArchiveMaker() as t: t.add('filename', ...) with t.open() as tar: ... # `tar` is now a TarFile with 'filename' in it!
| 3590 | return result |
| 3591 | |
| 3592 | class ArchiveMaker: |
| 3593 | """Helper to create a tar file with specific contents |
| 3594 | |
| 3595 | Usage: |
| 3596 | |
| 3597 | with ArchiveMaker() as t: |
| 3598 | t.add('filename', ...) |
| 3599 | |
| 3600 | with t.open() as tar: |
| 3601 | ... # `tar` is now a TarFile with 'filename' in it! |
| 3602 | """ |
| 3603 | def __init__(self, **kwargs): |
| 3604 | self.bio = io.BytesIO() |
| 3605 | self.tar_kwargs = dict(kwargs) |
| 3606 | |
| 3607 | def __enter__(self): |
| 3608 | self.tar_w = tarfile.TarFile(mode='w', fileobj=self.bio, **self.tar_kwargs) |
| 3609 | return self |
| 3610 | |
| 3611 | def __exit__(self, *exc): |
| 3612 | self.tar_w.close() |
| 3613 | self.contents = self.bio.getvalue() |
| 3614 | self.bio = None |
| 3615 | |
| 3616 | def add(self, name, *, type=None, symlink_to=None, hardlink_to=None, |
| 3617 | mode=None, size=None, content=None, **kwargs): |
| 3618 | """Add a member to the test archive. Call within `with`. |
| 3619 | |
| 3620 | Provides many shortcuts: |
| 3621 | - default `type` is based on symlink_to, hardlink_to, and trailing `/` |
| 3622 | in name (which is stripped) |
| 3623 | - size & content defaults are based on each other |
| 3624 | - content can be str or bytes |
| 3625 | - mode should be textual ('-rwxrwxrwx') |
| 3626 | |
| 3627 | (add more! this is unstable internal test-only API) |
| 3628 | """ |
| 3629 | name = str(name) |
| 3630 | tarinfo = tarfile.TarInfo(name).replace(**kwargs) |
| 3631 | if content is not None: |
| 3632 | if isinstance(content, str): |
| 3633 | content = content.encode() |
| 3634 | size = len(content) |
| 3635 | if size is not None: |
| 3636 | tarinfo.size = size |
| 3637 | if content is None: |
| 3638 | content = bytes(tarinfo.size) |
| 3639 | if mode: |
| 3640 | tarinfo.mode = _filemode_to_int(mode) |
| 3641 | if symlink_to is not None: |
| 3642 | type = tarfile.SYMTYPE |
| 3643 | tarinfo.linkname = str(symlink_to) |
| 3644 | if hardlink_to is not None: |
| 3645 | type = tarfile.LNKTYPE |
| 3646 | tarinfo.linkname = str(hardlink_to) |
| 3647 | if name.endswith('/') and type is None: |
| 3648 | type = tarfile.DIRTYPE |
| 3649 | if type is not None: |
no outgoing calls
searching dependent graphs…