Commit 656a5721 authored by Jérome Perrin's avatar Jérome Perrin

WIP type defintions

parent 34d7fb60
[mypy]
ignore_missing_imports = True
[mypy-slapos]
ignore_missing_imports = True
[mypy-slapos.slap]
ignore_missing_imports = True
[mypy-slapos.slap.grid]
ignore_missing_imports = True
# interfaces cause error: Method must have at least one argument
[mypy-slapos.slap.interface]
ignore_errors = True
[mypy-slapos.slap.interface.slap]
ignore_errors = True
...@@ -75,7 +75,8 @@ setup(name=name, ...@@ -75,7 +75,8 @@ setup(name=name,
'cachecontrol', 'cachecontrol',
'lockfile', 'lockfile',
'uritemplate', # used by hateoas navigator 'uritemplate', # used by hateoas navigator
'subprocess32; python_version<"3"' 'subprocess32; python_version<"3"',
'typing; python_version<"3"',
] + additional_install_requires, ] + additional_install_requires,
extras_require=extras_require, extras_require=extras_require,
tests_require=extras_require['test'], tests_require=extras_require['test'],
......
...@@ -3,4 +3,4 @@ try: ...@@ -3,4 +3,4 @@ try:
__import__('pkg_resources').declare_namespace(__name__) __import__('pkg_resources').declare_namespace(__name__)
except ImportError: except ImportError:
from pkgutil import extend_path from pkgutil import extend_path
__path__ = extend_path(__path__, __name__) __path__ = extend_path(__path__, __name__) # type: ignore
...@@ -44,7 +44,7 @@ from slapos.proxy import ProxyConfig ...@@ -44,7 +44,7 @@ from slapos.proxy import ProxyConfig
from slapos.proxy.db_version import DB_VERSION from slapos.proxy.db_version import DB_VERSION
from slapos.util import sqlite_connect, str2bytes from slapos.util import sqlite_connect, str2bytes
if bytes is str: if sys.version_info[0] == 3:
from io import BytesIO from io import BytesIO
class StringIO(BytesIO): class StringIO(BytesIO):
# Something between strict io.BytesIO and laxist/slow StringIO.StringIO # Something between strict io.BytesIO and laxist/slow StringIO.StringIO
......
from __future__ import print_function from __future__ import print_function
from multiprocessing import Process, active_children, cpu_count, Pipe from multiprocessing import Process, active_children, cpu_count, Pipe
try: from typing import TYPE_CHECKING
if TYPE_CHECKING:
import subprocess
else:
try:
import subprocess32 as subprocess import subprocess32 as subprocess
except ImportError: except ImportError:
import subprocess import subprocess
import os import os
import signal import signal
......
...@@ -38,7 +38,8 @@ import subprocess ...@@ -38,7 +38,8 @@ import subprocess
import tarfile import tarfile
import tempfile import tempfile
import time import time
from six.moves import xmlrpc_client as xmlrpclib, range from six.moves import xmlrpc_client as xmlrpclib # type: ignore
from six.moves import range
from six.moves.configparser import ConfigParser from six.moves.configparser import ConfigParser
from supervisor import xmlrpc from supervisor import xmlrpc
......
...@@ -49,6 +49,10 @@ if sys.version_info < (2, 6): ...@@ -49,6 +49,10 @@ if sys.version_info < (2, 6):
warnings.warn('Used python version (%s) is old and has problems with' warnings.warn('Used python version (%s) is old and has problems with'
' IPv6 connections' % sys.version.split('\n')[0]) ' IPv6 connections' % sys.version.split('\n')[0])
from typing import List, Tuple, Sequence, TYPE_CHECKING
if TYPE_CHECKING:
from ..slap.slap import ComputerPartition
from lxml import etree from lxml import etree
from slapos import manager as slapmanager from slapos import manager as slapmanager
...@@ -537,6 +541,7 @@ stderr_logfile_backups=1 ...@@ -537,6 +541,7 @@ stderr_logfile_backups=1
launchSupervisord(instance_root=self.instance_root, logger=self.logger) launchSupervisord(instance_root=self.instance_root, logger=self.logger)
def getComputerPartitionList(self): def getComputerPartitionList(self):
# type: () -> Sequence[ComputerPartition]
try: try:
return self.computer.getComputerPartitionList() return self.computer.getComputerPartitionList()
except socket.error as exc: except socket.error as exc:
...@@ -789,7 +794,7 @@ stderr_logfile_backups=1 ...@@ -789,7 +794,7 @@ stderr_logfile_backups=1
reload_process = FPopen(reload_cmd, universal_newlines=True) reload_process = FPopen(reload_cmd, universal_newlines=True)
stdout, stderr = reload_process.communicate() stdout, stderr = reload_process.communicate()
if reload_process.returncode != 0: if reload_process.returncode != 0:
raise Exception("Failed to load firewalld rules with command %s.\n%" % ( raise Exception("Failed to load firewalld rules with command %s.\n%s" % (
stderr, reload_cmd)) stderr, reload_cmd))
with open(firewall_rules_path, 'w') as frules: with open(firewall_rules_path, 'w') as frules:
...@@ -1254,6 +1259,7 @@ stderr_logfile_backups=1 ...@@ -1254,6 +1259,7 @@ stderr_logfile_backups=1
f.write(str(timestamp)) f.write(str(timestamp))
def FilterComputerPartitionList(self, computer_partition_list): def FilterComputerPartitionList(self, computer_partition_list):
# type: (Sequence[ComputerPartition]) -> List[ComputerPartition]
""" """
Try to filter valid partitions to be processed from free partitions. Try to filter valid partitions to be processed from free partitions.
""" """
...@@ -1392,12 +1398,12 @@ stderr_logfile_backups=1 ...@@ -1392,12 +1398,12 @@ stderr_logfile_backups=1
self.logger.info('=' * 80) self.logger.info('=' * 80)
if process_error_partition_list: if process_error_partition_list:
self.logger.info('Error while processing the following partitions:') self.logger.info('Error while processing the following partitions:')
for partition, exc in process_error_partition_list: for partition, error in process_error_partition_list:
self.logger.info(' %s[%s]: %s', partition.getId(), getPartitionType(partition), exc) self.logger.info(' %s[%s]: %s', partition.getId(), getPartitionType(partition), error)
if promise_error_partition_list: if promise_error_partition_list:
self.logger.info('Error with promises for the following partitions:') self.logger.info('Error with promises for the following partitions:')
for partition, exc in promise_error_partition_list: for partition, error in promise_error_partition_list:
self.logger.info(' %s[%s]: %s', partition.getId(), getPartitionType(partition), exc) self.logger.info(' %s[%s]: %s', partition.getId(), getPartitionType(partition), error)
# Return success value # Return success value
if not clean_run: if not clean_run:
...@@ -1420,7 +1426,7 @@ stderr_logfile_backups=1 ...@@ -1420,7 +1426,7 @@ stderr_logfile_backups=1
computer_partition_list = self.FilterComputerPartitionList( computer_partition_list = self.FilterComputerPartitionList(
self.getComputerPartitionList()) self.getComputerPartitionList())
promise_error_partition_list = [] promise_error_partition_list = [] # type: List[Tuple[ComputerPartition, Union[PromiseError, Exception]]]
for computer_partition in computer_partition_list: for computer_partition in computer_partition_list:
try: try:
# Process the partition itself # Process the partition itself
...@@ -1444,8 +1450,8 @@ stderr_logfile_backups=1 ...@@ -1444,8 +1450,8 @@ stderr_logfile_backups=1
if promise_error_partition_list: if promise_error_partition_list:
self.logger.info('Finished computer partitions.') self.logger.info('Finished computer partitions.')
for partition, exc in promise_error_partition_list: for partition, error in promise_error_partition_list:
self.logger.info(' %s[%s]: %s', partition.getId(), getPartitionType(partition), exc) self.logger.info(' %s[%s]: %s', partition.getId(), getPartitionType(partition), error)
# Return success value # Return success value
if not clean_run_promise: if not clean_run_promise:
......
...@@ -35,7 +35,7 @@ import subprocess ...@@ -35,7 +35,7 @@ import subprocess
import stat import stat
import sys import sys
import time import time
from six.moves import xmlrpc_client as xmlrpclib from six.moves import xmlrpc_client as xmlrpclib # type: ignore
import contextlib import contextlib
from slapos.grid.utils import (createPrivateDirectory, SlapPopen, updateFile) from slapos.grid.utils import (createPrivateDirectory, SlapPopen, updateFile)
......
...@@ -53,8 +53,11 @@ EMPTY_DICT_XML = dumps({}) ...@@ -53,8 +53,11 @@ EMPTY_DICT_XML = dumps({})
class UnauthorizedError(Exception): class UnauthorizedError(Exception):
pass pass
from typing import Dict, Union, no_type_check
@no_type_check
def partitiondict2partition(partition): def partitiondict2partition(partition):
# type: (Dict[str, str]) -> ComputerPartition
slap_partition = ComputerPartition(partition['computer_reference'], slap_partition = ComputerPartition(partition['computer_reference'],
partition['reference']) partition['reference'])
slap_partition._software_release_document = None slap_partition._software_release_document = None
...@@ -365,6 +368,7 @@ def supplySupply(): ...@@ -365,6 +368,7 @@ def supplySupply():
@app.route('/requestComputerPartition', methods=['POST']) @app.route('/requestComputerPartition', methods=['POST'])
def requestComputerPartition(): def requestComputerPartition():
# type: () -> str
parsed_request_dict = parseRequestComputerPartitionForm(request.form) parsed_request_dict = parseRequestComputerPartitionForm(request.form)
# Is it a slave instance? # Is it a slave instance?
slave = loads(request.form.get('shared_xml', EMPTY_DICT_XML).encode('utf-8')) slave = loads(request.form.get('shared_xml', EMPTY_DICT_XML).encode('utf-8'))
...@@ -457,6 +461,7 @@ def requestComputerPartition(): ...@@ -457,6 +461,7 @@ def requestComputerPartition():
return dumps(software_instance) return dumps(software_instance)
def parseRequestComputerPartitionForm(form): def parseRequestComputerPartitionForm(form):
# type: (Dict) -> Dict
""" """
Parse without intelligence a form from a request(), return it. Parse without intelligence a form from a request(), return it.
""" """
...@@ -469,7 +474,7 @@ def parseRequestComputerPartitionForm(form): ...@@ -469,7 +474,7 @@ def parseRequestComputerPartitionForm(form):
'filter_kw': loads(form.get('filter_xml', EMPTY_DICT_XML).encode('utf-8')), 'filter_kw': loads(form.get('filter_xml', EMPTY_DICT_XML).encode('utf-8')),
# Note: currently ignored for slave instance (slave instances # Note: currently ignored for slave instance (slave instances
# are always started). # are always started).
'requested_state': loads(form.get('state').encode('utf-8')), 'requested_state': loads(form['state'].encode('utf-8')),
} }
return parsed_dict return parsed_dict
...@@ -543,10 +548,11 @@ def isRequestToBeForwardedToExternalMaster(parsed_request_dict): ...@@ -543,10 +548,11 @@ def isRequestToBeForwardedToExternalMaster(parsed_request_dict):
return None return None
def forwardRequestToExternalMaster(master_url, request_form): def forwardRequestToExternalMaster(master_url, request_form):
# type: (str, Dict) -> str
""" """
Forward instance request to external SlapOS Master. Forward instance request to external SlapOS Master.
""" """
master_entry = app.config.get('multimaster').get(master_url, {}) master_entry = app.config['multimaster'].get(master_url, {})
key_file = master_entry.get('key') key_file = master_entry.get('key')
cert_file = master_entry.get('cert') cert_file = master_entry.get('cert')
if master_url.startswith('https') and (not key_file or not cert_file): if master_url.startswith('https') and (not key_file or not cert_file):
...@@ -568,7 +574,7 @@ def forwardRequestToExternalMaster(master_url, request_form): ...@@ -568,7 +574,7 @@ def forwardRequestToExternalMaster(master_url, request_form):
{'partition_reference':partition_reference, 'master_url': master_url}) {'partition_reference':partition_reference, 'master_url': master_url})
new_request_form = request_form.copy() new_request_form = request_form.copy()
filter_kw = loads(new_request_form['filter_xml'].encode('utf-8')) filter_kw = loads(request_form['filter_xml'].encode('utf-8'))
filter_kw['source_instance_id'] = partition_reference filter_kw['source_instance_id'] = partition_reference
new_request_form['filter_xml'] = dumps(filter_kw) new_request_form['filter_xml'] = dumps(filter_kw)
...@@ -576,7 +582,7 @@ def forwardRequestToExternalMaster(master_url, request_form): ...@@ -576,7 +582,7 @@ def forwardRequestToExternalMaster(master_url, request_form):
partition = loads(xml) partition = loads(xml)
# XXX move to other end # XXX move to other end
partition._master_url = master_url partition._master_url = master_url # type: ignore
return dumps(partition) return dumps(partition)
......
This diff is collapsed.
...@@ -38,9 +38,15 @@ import shutil ...@@ -38,9 +38,15 @@ import shutil
from six.moves import urllib from six.moves import urllib
from six.moves import http_client from six.moves import http_client
try: from typing import TYPE_CHECKING, Optional, Iterable, Dict
if TYPE_CHECKING:
import subprocess
from ..slap.slap import Computer, ComputerPartition, SoftwareState, InstanceState, PartitionParameters, FilterParameters
else:
try:
import subprocess32 as subprocess import subprocess32 as subprocess
except ImportError: except ImportError:
import subprocess import subprocess
import xml_marshaller import xml_marshaller
...@@ -80,9 +86,11 @@ class ConfigWriter(object): ...@@ -80,9 +86,11 @@ class ConfigWriter(object):
"""Base class for an object writing a config file or wrapper script. """Base class for an object writing a config file or wrapper script.
""" """
def __init__(self, standalone_slapos): def __init__(self, standalone_slapos):
# type: (StandaloneSlapOS) -> None
self._standalone_slapos = standalone_slapos self._standalone_slapos = standalone_slapos
def writeConfig(self, path): def writeConfig(self, path):
# type: (str) -> None
NotImplemented NotImplemented
...@@ -90,6 +98,7 @@ class SupervisorConfigWriter(ConfigWriter): ...@@ -90,6 +98,7 @@ class SupervisorConfigWriter(ConfigWriter):
"""Write supervisor configuration at etc/supervisor.conf """Write supervisor configuration at etc/supervisor.conf
""" """
def _getProgramConfig(self, program_name, command, stdout_logfile): def _getProgramConfig(self, program_name, command, stdout_logfile):
# type: (str, str, str) -> str
"""Format a supervisor program block. """Format a supervisor program block.
""" """
return textwrap.dedent( return textwrap.dedent(
...@@ -108,6 +117,7 @@ class SupervisorConfigWriter(ConfigWriter): ...@@ -108,6 +117,7 @@ class SupervisorConfigWriter(ConfigWriter):
""").format(**locals()) """).format(**locals())
def _getSupervisorConfigParts(self): def _getSupervisorConfigParts(self):
# type: () -> Iterable[str]
"""Iterator on parts of formatted config. """Iterator on parts of formatted config.
""" """
standalone_slapos = self._standalone_slapos standalone_slapos = self._standalone_slapos
...@@ -143,6 +153,7 @@ class SupervisorConfigWriter(ConfigWriter): ...@@ -143,6 +153,7 @@ class SupervisorConfigWriter(ConfigWriter):
'stdout_logfile', 'AUTO').format(self=standalone_slapos)) 'stdout_logfile', 'AUTO').format(self=standalone_slapos))
def writeConfig(self, path): def writeConfig(self, path):
# type: (str) -> None
with open(path, 'w') as f: with open(path, 'w') as f:
for part in self._getSupervisorConfigParts(): for part in self._getSupervisorConfigParts():
f.write(part) f.write(part)
...@@ -151,8 +162,10 @@ class SupervisorConfigWriter(ConfigWriter): ...@@ -151,8 +162,10 @@ class SupervisorConfigWriter(ConfigWriter):
class SlapOSConfigWriter(ConfigWriter): class SlapOSConfigWriter(ConfigWriter):
"""Write slapos configuration at etc/slapos.cfg """Write slapos configuration at etc/slapos.cfg
""" """
def writeConfig(self, path): def writeConfig(self, path):
standalone_slapos = self._standalone_slapos # type: StandaloneSlapOS # type: (str) -> None
standalone_slapos = self._standalone_slapos
read_only_shared_part_list = '\n '.join( # pylint: disable=unused-variable; used in format() read_only_shared_part_list = '\n '.join( # pylint: disable=unused-variable; used in format()
standalone_slapos._shared_part_list) standalone_slapos._shared_part_list)
with open(path, 'w') as f: with open(path, 'w') as f:
...@@ -183,6 +196,7 @@ class SlapOSCommandWriter(ConfigWriter): ...@@ -183,6 +196,7 @@ class SlapOSCommandWriter(ConfigWriter):
"""Write a bin/slapos wrapper. """Write a bin/slapos wrapper.
""" """
def writeConfig(self, path): def writeConfig(self, path):
# type: (str) -> None
with open(path, 'w') as f: with open(path, 'w') as f:
f.write( f.write(
textwrap.dedent( textwrap.dedent(
...@@ -215,7 +229,9 @@ class StandaloneSlapOS(object): ...@@ -215,7 +229,9 @@ class StandaloneSlapOS(object):
shared_part_list=(), shared_part_list=(),
software_root=None, software_root=None,
instance_root=None, instance_root=None,
shared_part_root=None): shared_part_root=None,
):
# type: (str, str, int, str, Iterable[str], Optional[str], Optional[str], Optional[str]) -> None
"""Constructor, creates a standalone slapos in `base_directory`. """Constructor, creates a standalone slapos in `base_directory`.
Arguments: Arguments:
...@@ -273,6 +289,7 @@ class StandaloneSlapOS(object): ...@@ -273,6 +289,7 @@ class StandaloneSlapOS(object):
self._initBaseDirectory(software_root, instance_root, shared_part_root) self._initBaseDirectory(software_root, instance_root, shared_part_root)
def _initBaseDirectory(self, software_root, instance_root, shared_part_root): def _initBaseDirectory(self, software_root, instance_root, shared_part_root):
# type: (Optional[str], Optional[str], Optional[str]) -> None
"""Create the directory after checking it's not too deep. """Create the directory after checking it's not too deep.
""" """
base_directory = self._base_directory base_directory = self._base_directory
...@@ -337,6 +354,7 @@ class StandaloneSlapOS(object): ...@@ -337,6 +354,7 @@ class StandaloneSlapOS(object):
@property @property
def computer(self): def computer(self):
# type: () -> Computer
"""Access the computer. """Access the computer.
""" """
return self._slap.registerComputer(self._computer_id) return self._slap.registerComputer(self._computer_id)
...@@ -391,6 +409,7 @@ class StandaloneSlapOS(object): ...@@ -391,6 +409,7 @@ class StandaloneSlapOS(object):
ipv4_address, ipv4_address,
ipv6_address, ipv6_address,
partition_base_name="slappart"): partition_base_name="slappart"):
# type: (int, str, str, str) -> None
"""Creates `partition_count` partitions. """Creates `partition_count` partitions.
All partitions have the same `ipv4_address` and `ipv6_address` and All partitions have the same `ipv4_address` and `ipv6_address` and
...@@ -489,6 +508,7 @@ class StandaloneSlapOS(object): ...@@ -489,6 +508,7 @@ class StandaloneSlapOS(object):
os.unlink(supervisor_conf) os.unlink(supervisor_conf)
def supply(self, software_url, computer_guid=None, state="available"): def supply(self, software_url, computer_guid=None, state="available"):
# type: (str, Optional[str], SoftwareState) -> None
"""Supply a software, see ISupply.supply """Supply a software, see ISupply.supply
Software can only be supplied on this embedded computer. Software can only be supplied on this embedded computer.
...@@ -510,6 +530,7 @@ class StandaloneSlapOS(object): ...@@ -510,6 +530,7 @@ class StandaloneSlapOS(object):
partition_parameter_kw=None, partition_parameter_kw=None,
filter_kw=None, filter_kw=None,
state=None): state=None):
# type: (str, str, Optional[str], bool, Optional[PartitionParameters], Optional[FilterParameters], Optional[InstanceState]) -> ComputerPartition
"""Request an instance, see IRequester.request """Request an instance, see IRequester.request
Instance can only be requested on this embedded computer. Instance can only be requested on this embedded computer.
...@@ -526,6 +547,7 @@ class StandaloneSlapOS(object): ...@@ -526,6 +547,7 @@ class StandaloneSlapOS(object):
state=state) state=state)
def start(self): def start(self):
# type: () -> None
"""Start the system. """Start the system.
If system was stopped, it will start partitions. If system was stopped, it will start partitions.
...@@ -536,6 +558,7 @@ class StandaloneSlapOS(object): ...@@ -536,6 +558,7 @@ class StandaloneSlapOS(object):
self._ensureSlapOSAvailable() self._ensureSlapOSAvailable()
def stop(self): def stop(self):
# type: () -> None
"""Stops all services. """Stops all services.
This methods blocks until services are stopped or a timeout is reached. This methods blocks until services are stopped or a timeout is reached.
...@@ -573,6 +596,7 @@ class StandaloneSlapOS(object): ...@@ -573,6 +596,7 @@ class StandaloneSlapOS(object):
alive + instance_process_alive)) alive + instance_process_alive))
def waitForSoftware(self, max_retry=0, debug=False, error_lines=30): def waitForSoftware(self, max_retry=0, debug=False, error_lines=30):
# type: (int, bool, int) -> None
"""Synchronously install or uninstall all softwares previously supplied/removed. """Synchronously install or uninstall all softwares previously supplied/removed.
This method retries on errors. If after `max_retry` times there's This method retries on errors. If after `max_retry` times there's
...@@ -594,6 +618,7 @@ class StandaloneSlapOS(object): ...@@ -594,6 +618,7 @@ class StandaloneSlapOS(object):
) )
def waitForInstance(self, max_retry=0, debug=False, error_lines=30): def waitForInstance(self, max_retry=0, debug=False, error_lines=30):
# type: (int, bool, int) -> None
"""Instantiate all partitions previously requested for start. """Instantiate all partitions previously requested for start.
This method retries on errors. If after `max_retry` times there's This method retries on errors. If after `max_retry` times there's
...@@ -615,6 +640,7 @@ class StandaloneSlapOS(object): ...@@ -615,6 +640,7 @@ class StandaloneSlapOS(object):
) )
def waitForReport(self, max_retry=0, debug=False, error_lines=30): def waitForReport(self, max_retry=0, debug=False, error_lines=30):
# type: (int, bool, int) -> None
"""Destroy all partitions previously requested for destruction. """Destroy all partitions previously requested for destruction.
This method retries on errors. If after `max_retry` times there's This method retries on errors. If after `max_retry` times there's
...@@ -637,17 +663,19 @@ class StandaloneSlapOS(object): ...@@ -637,17 +663,19 @@ class StandaloneSlapOS(object):
def _runSlapOSCommand( def _runSlapOSCommand(
self, command, max_retry=0, debug=False, error_lines=30): self, command, max_retry=0, debug=False, error_lines=30):
# type: (str, int, bool, int) -> None
if debug: if debug:
prog = self._slapos_commands[command] prog = self._slapos_commands[command]
# used in format(**locals()) below # used in format(**locals()) below
debug_args = prog.get('debug_args', '') # pylint: disable=unused-variable debug_args = prog.get('debug_args', '') # pylint: disable=unused-variable
command = prog['command'].format(**locals()) command = prog['command'].format(**locals())
try: try:
return subprocess.check_call( subprocess.check_call(
command, command,
shell=True, shell=True,
env=self._getSubprocessEnvironment(), env=self._getSubprocessEnvironment(),
) )
return
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
if e.returncode == SLAPGRID_PROMISE_FAIL: if e.returncode == SLAPGRID_PROMISE_FAIL:
self._logger.exception('Promise error when running %s', command) self._logger.exception('Promise error when running %s', command)
...@@ -687,6 +715,7 @@ class StandaloneSlapOS(object): ...@@ -687,6 +715,7 @@ class StandaloneSlapOS(object):
retry += 1 retry += 1
def _ensureSupervisordStarted(self): def _ensureSupervisordStarted(self):
# type: () -> None
if os.path.exists(self._supervisor_pid): if os.path.exists(self._supervisor_pid):
with open(self._supervisor_pid, 'r') as f: with open(self._supervisor_pid, 'r') as f:
try: try:
...@@ -715,6 +744,7 @@ class StandaloneSlapOS(object): ...@@ -715,6 +744,7 @@ class StandaloneSlapOS(object):
self._logger.debug("Started new supervisor: %s", output) self._logger.debug("Started new supervisor: %s", output)
def _isSlapOSAvailable(self): def _isSlapOSAvailable(self):
# type: () -> bool
try: try:
urllib.request.urlopen(self._master_url).close() urllib.request.urlopen(self._master_url).close()
except urllib.error.HTTPError as e: except urllib.error.HTTPError as e:
...@@ -723,6 +753,7 @@ class StandaloneSlapOS(object): ...@@ -723,6 +753,7 @@ class StandaloneSlapOS(object):
return True return True
raise raise
except urllib.error.URLError as e: except urllib.error.URLError as e:
assert isinstance(e.reason, OSError)
if e.reason.errno == errno.ECONNREFUSED: if e.reason.errno == errno.ECONNREFUSED:
return False return False
raise raise
...@@ -735,6 +766,7 @@ class StandaloneSlapOS(object): ...@@ -735,6 +766,7 @@ class StandaloneSlapOS(object):
return True # (if / becomes 200 OK) return True # (if / becomes 200 OK)
def _ensureSlapOSAvailable(self): def _ensureSlapOSAvailable(self):
# type: () -> None
# Wait for proxy to accept connections # Wait for proxy to accept connections
for i in range(2**8): for i in range(2**8):
if self._isSlapOSAvailable(): if self._isSlapOSAvailable():
...@@ -743,6 +775,7 @@ class StandaloneSlapOS(object): ...@@ -743,6 +775,7 @@ class StandaloneSlapOS(object):
raise RuntimeError("SlapOS not started") raise RuntimeError("SlapOS not started")
def _getSubprocessEnvironment(self): def _getSubprocessEnvironment(self):
# type: () -> Optional[Dict[str, str]]
# Running tests with `python setup.py test` sets a PYTHONPATH that # Running tests with `python setup.py test` sets a PYTHONPATH that
# is suitable for current python, but problematic when this process # is suitable for current python, but problematic when this process
# runs another version of python in subprocess. # runs another version of python in subprocess.
...@@ -752,3 +785,4 @@ class StandaloneSlapOS(object): ...@@ -752,3 +785,4 @@ class StandaloneSlapOS(object):
env = os.environ.copy() env = os.environ.copy()
del env['PYTHONPATH'] del env['PYTHONPATH']
return env return env
return None
...@@ -32,10 +32,11 @@ import shutil ...@@ -32,10 +32,11 @@ import shutil
import unittest import unittest
import slapos.client import slapos.client
try: import sys
import mock if sys.version_info[0] == 3:
except ImportError:
from unittest import mock from unittest import mock
else:
import mock
from slapos.cli.prune import do_prune from slapos.cli.prune import do_prune
......
...@@ -34,10 +34,15 @@ import os ...@@ -34,10 +34,15 @@ import os
import logging import logging
import shutil import shutil
import socket import socket
try: from typing import TYPE_CHECKING
if TYPE_CHECKING:
import subprocess
else:
try:
import subprocess32 as subprocess import subprocess32 as subprocess
except ImportError: except ImportError:
import subprocess import subprocess
import sys import sys
import tempfile import tempfile
import time import time
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment