Repository: mesos Updated Branches: refs/heads/master 2a391e803 -> 52b9c0bec
Updated python CLI package to get properly installed via setup.py. Review: https://reviews.apache.org/r/36819 Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/52b9c0be Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/52b9c0be Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/52b9c0be Branch: refs/heads/master Commit: 52b9c0becc4cf5c349bce08d5ae3cf7d84b28d5b Parents: 2a391e8 Author: haosdent huang <[email protected]> Authored: Fri Aug 14 03:51:58 2015 +0200 Committer: Till Toenshoff <[email protected]> Committed: Fri Aug 14 03:51:58 2015 +0200 ---------------------------------------------------------------------- Makefile.am | 1 + bin/mesos.sh.in | 11 +- configure.ac | 1 + src/Makefile.am | 16 +- src/cli/python/mesos/__init__.py | 17 --- src/cli/python/mesos/cli.py | 57 ------- src/cli/python/mesos/futures.py | 188 ------------------------ src/cli/python/mesos/http.py | 44 ------ src/python/cli/setup.py.in | 37 +++++ src/python/cli/src/mesos/__init__.py | 10 ++ src/python/cli/src/mesos/cli.py | 57 +++++++ src/python/cli/src/mesos/futures.py | 188 ++++++++++++++++++++++++ src/python/cli/src/mesos/http.py | 44 ++++++ src/python/interface/setup.py.in | 2 + src/python/interface/src/mesos/__init__.py | 4 + src/python/native/setup.py.in | 2 + src/python/native/src/mesos/__init__.py | 4 + src/python/protocol/setup.py.in | 2 + src/python/protocol/src/mesos/__init__.py | 4 + src/python/setup.py.in | 2 + 20 files changed, 366 insertions(+), 325 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/Makefile.am ---------------------------------------------------------------------- diff --git a/Makefile.am b/Makefile.am index f8e958d..cb289b4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -30,6 +30,7 @@ pkgconfig_DATA = mesos.pc # Since we generate several files in src/ with config.status, make # sure they're regenerated before we recurse into the src directory. all-recursive: src/python/setup.py \ + src/python/cli/setup.py \ src/python/interface/setup.py \ src/python/native/setup.py \ src/java/mesos.pom http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/bin/mesos.sh.in ---------------------------------------------------------------------- diff --git a/bin/mesos.sh.in b/bin/mesos.sh.in index 5cbeac4..499181b 100644 --- a/bin/mesos.sh.in +++ b/bin/mesos.sh.in @@ -7,9 +7,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -27,11 +27,4 @@ PATH=@abs_top_builddir@/src:${PATH} export PATH -# Add 'src/cli/python' to PYTHONPATH. -# TODO(benh): Remove this if/when we install the 'mesos' module via -# PIP and setuptools. -PYTHONPATH=@abs_top_srcdir@/src/cli/python:${PYTHONPATH} - -export PYTHONPATH - exec @abs_top_builddir@/src/mesos "${@}" http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/configure.ac ---------------------------------------------------------------------- diff --git a/configure.ac b/configure.ac index b9ecafd..a478ebd 100644 --- a/configure.ac +++ b/configure.ac @@ -1315,6 +1315,7 @@ There are two possible workarounds for this issue: AC_CONFIG_FILES([src/examples/python/test-containerizer], [chmod +x src/examples/python/test-containerizer]) AC_CONFIG_FILES([src/python/setup.py]) + AC_CONFIG_FILES([src/python/cli/setup.py]) AC_CONFIG_FILES([src/python/interface/setup.py]) AC_CONFIG_FILES([src/python/native/ext_modules.py]) AC_CONFIG_FILES([src/python/native/setup.py]) http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/src/Makefile.am ---------------------------------------------------------------------- diff --git a/src/Makefile.am b/src/Makefile.am index ffd2024..e990369 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1030,16 +1030,6 @@ dist_bin_SCRIPTS += \ cli/mesos-scp \ cli/mesos-tail -# Also install the supporting scripts for the Python based CLI tools. -# TODO(benh): Use PIP and python/setup.py to do this correctly. -mesospythonpkglibexecdir = $(pkglibexecdir)/python/mesos - -dist_mesospythonpkglibexec_SCRIPTS = \ - cli/python/mesos/__init__.py \ - cli/python/mesos/cli.py \ - cli/python/mesos/futures.py \ - cli/python/mesos/http.py - # Need to distribute/install webui javascript. We use 'pkgdatadir' # instead of 'datadir' as the install directory so we get the the # package name (i.e., 'mesos') as part of the path (i.e., @@ -1295,6 +1285,10 @@ PHONY_TARGETS += clean-java # distribution unconditionally. PYTHON_SOURCE = \ python/src/mesos/__init__.py \ + python/cli/src/mesos/__init__.py \ + python/cli/src/mesos/cli.py \ + python/cli/src/mesos/futures.py \ + python/cli/src/mesos/http.py \ python/interface/src/mesos/__init__.py \ python/interface/src/mesos/interface/__init__.py \ python/native/src/mesos/__init__.py \ @@ -1354,11 +1348,13 @@ $(PYTHON_SOURCE): # can be easily uninstalled. They end up being what gets installed/uninstalled. MESOS_EGGS = \ python/dist/mesos-$(PACKAGE_VERSION)$(PYTHON_EGG_PUREPY_POSTFIX).egg \ + python/dist/mesos.cli-$(PACKAGE_VERSION)$(PYTHON_EGG_PUREPY_POSTFIX).egg \ python/dist/mesos.interface-$(PACKAGE_VERSION)$(PYTHON_EGG_PUREPY_POSTFIX).egg \ python/dist/mesos.native-$(PACKAGE_VERSION)$(PYTHON_EGG_POSTFIX).egg MESOS_WHLS = \ python/dist/mesos-$(PACKAGE_VERSION)$(PYTHON_WHL_PUREPY_POSTFIX).whl \ + python/dist/mesos.cli-$(PACKAGE_VERSION)$(PYTHON_WHL_PUREPY_POSTFIX).whl \ python/dist/mesos.interface-$(PACKAGE_VERSION)$(PYTHON_WHL_PUREPY_POSTFIX).whl \ python/dist/mesos.native-$(PACKAGE_VERSION)$(PYTHON_WHL_POSTFIX).whl http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/src/cli/python/mesos/__init__.py ---------------------------------------------------------------------- diff --git a/src/cli/python/mesos/__init__.py b/src/cli/python/mesos/__init__.py deleted file mode 100644 index 028b0d2..0000000 --- a/src/cli/python/mesos/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env python - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/src/cli/python/mesos/cli.py ---------------------------------------------------------------------- diff --git a/src/cli/python/mesos/cli.py b/src/cli/python/mesos/cli.py deleted file mode 100644 index 857059e..0000000 --- a/src/cli/python/mesos/cli.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env python - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Helper for printing out a message and then the "usage" then exiting. -def usage(message, parser): - import sys - sys.stderr.write(message + '\n') - parser.print_help() - sys.exit(-1) - - -# Helper for printing out a message and then exiting. -def fatal(message): - import sys - sys.stderr.write(message + '\n') - sys.exit(-1) - - -# Helper that uses 'mesos-resolve' to resolve a master IP:port from -# one of: -# zk://host1:port1,host2:port2,.../path -# zk://username:password@host1:port1,host2:port2,.../path -# file://path/to/file (where file contains one of the above) -def resolve(master): - import subprocess - - process = subprocess.Popen( - ['mesos-resolve', master], - stdin=None, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - shell=False) - - status = process.wait() - if status != 0: - raise Exception('Failed to execute \'mesos-resolve %s\':\n%s' - % (master, process.stderr.read())) - - result = process.stdout.read() - process.stdout.close() - process.stderr.close() - return result http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/src/cli/python/mesos/futures.py ---------------------------------------------------------------------- diff --git a/src/cli/python/mesos/futures.py b/src/cli/python/mesos/futures.py deleted file mode 100644 index da2f4ce..0000000 --- a/src/cli/python/mesos/futures.py +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/env python - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -try: - from concurrent.futures import * -except ImportError: - import threading - import time - - from Queue import Queue - from Queue import Empty - - class TimeoutError(Exception): - """The operation timed out""" - - class Future(object): - def __init__(self): - self._lock = threading.RLock() - self._condition = threading.Condition(self._lock) - self._done = False - self._result = None - self._exception = None - self._exc_info = None - self._callbacks = [] - - def cancel(self): - # These futures are possibly backed by threads which can - # not (easily or portably) be interrupted so instead we - # simply don't let people cancel. - - # TODO(benh): If more use cases come about that want to - # differentiate a started versus a - raise False - - def cancelled(self): - return False - - def running(self): - return not self.done() - - def done(self): - with self._lock: - return self._done - - def result(self, timeout=None): - with self._lock: - self._await(timeout) - if self._exception: - raise self._exception - return self._result - - def exception(self, timeout=None): - with self._lock: - self._await(timeout) - if self._exception: - return self._exception - return None - - def add_done_callback(self, fn): - run = False - with self._lock: - if self._done: - run = True - else: - self._callbacks.append(fn) - if run: - try: - fn(self) - except: - # TODO(benh): Log if Exception, but semantics tell - # us to ignore regardless. - pass - - def set_result(self, result): - with self._lock: - self._result = result - self._finish() - - def set_exception(self, exception): - with self._lock: - self._exception = exception - self._finish() - - def _await(self, timeout): - with self._lock: - if not self._done: - self._condition.wait(timeout) - if not self._done: - raise TimeoutError() - - def _finish(self): - callbacks = None - with self._lock: - self._done = True - callbacks = self._callbacks - self._callbacks = None - for cb in callbacks: - try: - cb(self) - except: - # TODO(benh): Log if Exception, but semantics tell - # us to ignore regardless. - pass - - - class Executor(object): - def __enter__(self): - return self - - def __exit__(self, type, value, traceback): - self.shutdown() - - - def as_completed(futures, timeout=None): - # Record the start time in order to determine the remaining - # timeout as futures are completed. - start = time.time() - - # Use a queue to collect the done futures. - queue = Queue() - - # Define a helper for the future "done callback". - def done(future): - queue.put(future) - - # Add a "done callback" for each future. - for future in futures: - future.add_done_callback(done) - - # Helper to determine the remaining timeout. - def remaining(): - if timeout is None: - return None - end = start + timeout - remaining = end - time.time() - return remaining if remaining >= 0 else 0 - - # Now wait until all the futures have completed or we timeout. - finished = 0 - while finished < len(futures): - try: - yield queue.get(timeout=remaining()) - except Empty: - raise TimeoutError() - else: - finished += 1 - - -class ThreadingExecutor(Executor): - def __init__(self): - self._threads = [] - - def submit(self, fn, *args, **kwargs): - future = Future() - def run(): - try: - future.set_result(fn(*args, **kwargs)) - except Exception as e: - future.set_exception(e) - thread = threading.Thread(target=run) - thread.start() - self._threads.append(thread) - return future - - def map(self, func, iterables, timeout=None): - # TODO(benh): Implement! - raise NotImplementedError() - - def shutdown(self, wait=True): - if wait: - for thread in self._threads: - thread.join() - self._threads = [] http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/src/cli/python/mesos/http.py ---------------------------------------------------------------------- diff --git a/src/cli/python/mesos/http.py b/src/cli/python/mesos/http.py deleted file mode 100644 index 0e19aa8..0000000 --- a/src/cli/python/mesos/http.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Helper for doing an HTTP GET given a PID, a path, and a query dict. -# For example: -# -# get('[email protected]:123', -# '/endpoint', -# {'first': 'ben', -# 'last': 'hindman'}) -# -# Would yield: 1.2.3.4:123/endpoint?first='ben'&last='hindman' -# -# Note that you can also pass an IP:port (or hostname:port) for 'pid' -# (i.e., you can omit the ID component of the PID, e.g., 'foo@'). -def get(pid, path, query=None): - import urllib2 - - from contextlib import closing - - url = 'http://' + pid[(pid.find('@') + 1):] + path - - if query is not None and len(query) > 0: - url += '?' + '&'.join( - ['%s=%s' % (urllib2.quote(str(key)), urllib2.quote(str(value))) - for (key, value) in query.items()]) - - with closing(urllib2.urlopen(url)) as file: - return file.read() http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/src/python/cli/setup.py.in ---------------------------------------------------------------------- diff --git a/src/python/cli/setup.py.in b/src/python/cli/setup.py.in new file mode 100644 index 0000000..0259bc6 --- /dev/null +++ b/src/python/cli/setup.py.in @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +config = { + 'name': 'mesos.cli', + 'version': '@PACKAGE_VERSION@', + 'description': 'Mesos command line utilities', + 'author': 'Apache Mesos', + 'author_email': '[email protected]', + 'url': 'http://pypi.python.org/pypi/mesos.cli', + 'namespace_packages': [ 'mesos' ], + 'packages': [ 'mesos' ], + 'package_dir': { '': 'src' }, + 'install_requires': [ ], + 'license': 'Apache 2.0', + 'keywords': 'mesos', + 'classifiers': [ ] +} + +from setuptools import setup + +setup(**config) http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/src/python/cli/src/mesos/__init__.py ---------------------------------------------------------------------- diff --git a/src/python/cli/src/mesos/__init__.py b/src/python/cli/src/mesos/__init__.py new file mode 100644 index 0000000..3fcba01 --- /dev/null +++ b/src/python/cli/src/mesos/__init__.py @@ -0,0 +1,10 @@ +# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages +# Because python does not normally allow the contents of a package to be +# retrieved from more than one location, this code snippet ensures that the +# namespace package machinery is operating and that the current package is +# registered as a namespace package. +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/src/python/cli/src/mesos/cli.py ---------------------------------------------------------------------- diff --git a/src/python/cli/src/mesos/cli.py b/src/python/cli/src/mesos/cli.py new file mode 100644 index 0000000..857059e --- /dev/null +++ b/src/python/cli/src/mesos/cli.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Helper for printing out a message and then the "usage" then exiting. +def usage(message, parser): + import sys + sys.stderr.write(message + '\n') + parser.print_help() + sys.exit(-1) + + +# Helper for printing out a message and then exiting. +def fatal(message): + import sys + sys.stderr.write(message + '\n') + sys.exit(-1) + + +# Helper that uses 'mesos-resolve' to resolve a master IP:port from +# one of: +# zk://host1:port1,host2:port2,.../path +# zk://username:password@host1:port1,host2:port2,.../path +# file://path/to/file (where file contains one of the above) +def resolve(master): + import subprocess + + process = subprocess.Popen( + ['mesos-resolve', master], + stdin=None, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=False) + + status = process.wait() + if status != 0: + raise Exception('Failed to execute \'mesos-resolve %s\':\n%s' + % (master, process.stderr.read())) + + result = process.stdout.read() + process.stdout.close() + process.stderr.close() + return result http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/src/python/cli/src/mesos/futures.py ---------------------------------------------------------------------- diff --git a/src/python/cli/src/mesos/futures.py b/src/python/cli/src/mesos/futures.py new file mode 100644 index 0000000..da2f4ce --- /dev/null +++ b/src/python/cli/src/mesos/futures.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +try: + from concurrent.futures import * +except ImportError: + import threading + import time + + from Queue import Queue + from Queue import Empty + + class TimeoutError(Exception): + """The operation timed out""" + + class Future(object): + def __init__(self): + self._lock = threading.RLock() + self._condition = threading.Condition(self._lock) + self._done = False + self._result = None + self._exception = None + self._exc_info = None + self._callbacks = [] + + def cancel(self): + # These futures are possibly backed by threads which can + # not (easily or portably) be interrupted so instead we + # simply don't let people cancel. + + # TODO(benh): If more use cases come about that want to + # differentiate a started versus a + raise False + + def cancelled(self): + return False + + def running(self): + return not self.done() + + def done(self): + with self._lock: + return self._done + + def result(self, timeout=None): + with self._lock: + self._await(timeout) + if self._exception: + raise self._exception + return self._result + + def exception(self, timeout=None): + with self._lock: + self._await(timeout) + if self._exception: + return self._exception + return None + + def add_done_callback(self, fn): + run = False + with self._lock: + if self._done: + run = True + else: + self._callbacks.append(fn) + if run: + try: + fn(self) + except: + # TODO(benh): Log if Exception, but semantics tell + # us to ignore regardless. + pass + + def set_result(self, result): + with self._lock: + self._result = result + self._finish() + + def set_exception(self, exception): + with self._lock: + self._exception = exception + self._finish() + + def _await(self, timeout): + with self._lock: + if not self._done: + self._condition.wait(timeout) + if not self._done: + raise TimeoutError() + + def _finish(self): + callbacks = None + with self._lock: + self._done = True + callbacks = self._callbacks + self._callbacks = None + for cb in callbacks: + try: + cb(self) + except: + # TODO(benh): Log if Exception, but semantics tell + # us to ignore regardless. + pass + + + class Executor(object): + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.shutdown() + + + def as_completed(futures, timeout=None): + # Record the start time in order to determine the remaining + # timeout as futures are completed. + start = time.time() + + # Use a queue to collect the done futures. + queue = Queue() + + # Define a helper for the future "done callback". + def done(future): + queue.put(future) + + # Add a "done callback" for each future. + for future in futures: + future.add_done_callback(done) + + # Helper to determine the remaining timeout. + def remaining(): + if timeout is None: + return None + end = start + timeout + remaining = end - time.time() + return remaining if remaining >= 0 else 0 + + # Now wait until all the futures have completed or we timeout. + finished = 0 + while finished < len(futures): + try: + yield queue.get(timeout=remaining()) + except Empty: + raise TimeoutError() + else: + finished += 1 + + +class ThreadingExecutor(Executor): + def __init__(self): + self._threads = [] + + def submit(self, fn, *args, **kwargs): + future = Future() + def run(): + try: + future.set_result(fn(*args, **kwargs)) + except Exception as e: + future.set_exception(e) + thread = threading.Thread(target=run) + thread.start() + self._threads.append(thread) + return future + + def map(self, func, iterables, timeout=None): + # TODO(benh): Implement! + raise NotImplementedError() + + def shutdown(self, wait=True): + if wait: + for thread in self._threads: + thread.join() + self._threads = [] http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/src/python/cli/src/mesos/http.py ---------------------------------------------------------------------- diff --git a/src/python/cli/src/mesos/http.py b/src/python/cli/src/mesos/http.py new file mode 100644 index 0000000..0e19aa8 --- /dev/null +++ b/src/python/cli/src/mesos/http.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Helper for doing an HTTP GET given a PID, a path, and a query dict. +# For example: +# +# get('[email protected]:123', +# '/endpoint', +# {'first': 'ben', +# 'last': 'hindman'}) +# +# Would yield: 1.2.3.4:123/endpoint?first='ben'&last='hindman' +# +# Note that you can also pass an IP:port (or hostname:port) for 'pid' +# (i.e., you can omit the ID component of the PID, e.g., 'foo@'). +def get(pid, path, query=None): + import urllib2 + + from contextlib import closing + + url = 'http://' + pid[(pid.find('@') + 1):] + path + + if query is not None and len(query) > 0: + url += '?' + '&'.join( + ['%s=%s' % (urllib2.quote(str(key)), urllib2.quote(str(value))) + for (key, value) in query.items()]) + + with closing(urllib2.urlopen(url)) as file: + return file.read() http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/src/python/interface/setup.py.in ---------------------------------------------------------------------- diff --git a/src/python/interface/setup.py.in b/src/python/interface/setup.py.in index 880e2a6..d739967 100644 --- a/src/python/interface/setup.py.in +++ b/src/python/interface/setup.py.in @@ -1,3 +1,5 @@ +#!/usr/bin/env python + # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/src/python/interface/src/mesos/__init__.py ---------------------------------------------------------------------- diff --git a/src/python/interface/src/mesos/__init__.py b/src/python/interface/src/mesos/__init__.py index f48ad10..3fcba01 100644 --- a/src/python/interface/src/mesos/__init__.py +++ b/src/python/interface/src/mesos/__init__.py @@ -1,4 +1,8 @@ # See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages +# Because python does not normally allow the contents of a package to be +# retrieved from more than one location, this code snippet ensures that the +# namespace package machinery is operating and that the current package is +# registered as a namespace package. try: __import__('pkg_resources').declare_namespace(__name__) except ImportError: http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/src/python/native/setup.py.in ---------------------------------------------------------------------- diff --git a/src/python/native/setup.py.in b/src/python/native/setup.py.in index 9fc9ad2..49ed612 100644 --- a/src/python/native/setup.py.in +++ b/src/python/native/setup.py.in @@ -1,3 +1,5 @@ +#!/usr/bin/env python + # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/src/python/native/src/mesos/__init__.py ---------------------------------------------------------------------- diff --git a/src/python/native/src/mesos/__init__.py b/src/python/native/src/mesos/__init__.py index f48ad10..3fcba01 100644 --- a/src/python/native/src/mesos/__init__.py +++ b/src/python/native/src/mesos/__init__.py @@ -1,4 +1,8 @@ # See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages +# Because python does not normally allow the contents of a package to be +# retrieved from more than one location, this code snippet ensures that the +# namespace package machinery is operating and that the current package is +# registered as a namespace package. try: __import__('pkg_resources').declare_namespace(__name__) except ImportError: http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/src/python/protocol/setup.py.in ---------------------------------------------------------------------- diff --git a/src/python/protocol/setup.py.in b/src/python/protocol/setup.py.in index 72cb770..4c50fbb 100644 --- a/src/python/protocol/setup.py.in +++ b/src/python/protocol/setup.py.in @@ -1,3 +1,5 @@ +#!/usr/bin/env python + # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/src/python/protocol/src/mesos/__init__.py ---------------------------------------------------------------------- diff --git a/src/python/protocol/src/mesos/__init__.py b/src/python/protocol/src/mesos/__init__.py index f48ad10..3fcba01 100644 --- a/src/python/protocol/src/mesos/__init__.py +++ b/src/python/protocol/src/mesos/__init__.py @@ -1,4 +1,8 @@ # See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages +# Because python does not normally allow the contents of a package to be +# retrieved from more than one location, this code snippet ensures that the +# namespace package machinery is operating and that the current package is +# registered as a namespace package. try: __import__('pkg_resources').declare_namespace(__name__) except ImportError: http://git-wip-us.apache.org/repos/asf/mesos/blob/52b9c0be/src/python/setup.py.in ---------------------------------------------------------------------- diff --git a/src/python/setup.py.in b/src/python/setup.py.in index 8ffde68..7370669 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -1,3 +1,5 @@ +#!/usr/bin/env python + # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information
