Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

# Copyright (c) 2014, Facebook, Inc.  All rights reserved. 

# 

# This source code is licensed under the BSD-style license found in the 

# LICENSE file in the root directory of this source tree. An additional grant 

# of patent rights can be found in the PATENTS file in the same directory. 

# 

"""Helpers for commonly performed file operations""" 

from distutils.spawn import find_executable 

import errno 

import logging 

import os.path 

import shutil 

import tempfile 

 

logger = logging.getLogger('sparts.fileutils') 

 

 

def readfile(path): 

    """Return the contents of the file at `path`""" 

    with open(path, mode='rb') as f: 

        return f.read().decode('UTF-8') 

 

def writefile(path, contents): 

    """Write `contents` to the file at `path`""" 

    logger.debug('writefile("%s", ...)', path) 

    with open(path, mode='wb') as f: 

        return f.write(contents.encode('UTF-8')) 

 

def makedirs(path, *args, **kwargs): 

    """Create necessary directory heirarchy to `path` if it doesn't exist""" 

    try: 

        logger.debug('makedirs("%s", ...)', path) 

        os.makedirs(path, *args, **kwargs) 

    except OSError as err: 

        if err.errno != errno.EEXIST: 

            raise 

 

 

# This function is really handy.  Make it accessible via this module 

find_executable = find_executable 

 

 

def resolve_partition(path): 

    """Return the mount that `path` is present on. 

 

    Requires `psutil`.""" 

    import psutil 

    path = os.path.realpath(path) 

    found = None 

 

    for partition in psutil.disk_partitions('all'): 

        mountpoint = partition.mountpoint 

        if not mountpoint.endswith('/'): 

            mountpoint += '/' 

        if path.startswith(mountpoint): 

            if found is None: 

                found = partition 

            elif len(mountpoint) > len(found.mountpoint): 

                found = partition 

    return found 

 

 

class NamedTemporary(object): 

    def __init__(self): 

        self.delete = True 

        self.close_called = False 

 

    def __del__(self): 

        self.close() 

 

    def __enter__(self): 

        return self 

 

    def __exit__(self, exc, value, tb): 

        self.close() 

 

    def __str__(self): 

        return self.name 

 

    def __repr__(self): 

        """Overridden to include the temp dir path for debugging clarity.""" 

        return "<%s '%s' at 0x%x>" % \ 

            (self.__class__.__name__, self.name, id(self)) 

 

    def close(self): 

        """Trigger cleanup (if it has not been disabled)""" 

        if not self.close_called: 

            if self.delete: 

                self._cleanup() 

            self.close_called = True 

 

    def keep(self): 

        """Request persistence of the contents of this temporary directory. 

 

        Disabled the cleanup logic that is normally triggered on `__exit__()`, 

        `__del__()`, or close() calls.""" 

        self.delete = False 

 

    def _cleanup(self): 

        """Implement this to cleanup after yourself""" 

        raise NotImplementedError() 

 

 

class NamedTemporaryDirectory(NamedTemporary): 

    """Wrapper around `mkdtemp` that cleans up after itself 

 

    These objects provide the following additional nice features: 

 

    - A `name` attribute, which refers to the full temporary path created 

    - The ContextManager protocol, similar to ctx.tempdir, 

      to cleanup as the context exits. 

    - Implicit cleanup on dereference (via `__del__`) 

    - Helpers for reading and writing files relative to this created directory 

    """ 

    def __init__(self, suffix="", prefix=tempfile.template, dir=None): 

        self.name = tempfile.mkdtemp(suffix=suffix, prefix=prefix, dir=dir) 

        super(NamedTemporaryDirectory, self).__init__() 

 

    def _cleanup(self): 

        shutil.rmtree(self.name) 

 

    def writefile(self, path, contents): 

        """Writes `contents` to the `path` relative to this directory""" 

        return writefile(self.join(path), contents) 

 

    def readfile(self, path): 

        """Reads the contents from the `path` relative to this directory""" 

        return readfile(self.join(path)) 

 

    def symlink(self, path, dst): 

        """Create a symlink to `dst` at the `path` relative to this directory""" 

        return os.symlink(dst, self.join(path)) 

 

    def makedirs(self, path): 

        return makedirs(self.join(path)) 

 

    def join(self, *path): 

        return os.path.join(self.name, *path)