Skip to content

Commit

Permalink
fix conditional requests_credssp import (#85)
Browse files Browse the repository at this point in the history
  • Loading branch information
graingert authored Aug 7, 2020
1 parent baf61c9 commit 9e8a41a
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 35 deletions.
26 changes: 24 additions & 2 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,22 @@ stages:
matrix:
Python27:
python.version: 2.7
credssp: "requests-credssp"
Python35:
python.version: 3.5
credssp: "requests-credssp"
Python36:
python.version: 3.6
credssp: "requests-credssp"
Python37:
python.version: 3.7
credssp: "requests-credssp"
Python38:
python.version: 3.8
credssp: "requests-credssp"
Python38-nocredssp:
python.version: 3.8
credssp: ""

steps:
- task: UsePythonVersion@0
Expand All @@ -51,7 +59,7 @@ stages:
python -m pip install --upgrade pip setuptools wheel coverage -c tests/constraints.txt
echo "Installing test requirements"
python -m pip install -r requirements-test.txt -c tests/constraints.txt
python -m pip install $(credssp) -r requirements-test.txt -c tests/constraints.txt
echo "Installing package"
python -m pip install . -c tests/constraints.txt
Expand Down Expand Up @@ -91,33 +99,47 @@ stages:
Python27-x86:
python.version: 2.7
python.arch: x86
credssp: "requests-credssp"
Python27-x64:
python.version: 2.7
python.arch: x64
credssp: "requests-credssp"
Python35-x86:
python.version: 3.5
python.arch: x86
credssp: "requests-credssp"
Python35-x64:
python.version: 3.5
python.arch: x64
credssp: "requests-credssp"
Python36-x86:
python.version: 3.6
python.arch: x86
credssp: "requests-credssp"
Python36-x64:
python.version: 3.6
python.arch: x64
credssp: "requests-credssp"
Python37-x86:
python.version: 3.7
python.arch: x86
credssp: "requests-credssp"
Python37-x64:
python.version: 3.7
python.arch: x64
credssp: "requests-credssp"
Python38-x86:
python.version: 3.8
python.arch: x86
credssp: "requests-credssp"
Python38-x64:
python.version: 3.8
python.arch: x64
credssp: "requests-credssp"
Python38-x64-nocredssp:
python.version: 3.8
python.arch: x64
credssp: ""

steps:
- task: UsePythonVersion@0
Expand All @@ -130,7 +152,7 @@ stages:
python -m pip install --upgrade pip setuptools wheel coverage -c tests/constraints.txt
echo "Installing test requirements"
python -m pip install -r requirements-test.txt -c tests/constraints.txt
python -m pip install $(credssp) -r requirements-test.txt -c tests/constraints.txt
echo "Installing package"
python -m pip install . -c tests/constraints.txt
Expand Down
16 changes: 8 additions & 8 deletions pypsrp/wsman.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@
from pypsrp.negotiate import HTTPNegotiateAuth
from pypsrp._utils import to_string, to_unicode, get_hostname

HAS_CREDSSP = True
CREDSSP_IMP_ERR = None
try:
from requests_credssp import HttpCredSSPAuth
except ImportError as err: # pragma: no cover
HAS_CREDSSP = False
CREDSSP_IMP_ERR = err
_requests_credssp_import_error = (
"Cannot use CredSSP auth as requests-credssp is not installed: %s"
% err
)

class HttpCredSSPAuth(object):
def __init__(self, *args, **kwargs):
raise ImportError(_requests_credssp_import_error)

if sys.version_info[0] == 2 and sys.version_info[1] < 7: # pragma: no cover
# ElementTree in Python 2.6 does not support namespaces so we need to use
Expand Down Expand Up @@ -882,10 +886,6 @@ def _build_auth_certificate(self, session):
"https/mutual"

def _build_auth_credssp(self, session):
if not HAS_CREDSSP:
raise ImportError("Cannot use CredSSP auth as requests-credssp is "
"not installed: %s" % str(CREDSSP_IMP_ERR))

if self.username is None:
raise ValueError("For credssp auth, the username must be "
"specified")
Expand Down
1 change: 0 additions & 1 deletion requirements-test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ pytest
pytest-cov
pytest-mock
pyyaml
requests-credssp >= 1.0.0
xmldiff
1 change: 1 addition & 0 deletions tests/constraints.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# Other constraints
pytest >= 3.6 ; python_version > "2.7" # Make sure other Python versions use a newer version of pytest
requests-credssp >= 1.0.0
43 changes: 21 additions & 22 deletions tests/test_wsman.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
except ImportError:
from mock import MagicMock

try:
import requests_credssp
except ImportError:
requests_credssp = None

if sys.version_info[0] == 2 and sys.version_info[1] < 7: # pragma: no cover
# ElementTree in Python 2.6 does not support namespaces so we need to use
# lxml instead for this version
Expand All @@ -27,16 +32,6 @@
import xml.etree.ElementTree as ET


@pytest.fixture('function')
def reset_imports():
# ensure the changes to these globals aren't persisted after each test
orig_has_credssp = pypsrp_wsman.HAS_CREDSSP
orig_credssp_imp_err = pypsrp_wsman.CREDSSP_IMP_ERR
yield None
pypsrp_wsman.HAS_CREDSSP = orig_has_credssp
pypsrp_wsman.CREDSSP_IMP_ERR = orig_credssp_imp_err


class _TransportTest(object):

def __init__(self, expected_action=None):
Expand Down Expand Up @@ -684,6 +679,7 @@ def test_set_multiple_options(self):
assert str(selector_set) == "{'key1': 'value1', 'key2': 'value2'}"



class TestTransportHTTP(object):

def test_not_supported_auth(self):
Expand Down Expand Up @@ -773,26 +769,29 @@ def test_build_certificate(self):
"http://schemas.dmtf.org/wbem/wsman/1/wsman/secprofile/" \
"https/mutual"

def test_build_credssp_not_imported(self, reset_imports):
pypsrp_wsman.HAS_CREDSSP = False
pypsrp_wsman.CREDSSP_IMP_ERR = "import failed"
transport = _TransportHTTP("")
with pytest.raises(ImportError) as err:
@pytest.mark.skipif(
requests_credssp,
reason="only raises if requests-credssp is not installed",
)
def test_build_credssp_not_imported(self):
transport = _TransportHTTP("", username="user", password="password")
with pytest.raises(
ImportError,
match=(
r"Cannot use CredSSP auth as requests-credssp is not "
r"installed: No module named '?requests_credssp'?"
),
):
transport._build_auth_credssp(None)
assert str(err.value) == \
"Cannot use CredSSP auth as requests-credssp is not " \
"installed: import failed"

def test_build_credssp_no_username(self, reset_imports):
pypsrp_wsman.HAS_CREDSSP = True
def test_build_credssp_no_username(self):
transport = _TransportHTTP("")
with pytest.raises(ValueError) as err:
transport._build_auth_credssp(None)
assert str(err.value) == \
"For credssp auth, the username must be specified"

def test_build_credssp_no_password(self, reset_imports):
pypsrp_wsman.HAS_CREDSSP = True
def test_build_credssp_no_password(self):
transport = _TransportHTTP("", username="user")
with pytest.raises(ValueError) as err:
transport._build_auth_credssp(None)
Expand Down
5 changes: 3 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
[tox]
envlist = lint,py27,py35,py36,py37,py38
envlist = lint,py27,py35,py36,py37,py38-{credssp,}
skip_missing_interpreters = true

[testenv]
deps =
-r{toxinidir}/requirements-test.txt
-c{toxinidir}/tests/constraints.txt
credssp: requests-credssp >= 1.0.0
commands =
py.test -v --cov pypspnego --cov-report term-missing

Expand All @@ -14,4 +15,4 @@ passenv =

[testenv:lint]
commands =
pycodestyle pypsrp --verbose --show-source --statistics
pycodestyle pypsrp --verbose --show-source --statistics

0 comments on commit 9e8a41a

Please sign in to comment.