/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
1
# Copyright (C) 2006, 2007 Canonical Ltd
2
#
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
17
"""Win32-specific helper functions
18
19
Only one dependency: ctypes should be installed.
20
"""
21
22
import os
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
23
import struct
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
24
import sys
25
26
27
# Windows version
28
if sys.platform == 'win32':
29
    _major,_minor,_build,_platform,_text = sys.getwindowsversion()
2245.4.11 by Alexander Belchenko
Small fixes after John's review; added NEWS entry
30
    # from MSDN:
31
    # dwPlatformId
32
    #   The operating system platform.
33
    #   This member can be one of the following values.
34
    #   ==========================  ======================================
35
    #   Value                       Meaning
36
    #   --------------------------  --------------------------------------
37
    #   VER_PLATFORM_WIN32_NT       The operating system is Windows Vista,
38
    #   2                           Windows Server "Longhorn",
39
    #                               Windows Server 2003, Windows XP,
40
    #                               Windows 2000, or Windows NT.
41
    #
42
    #   VER_PLATFORM_WIN32_WINDOWS  The operating system is Windows Me,
43
    #   1                           Windows 98, or Windows 95.
44
    #   ==========================  ======================================
45
    if _platform == 2:
46
        winver = 'Windows NT'
47
    else:
48
        # don't care about real Windows name, just to force safe operations
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
49
        winver = 'Windows 98'
50
else:
51
    winver = None
52
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
53
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
54
# We can cope without it; use a separate variable to help pyflakes
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
55
try:
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
56
    import ctypes
57
    has_ctypes = True
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
58
except ImportError:
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
59
    has_ctypes = False
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
60
else:
61
    if winver == 'Windows 98':
62
        create_buffer = ctypes.create_string_buffer
63
        suffix = 'A'
64
    else:
65
        create_buffer = ctypes.create_unicode_buffer
66
        suffix = 'W'
3023.1.2 by Alexander Belchenko
Martin's review.
67
try:
68
    import win32file
69
    has_win32file = True
70
except ImportError:
71
    has_win32file = False
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
72
73
74
# Special Win32 API constants
75
# Handles of std streams
1704.2.3 by Martin Pool
(win32) Detect terminal width using GetConsoleScreenBufferInfo (Alexander)
76
WIN32_STDIN_HANDLE = -10
77
WIN32_STDOUT_HANDLE = -11
78
WIN32_STDERR_HANDLE = -12
79
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
80
# CSIDL constants (from MSDN 2003)
81
CSIDL_APPDATA = 0x001A      # Application Data folder
82
CSIDL_PERSONAL = 0x0005     # My Documents folder
83
84
# from winapi C headers
85
MAX_PATH = 260
86
UNLEN = 256
87
MAX_COMPUTERNAME_LENGTH = 31
88
1704.2.3 by Martin Pool
(win32) Detect terminal width using GetConsoleScreenBufferInfo (Alexander)
89
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
90
def get_console_size(defaultx=80, defaulty=25):
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
91
    """Return size of current console.
92
93
    This function try to determine actual size of current working
94
    console window and return tuple (sizex, sizey) if success,
95
    or default size (defaultx, defaulty) otherwise.
96
    """
97
    if not has_ctypes:
98
        # no ctypes is found
99
        return (defaultx, defaulty)
100
101
    # To avoid problem with redirecting output via pipe
102
    # need to use stderr instead of stdout
103
    h = ctypes.windll.kernel32.GetStdHandle(WIN32_STDERR_HANDLE)
104
    csbi = ctypes.create_string_buffer(22)
105
    res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
106
107
    if res:
108
        (bufx, bufy, curx, cury, wattr,
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
109
        left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
110
        sizex = right - left + 1
111
        sizey = bottom - top + 1
112
        return (sizex, sizey)
113
    else:
114
        return (defaultx, defaulty)
115
116
117
def get_appdata_location():
118
    """Return Application Data location.
119
    Return None if we cannot obtain location.
120
121
    Returned value can be unicode or plain sring.
122
    To convert plain string to unicode use
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
123
    s.decode(osutils.get_user_encoding())
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
124
    """
125
    if has_ctypes:
126
        try:
127
            SHGetSpecialFolderPath = \
128
                ctypes.windll.shell32.SHGetSpecialFolderPathW
129
        except AttributeError:
130
            pass
131
        else:
132
            buf = ctypes.create_unicode_buffer(MAX_PATH)
133
            if SHGetSpecialFolderPath(None,buf,CSIDL_APPDATA,0):
134
                return buf.value
135
    # from env variable
136
    appdata = os.environ.get('APPDATA')
137
    if appdata:
138
        return appdata
139
    # if we fall to this point we on win98
140
    # at least try C:/WINDOWS/Application Data
141
    windir = os.environ.get('windir')
142
    if windir:
143
        appdata = os.path.join(windir, 'Application Data')
144
        if os.path.isdir(appdata):
145
            return appdata
146
    # did not find anything
147
    return None
148
149
150
def get_home_location():
151
    """Return user's home location.
152
    Assume on win32 it's the <My Documents> folder.
153
    If location cannot be obtained return system drive root,
154
    i.e. C:\
155
156
    Returned value can be unicode or plain sring.
157
    To convert plain string to unicode use
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
158
    s.decode(osutils.get_user_encoding())
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
159
    """
160
    if has_ctypes:
161
        try:
162
            SHGetSpecialFolderPath = \
163
                ctypes.windll.shell32.SHGetSpecialFolderPathW
164
        except AttributeError:
165
            pass
166
        else:
167
            buf = ctypes.create_unicode_buffer(MAX_PATH)
168
            if SHGetSpecialFolderPath(None,buf,CSIDL_PERSONAL,0):
169
                return buf.value
170
    # try for HOME env variable
171
    home = os.path.expanduser('~')
172
    if home != '~':
173
        return home
174
    # at least return windows root directory
175
    windir = os.environ.get('windir')
176
    if windir:
2610.1.1 by Martin Pool
Fix get_home_location on Win98 (gzlist,r=john,r=alexander)
177
        return os.path.splitdrive(windir)[0] + '/'
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
178
    # otherwise C:\ is good enough for 98% users
179
    return 'C:/'
180
181
182
def get_user_name():
183
    """Return user name as login name.
184
    If name cannot be obtained return None.
185
186
    Returned value can be unicode or plain sring.
187
    To convert plain string to unicode use
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
188
    s.decode(osutils.get_user_encoding())
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
189
    """
190
    if has_ctypes:
191
        try:
192
            advapi32 = ctypes.windll.advapi32
193
            GetUserName = getattr(advapi32, 'GetUserName'+suffix)
194
        except AttributeError:
195
            pass
196
        else:
197
            buf = create_buffer(UNLEN+1)
198
            n = ctypes.c_int(UNLEN+1)
199
            if GetUserName(buf, ctypes.byref(n)):
200
                return buf.value
201
    # otherwise try env variables
202
    return os.environ.get('USERNAME', None)
203
204
205
def get_host_name():
206
    """Return host machine name.
207
    If name cannot be obtained return None.
208
209
    Returned value can be unicode or plain sring.
210
    To convert plain string to unicode use
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
211
    s.decode(osutils.get_user_encoding())
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
212
    """
213
    if has_ctypes:
214
        try:
215
            kernel32 = ctypes.windll.kernel32
216
            GetComputerName = getattr(kernel32, 'GetComputerName'+suffix)
217
        except AttributeError:
218
            pass
219
        else:
220
            buf = create_buffer(MAX_COMPUTERNAME_LENGTH+1)
221
            n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1)
222
            if GetComputerName(buf, ctypes.byref(n)):
223
                return buf.value
224
    # otherwise try env variables
225
    return os.environ.get('COMPUTERNAME', None)
226
227
228
def _ensure_unicode(s):
229
    if s and type(s) != unicode:
3224.5.4 by Andrew Bennetts
Fix test suite, mainly weeding out uses of bzrlib.user_encoding.
230
        s = s.decode(osutils.get_user_encoding())
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
231
    return s
232
    
233
234
def get_appdata_location_unicode():
235
    return _ensure_unicode(get_appdata_location())
236
237
def get_home_location_unicode():
238
    return _ensure_unicode(get_home_location())
239
240
def get_user_name_unicode():
241
    return _ensure_unicode(get_user_name())
242
243
def get_host_name_unicode():
244
    return _ensure_unicode(get_host_name())
2568.2.2 by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class
245
246
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
247
def _ensure_with_dir(path):
248
    if not os.path.split(path)[0] or path.startswith(u'*') or path.startswith(u'?'):
249
        return u'./' + path, True
250
    else:
251
        return path, False
252
    
253
def _undo_ensure_with_dir(path, corrected):
254
    if corrected:
255
        return path[2:]
256
    else:
257
        return path
258
259
260
2598.3.1 by Kuno Meyer
fix method rename glob_expand_for_win32 -> win32utils.glob_expand
261
def glob_expand(file_list):
2568.2.2 by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class
262
    """Replacement for glob expansion by the shell.
263
264
    Win32's cmd.exe does not do glob expansion (eg ``*.py``), so we do our own
265
    here.
266
267
    :param file_list: A list of filenames which may include shell globs.
268
    :return: An expanded list of filenames.
269
270
    Introduced in bzrlib 0.18.
271
    """
272
    if not file_list:
273
        return []
274
    import glob
275
    expanded_file_list = []
276
    for possible_glob in file_list:
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
277
        
278
        # work around bugs in glob.glob()
279
        # - Python bug #1001604 ("glob doesn't return unicode with ...")
280
        # - failing expansion for */* with non-iso-8859-* chars
281
        possible_glob, corrected = _ensure_with_dir(possible_glob)
2568.2.2 by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class
282
        glob_files = glob.glob(possible_glob)
283
284
        if glob_files == []:
285
            # special case to let the normal code path handle
286
            # files that do not exists
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
287
            expanded_file_list.append(
288
                _undo_ensure_with_dir(possible_glob, corrected))
2568.2.2 by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class
289
        else:
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
290
            glob_files = [_undo_ensure_with_dir(elem, corrected) for elem in glob_files]
2568.2.2 by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class
291
            expanded_file_list += glob_files
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
292
            
293
    return [elem.replace(u'\\', u'/') for elem in expanded_file_list] 
2681.4.1 by Alexander Belchenko
win32: looking for full path of mail client executable in registry
294
295
296
def get_app_path(appname):
297
    """Look up in Windows registry for full path to application executable.
298
    Typicaly, applications create subkey with their basename
299
    in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\
300
301
    :param  appname:    name of application (if no filename extension
302
                        is specified, .exe used)
303
    :return:    full path to aplication executable from registry,
304
                or appname itself if nothing found.
305
    """
2681.4.3 by Alexander Belchenko
move import _winreg into function get_app_path to avoid ImportError on non-win32 platforms
306
    import _winreg
2681.4.1 by Alexander Belchenko
win32: looking for full path of mail client executable in registry
307
    try:
308
        hkey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
309
                               r'SOFTWARE\Microsoft\Windows'
310
                               r'\CurrentVersion\App Paths')
311
    except EnvironmentError:
312
        return appname
313
314
    basename = appname
315
    if not os.path.splitext(basename)[1]:
316
        basename = appname + '.exe'
317
    try:
318
        try:
319
            fullpath = _winreg.QueryValue(hkey, basename)
320
        except WindowsError:
321
            fullpath = appname
322
    finally:
323
        _winreg.CloseKey(hkey)
324
325
    return fullpath
3023.1.2 by Alexander Belchenko
Martin's review.
326
327
328
def set_file_attr_hidden(path):
329
    """Set file attributes to hidden if possible"""
330
    if has_win32file:
331
        win32file.SetFileAttributes(path, win32file.FILE_ATTRIBUTE_HIDDEN)