経緯
解凍して、配置して、goapp serve
したらFailed.
Download the App Engine SDK for Go | App Engine standard environment for Go | Google Cloud Platform
パッチ
エラーをみると、set_skip_files_re
関数が無いヨ。といわれている。たしかにWin32FileWatcherクラスだけ実装されていなかった。以下は付け焼き刃的パッチなので、不完全だとおもいます。app.yaml でskip_files パラメータを使用している環境の方はアップデートを待つほうがいいとおもいます。
app.yaml Reference | App Engine standard environment for Python | Google Cloud Platform
Version: 1.9.46 - 2016-11-03 Size: 67.7 MB
go_appengine\google\appengine\tools\devappserver2\win32_file_watcher.py
class Win32FileWatcher(object):
"""Monitors a directory tree for changes using win32 API."""
SUPPORTS_MULTIPLE_DIRECTORIES = False
def __init__(self, directory):
"""Initializer for Win32FileWatcher.
Args:
directory: A string representing the path to a directory that should
be monitored for changes i.e. files and directories added, renamed,
deleted or changed.
"""
self._directory = os.path.abspath(directory)
self._directory_handle = None
self._change_set = set()
self._lock = threading.Lock() # protects self._change_set
self._stop = threading.Event()
self._change_event = threading.Event()
self._thread = None
+ self._skip_files_re = None
+ def set_skip_files_re(self, skip_files_re):
+ """Allows the file watcher to respect skip_files in app.yaml.
+
+ Args:
+ skip_files_re: The skip_files field of current ModuleConfiguration,
+ defined in app.yaml.
+ """
+ self._skip_files_re = skip_files_re
def start(self):
"""Start watching the directory for changes."""
self._directory_handle = ctypes.windll.kernel32.CreateFileW(
ctypes.c_wchar_p(self._directory),
ctypes.c_ulong(_FILE_LIST_DIRECTORY),
ctypes.c_ulong(_FILE_SHARE_READ |
_FILE_SHARE_WRITE),
None,
ctypes.c_ulong(_OPEN_EXISTING),
# required to monitor changes.
ctypes.c_ulong(_FILE_FLAG_BACKUP_SEMANTICS),
None)
if self._directory_handle == _INVALID_HANDLE_VALUE:
raise ctypes.WinError()
self._thread = threading.Thread(
target=self._monitor, name='Win32 File Watcher')
self._thread.start()
def quit(self):
"""Stop watching the directory for changes."""
self._stop.set()
# Note: this will unlock the blocking ReadDirectoryChangesW call.
ctypes.windll.kernel32.CancelIoEx(self._directory_handle, None)
self._thread.join()
ctypes.windll.kernel32.CloseHandle(self._directory_handle)
def changes(self, timeout_ms=0):
"""Returns the paths changed in the watched directory since the last call.
start() must be called before this method.
Args:
timeout_ms: the maximum number of milliseconds you allow this function to
wait for a filesystem change.
Returns:
Returns an iterable of changed directories/files.
"""
if timeout_ms != 0:
self._change_event.wait(timeout_ms / 1000.0)
with self._lock:
result = self._change_set
self._change_set = set()
self._change_event.clear()
return result
def _monitor(self):
buff = ctypes.create_string_buffer(_BUFF_SIZE)
while not self._stop.isSet():
size_returned = ctypes.c_ulong(0)
result = ctypes.windll.kernel32.ReadDirectoryChangesW(
self._directory_handle,
buff,
ctypes.c_ulong(_BUFF_SIZE),
True, # recursive.
ctypes.c_ulong(_FILE_NOTIFY_CHANGE_ANY),
ctypes.byref(size_returned),
None,
None) # this is a blocking call.
if result == 0 and ctypes.GetLastError() == _ERROR_NOTIFY_ENUM_DIR:
logging.warning('Buffer overflow while monitoring for file changes.')
# we need to notify that something changed anyway
with self._lock:
self._change_set |= {'Unknown file'}
if result != 0 and size_returned.value != 0:
additional_changes = _parse_buffer(buff)
with self._lock:
self._change_set |= additional_changes
self._change_event.set()