Coverage for Applications/PyCharm.app/Contents/plugins/python/helpers/pycharm/_jb_utils.py: 52%

71 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2023-09-19 10:04 +0530

1# coding=utf-8 

2 

3__author__ = 'Ilya.Kazakevich' 

4import fnmatch 

5import os 

6import sys 

7 

8 

9class FileChangesTracker(object): 

10 """ 

11 On the instantiation the class records the timestampts of files stored in the folder. 

12 #get_changed_files() return the list of files that have a timestamp different from the one they had during the class instantiation 

13 

14 

15 """ 

16 

17 def __init__(self, folder, patterns="*"): 

18 self.old_files = self._get_changes_from(folder, patterns) 

19 self.folder = folder 

20 self.patterns = patterns 

21 

22 def get_changed_files(self): 

23 assert self.folder, "No changes recorded" 

24 new_files = self._get_changes_from(self.folder, patterns=self.patterns) 

25 return filter(lambda f: f not in self.old_files or self.old_files[f] != new_files[f], new_files.keys()) 

26 

27 @staticmethod 

28 def _get_changes_from(folder, patterns): 

29 result = {} 

30 for tmp_folder, sub_dirs, files in os.walk(folder): 

31 sub_dirs[:] = [s for s in sub_dirs if not s.startswith(".")] 

32 if any(fnmatch.fnmatch(os.path.basename(tmp_folder), p) for p in patterns): 

33 for file in map(lambda f: os.path.join(tmp_folder, f), files): 

34 try: 

35 result.update({file: os.path.getmtime(file)}) 

36 except OSError: # on Windows long path may lead to it: PY-23386 

37 message = "PyCharm can't check if the following file been updated: {0}\n".format(str(file)) 

38 sys.stderr.write(message) 

39 return result 

40 

41 

42def jb_escape_output(output): 

43 """ 

44 Escapes text in manner that is supported on Java side with CommandLineConsoleApi.kt#jbFilter 

45 Check jbFilter doc for more info 

46 

47 :param output: raw text 

48 :return: escaped text 

49 """ 

50 return "##[jetbrains{0}".format(output) 

51 

52 

53class OptionDescription(object): 

54 """ 

55 Wrapper for argparse/optparse option (see VersionAgnosticUtils#get_options) 

56 """ 

57 

58 def __init__(self, name, description, action=None): 

59 self.name = name 

60 self.description = description 

61 self.action = action 

62 

63 

64class VersionAgnosticUtils(object): 

65 """ 

66 "six" emulator: this class fabrics appropriate tool to use regardless python version. 

67 Use it to write code that works both on py2 and py3. # TODO: Use Six instead 

68 """ 

69 

70 @staticmethod 

71 def is_py3k(): 

72 return sys.version_info >= (3, 0) 

73 

74 @staticmethod 

75 def __new__(cls, *more): 

76 """ 

77 Fabrics Py2 or Py3 instance based on py version 

78 """ 

79 real_class = _Py3KUtils if VersionAgnosticUtils.is_py3k() else _Py2Utils 

80 return super(cls, real_class).__new__(real_class, *more) 

81 

82 def to_unicode(self, obj): 

83 """ 

84 

85 :param obj: string to convert to unicode 

86 :return: unicode string 

87 """ 

88 

89 raise NotImplementedError() 

90 

91 def get_options(self, *args): 

92 """ 

93 Hides agrparse/optparse difference 

94  

95 :param args: OptionDescription 

96 :return: options namespace 

97 """ 

98 raise NotImplementedError() 

99 

100 

101class _Py2Utils(VersionAgnosticUtils): 

102 """ 

103 Util for Py2 

104 """ 

105 

106 def to_unicode(self, obj): 

107 if isinstance(obj, unicode): 

108 return obj 

109 try: 

110 return unicode(obj) # Obj may have its own __unicode__ 

111 except (UnicodeDecodeError, AttributeError): 

112 return unicode(str(obj).decode("utf-8")) # or it may have __str__ 

113 

114 def get_options(self, *args): 

115 import optparse 

116 

117 parser = optparse.OptionParser() 

118 for option in args: 

119 assert isinstance(option, OptionDescription) 

120 parser.add_option(option.name, help=option.description, action=option.action) 

121 (options, _) = parser.parse_args() 

122 return options 

123 

124 

125class _Py3KUtils(VersionAgnosticUtils): 

126 """ 

127 Util for Py3 

128 """ 

129 

130 def to_unicode(self, obj): 

131 return str(obj) 

132 

133 def get_options(self, *args): 

134 import argparse 

135 

136 parser = argparse.ArgumentParser() 

137 for option in args: 

138 assert isinstance(option, OptionDescription) 

139 parser.add_argument(option.name, help=option.description, action=option.action) 

140 return parser.parse_args()