aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--__init__.py0
-rw-r--r--gsxws/__init__.py25
-rw-r--r--gsxws/comms.py4
-rw-r--r--gsxws/comptia.py12
-rw-r--r--gsxws/core.py53
-rw-r--r--gsxws/diagnostics.py2
-rw-r--r--gsxws/escalations.py4
-rw-r--r--gsxws/lookups.py2
-rw-r--r--gsxws/objectify.py8
-rw-r--r--gsxws/orders.py4
-rw-r--r--gsxws/parts.py14
-rw-r--r--gsxws/products.py15
-rw-r--r--gsxws/products.yaml42
-rw-r--r--gsxws/repairs.py6
-rw-r--r--gsxws/returns.py4
-rw-r--r--gsxws/utils.py31
-rw-r--r--requirements.pip1
-rw-r--r--setup.py2
-rw-r--r--tests/test_gsxws.py66
20 files changed, 196 insertions, 105 deletions
diff --git a/.gitignore b/.gitignore
index d2d6f36..1635145 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,3 +33,9 @@ nosetests.xml
.mr.developer.cfg
.project
.pydevproject
+
+.env
+.envrc
+*.sublime-*
+
+
diff --git a/__init__.py b/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/__init__.py
+++ /dev/null
diff --git a/gsxws/__init__.py b/gsxws/__init__.py
index 13a3a5b..bbec77f 100644
--- a/gsxws/__init__.py
+++ b/gsxws/__init__.py
@@ -1,11 +1,14 @@
-from core import *
-from repairs import *
-from products import *
-from returns import *
-from comms import *
-from diagnostics import *
-from parts import *
-from comptia import *
-from escalations import *
-from lookups import *
-from orders import *
+# -*- coding: utf-8 -*-
+
+from .core import *
+from .repairs import *
+from .products import *
+from .returns import *
+from .comms import *
+from .diagnostics import *
+from .parts import *
+from .comptia import *
+from .escalations import *
+from .lookups import *
+from .orders import *
+from . import objectify
diff --git a/gsxws/comms.py b/gsxws/comms.py
index dc37e9b..3ff1ac3 100644
--- a/gsxws/comms.py
+++ b/gsxws/comms.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-from core import GsxObject
+from .core import GsxObject
class Communication(GsxObject):
@@ -49,7 +49,7 @@ def ack(id, status):
if __name__ == '__main__':
import sys
import doctest
- from core import connect
+ from .core import connect
logging.basicConfig(level=logging.DEBUG)
connect(*sys.argv[1:4])
doctest.testmod()
diff --git a/gsxws/comptia.py b/gsxws/comptia.py
index 3cd47d7..dfcd00e 100644
--- a/gsxws/comptia.py
+++ b/gsxws/comptia.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import logging
-from core import GsxObject, GsxCache
+from .core import GsxObject, GsxCache
MODIFIERS = (
("A", "Not Applicable"),
@@ -69,9 +69,9 @@ class CompTIA(GsxObject):
for el in root.findall(".//comptiaGroup"):
group = []
- comp_id = unicode(el[0].text)
+ comp_id = str(el[0].text)
for ci in el.findall("comptiaCodeInfo"):
- group.append((ci[0].text, unicode(ci[1].text)),)
+ group.append((ci[0].text, str(ci[1].text)),)
self._comptia[comp_id] = group
@@ -88,9 +88,9 @@ class CompTIA(GsxObject):
"""
r = dict()
- for g, codes in self._comptia.items():
+ for g, codes in list(self._comptia.items()):
r[g] = list()
- for k, v in codes.items():
+ for k, v in list(codes.items()):
r[g].append((k, v,))
return r[component] if component else r
@@ -104,7 +104,7 @@ def fetch():
if __name__ == '__main__':
import sys
import doctest
- from core import connect
+ from .core import connect
logging.basicConfig(level=logging.DEBUG)
connect(*sys.argv[1:4])
doctest.testmod()
diff --git a/gsxws/core.py b/gsxws/core.py
index 1d3e18b..b9d6f62 100644
--- a/gsxws/core.py
+++ b/gsxws/core.py
@@ -34,12 +34,12 @@ import hashlib
import logging
import requests
import tempfile
-import objectify
import xml.etree.ElementTree as ET
+from . import objectify
from datetime import date, time, datetime, timedelta
-VERSION = "0.92"
+VERSION = "0.93"
GSX_ENV = "ut" # it, ut or pr
GSX_LANG = "en"
@@ -127,7 +127,7 @@ def validate(value, what=None):
"""
result = None
- if not isinstance(value, basestring):
+ if not isinstance(value, str):
raise ValueError('%s is not valid input (%s != string)' % (value, type(value)))
rex = {
@@ -142,7 +142,7 @@ def validate(value, what=None):
'productName': r'^i?Mac',
}
- for k, v in rex.items():
+ for k, v in list(rex.items()):
if re.match(v, value):
result = k
@@ -151,8 +151,8 @@ def validate(value, what=None):
def get_format(locale=GSX_LOCALE):
filepath = os.path.join(os.path.dirname(__file__), 'langs.json')
- df = open(filepath, 'r')
- return json.load(df).get(locale)
+ with open(filepath, 'r') as df:
+ return json.load(df).get(locale)
class GsxError(Exception):
@@ -163,7 +163,7 @@ class GsxError(Exception):
self.codes = []
self.messages = []
- if isinstance(message, basestring):
+ if isinstance(message, str):
self.messages.append(message)
if status == 403:
@@ -189,41 +189,38 @@ class GsxError(Exception):
self.messages.append(el.text)
def __str__(self):
- return repr(self.message)
+ return ' '.join(self.messages)
@property
def code(self):
try:
return self.codes[0]
except IndexError:
- return u'XXX'
-
- @property
- def message(self):
- return unicode(self)
+ return 'XXX'
@property
def errors(self):
- return dict(zip(self.codes, self.messages))
+ return dict(list(zip(self.codes, self.messages)))
def __unicode__(self):
if len(self.messages) < 1:
- return u'Unknown GSX error'
+ return 'Unknown GSX error'
- return u' '.join(self.messages)
+ return ' '.join(self.messages)
class GsxCache(object):
"""The cache creates a separate shelf for each GSX session."""
shelf = None
+ shelf_prefix = 'gsxws'
tmpdir = tempfile.gettempdir()
def __init__(self, key, expires=timedelta(minutes=20)):
self.key = key
self.expires = expires
self.now = datetime.now()
- self.fp = os.path.join(self.tmpdir, "gsxws_%s" % key)
+ self.fp = os.path.join(self.tmpdir, '%s_%s.db' % (self.shelf_prefix, key))
self.shelf = shelve.open(self.fp, protocol=-1)
if not self.shelf.get(key):
@@ -251,6 +248,13 @@ class GsxCache(object):
self.shelf[key] = d
return self
+ @classmethod
+ def nukeall(cls):
+ """Delete all gsxws caches"""
+ import subprocess
+ path = os.path.join(cls.tmpdir, cls.shelf_prefix) + '*.db'
+ subprocess.call('/bin/rm ' + path, shell=True)
+
def nuke(self):
"""Delete this cache."""
os.remove(self.fp)
@@ -281,7 +285,7 @@ class GsxRequest(object):
self.body = ET.SubElement(self.env, "soapenv:Body")
self.xml_response = ''
- for k, v in kwargs.items():
+ for k, v in list(kwargs.items()):
self.obj = v
self._request = k
self.data = v.to_xml(self._request)
@@ -295,7 +299,7 @@ class GsxRequest(object):
self._url = GSX_URL.format(env=GSX_HOSTS[GSX_ENV], region=GSX_REGION)
except KeyError:
raise GsxError('GSX environment (%s) must be one of: %s' % (GSX_ENV,
- ', '.join(GSX_HOSTS.keys())))
+ ', '.join(list(GSX_HOSTS.keys()))))
logging.debug(self._url)
logging.debug(xmldata)
@@ -376,7 +380,7 @@ class GsxRequest(object):
return ET.tostring(self.env)
def __str__(self):
- return unicode(self).encode('utf-8')
+ return str(self).encode('utf-8')
class GsxResponse:
@@ -422,7 +426,7 @@ class GsxObject(object):
if k is not None:
kwargs[k] = a
- for k, v in kwargs.items():
+ for k, v in list(kwargs.items()):
self.__setattr__(k, v)
def __setattr__(self, name, value):
@@ -479,7 +483,7 @@ class GsxObject(object):
<Element 'blaa' at 0x...
"""
root = ET.Element(root)
- for k, v in self._data.items():
+ for k, v in list(self._data.items()):
if isinstance(v, list):
for e in v:
if isinstance(e, GsxObject):
@@ -487,7 +491,7 @@ class GsxObject(object):
i.extend(e.to_xml(k))
else:
el = ET.SubElement(root, k)
- if isinstance(v, basestring):
+ if isinstance(v, str):
el.text = v
if isinstance(v, GsxObject):
el.extend(v.to_xml(k))
@@ -523,7 +527,8 @@ class GsxSession(GsxObject):
self._session_id = ""
md5 = hashlib.md5()
- md5.update(user_id + self.serviceAccountNo + GSX_ENV)
+ s = (user_id + self.serviceAccountNo + GSX_ENV).encode()
+ md5.update(s)
self._cache_key = md5.hexdigest()
self._cache = GsxCache(self._cache_key)
diff --git a/gsxws/diagnostics.py b/gsxws/diagnostics.py
index f1815e7..2ad1e8c 100644
--- a/gsxws/diagnostics.py
+++ b/gsxws/diagnostics.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-from core import GsxObject, GsxError
+from .core import GsxObject, GsxError
class Diagnostics(GsxObject):
diff --git a/gsxws/escalations.py b/gsxws/escalations.py
index 70f7732..6a1ffbb 100644
--- a/gsxws/escalations.py
+++ b/gsxws/escalations.py
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
import os.path
-from core import GsxObject
-from lookups import Lookup
+from .core import GsxObject
+from .lookups import Lookup
STATUS_OPEN = 'O'
STATUS_CLOSED = 'C'
diff --git a/gsxws/lookups.py b/gsxws/lookups.py
index 6a91e90..e71ff40 100644
--- a/gsxws/lookups.py
+++ b/gsxws/lookups.py
@@ -5,7 +5,7 @@ import logging
import tempfile
from datetime import date
-from core import GsxObject, connect
+from .core import GsxObject, connect
class Lookup(GsxObject):
diff --git a/gsxws/objectify.py b/gsxws/objectify.py
index 7803f43..dfcae79 100644
--- a/gsxws/objectify.py
+++ b/gsxws/objectify.py
@@ -112,7 +112,7 @@ class GsxElement(objectify.ObjectifiedElement):
# Work around lxml chomping leading zeros off of IMEI numbers
if name in STRING_TYPES:
- return unicode(result.text or '')
+ return str(result.text or '')
if isinstance(result, objectify.NumberElement):
return result.pyval
@@ -120,7 +120,7 @@ class GsxElement(objectify.ObjectifiedElement):
if isinstance(result, objectify.StringElement):
name = result.tag
result = result.text or ''
- result = unicode(result)
+ result = str(result)
if not result:
return
@@ -157,10 +157,10 @@ def parse(root, response):
lookup = objectify.ObjectifyElementClassLookup(tree_class=GsxElement)
parser.set_element_class_lookup(lookup)
- if isinstance(root, basestring) and os.path.exists(root):
+ if isinstance(root, str) and os.path.exists(root):
root = objectify.parse(root, parser)
else:
- root = objectify.fromstring(root, parser)
+ root = objectify.fromstring(root.encode(), parser)
return root.find('*//%s' % response)
diff --git a/gsxws/orders.py b/gsxws/orders.py
index c06a073..685e038 100644
--- a/gsxws/orders.py
+++ b/gsxws/orders.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-from core import GsxObject
+from .core import GsxObject
class OrderLine(GsxObject):
@@ -63,7 +63,7 @@ if __name__ == '__main__':
import sys
import doctest
import logging
- from core import connect
+ from .core import connect
logging.basicConfig(level=logging.DEBUG)
connect(*sys.argv[1:5])
doctest.testmod()
diff --git a/gsxws/parts.py b/gsxws/parts.py
index 6f9fb02..0f3691b 100644
--- a/gsxws/parts.py
+++ b/gsxws/parts.py
@@ -1,10 +1,8 @@
# -*- coding: utf-8 -*-
-import urllib
-import tempfile
-
-from lookups import Lookup
-from core import GsxObject, GsxError
+from .lookups import Lookup
+from .utils import fetch_url
+from .core import GsxObject, GsxError
REASON_CODES = (
('A', 'Part not needed'),
@@ -35,11 +33,9 @@ class Part(GsxObject):
raise GsxError("Cannot fetch part image without part number")
image = "%s_350_350.gif" % self.partNumber
- url = IMAGE_URL % image
- tmpfile = tempfile.mkstemp(suffix=image)
try:
- return urllib.urlretrieve(url, tmpfile[1])[0]
+ return fetch_url(IMAGE_URL % image)
except Exception as e:
raise GsxError("Failed to fetch part image: %s" % e)
@@ -48,7 +44,7 @@ if __name__ == '__main__':
import sys
import doctest
import logging
- from core import connect
+ from .core import connect
logging.basicConfig(level=logging.DEBUG)
connect(*sys.argv[1:])
doctest.testmod()
diff --git a/gsxws/products.py b/gsxws/products.py
index 2c2745a..a656f98 100644
--- a/gsxws/products.py
+++ b/gsxws/products.py
@@ -4,11 +4,11 @@ https://gsxwsut.apple.com/apidocs/ut/html/WSAPIChangeLog.html?user=asp
"""
import re
-import urllib
-from lookups import Lookup
-from diagnostics import Diagnostics
-from core import GsxObject, GsxError, validate
+from .utils import fetch_url
+from .lookups import Lookup
+from .diagnostics import Diagnostics
+from .core import GsxObject, GsxError, validate
def models():
@@ -19,7 +19,8 @@ def models():
import os
import yaml
filepath = os.path.join(os.path.dirname(__file__), "products.yaml")
- return yaml.load(open(filepath, 'r'))
+ with open(filepath, 'r') as f:
+ return yaml.load(f)
class Product(object):
@@ -151,7 +152,7 @@ class Product(object):
raise GsxError("No URL to fetch product image")
try:
- return urllib.urlretrieve(url)[0]
+ return fetch_url(url)
except Exception as e:
raise GsxError("Failed to fetch product image: %s" % e)
@@ -262,7 +263,7 @@ if __name__ == '__main__':
import sys
import doctest
import logging
- from core import connect
+ from .core import connect
logging.basicConfig(level=logging.DEBUG)
connect(*sys.argv[1:])
doctest.testmod()
diff --git a/gsxws/products.yaml b/gsxws/products.yaml
index 81e937a..e18d063 100644
--- a/gsxws/products.yaml
+++ b/gsxws/products.yaml
@@ -5,6 +5,7 @@ APPLETV:
- "Apple TV (2nd generation)"
- "Apple TV (3rd generation)"
- "Apple TV (4th generation)"
+ - "Apple TV 4K"
DISPLAYS:
name: Display
@@ -52,7 +53,10 @@ IMAC:
- "iMac (21.5-inch, Late 2015)"
- "iMac (Retina 4K, 21.5-inch, Late 2015)"
- "iMac (Retina 5K, 27-inch, Late 2015)"
-
+ - "iMac (21.5-inch, 2017)"
+ - "iMac (Retina 4K, 21.5-inch, 2017)"
+ - "iMac (Retina 5K, 27-inch, 2017)"
+ - "iMac Pro (2017)"
IPAD:
name: iPad
@@ -79,9 +83,17 @@ IPAD:
- "iPad Air (Wi-Fi)"
- "iPad Air (Wi-Fi + Cellular)"
- "iPad Air 2"
- - "iPad Pro"
- - "iPad Pro (Wi-Fi)"
- - "iPad Pro (Wi-Fi + Cellular)"
+ - "iPad Pro (12.9-inch) (Wi-Fi)"
+ - "iPad Pro (12.9-inch) (Wi-Fi + Cellular)"
+ - "iPad Pro (9.7-inch) (Wi-Fi)"
+ - "iPad Pro (9.7-inch) (Wi-Fi + Cellular)"
+ - "iPad (5th generation) (Wi-Fi)"
+ - "iPad (5th generation) (Wi-Fi + Cellular)"
+ - "iPad Pro (10.5-inch) (Wi-Fi)"
+ - "iPad Pro (10.5-inch) (Wi-Fi + Cellular)"
+ - "iPad Pro (12.9-inch) (2nd generation) (Wi-Fi)"
+ - "iPad Pro (12.9-inch) (2nd generation) (Wi-Fi + Cellular)"
+
IPADACCESSORY:
name: iPad Accessory
@@ -112,6 +124,9 @@ IPHONE:
- "iPhone SE"
- "iPhone 7"
- "iPhone 7 Plus"
+ - "iPhone 8"
+ - "iPhone 8 Plus"
+ - "iPhone X"
IPHONEACCESSORY:
name: iPhone Accessory
@@ -153,6 +168,7 @@ MACACCESSORY:
- "Apple 85W MagSafe Power Adapter"
- "AirPort Extreme 802.11ac"
- "AirPort Time Capsule 802.11ac"
+ - "Magic Keyboard with Numeric Keypad"
IPODCLASSIC:
name: iPod Classic
@@ -224,8 +240,8 @@ MACPRO:
- Mac Pro (Mid 2010)
- Mac Pro Server (Mid 2010)
- Mac Pro (Mid 2012)
- - Mac Pro (Late 2013)
- Mac Pro Server (Mid 2012)
+ - Mac Pro (Late 2013)
MACBOOK:
name: MacBook
@@ -243,6 +259,7 @@ MACBOOK:
- "MacBook (13-inch, Mid 2010)"
- "MacBook (Retina, 12-inch, Early 2015)"
- "MacBook (Retina, 12-inch, Early 2016)"
+ - "MacBook (Retina, 12-inch, 2017)"
MACBOOKLEGACY:
name: MacBook (Legacy)
@@ -277,6 +294,7 @@ MACBOOKAIR:
- "MacBook Air (13-inch, Early 2014)"
- "MacBook Air (11-inch, Early 2015)"
- "MacBook Air (13-inch, Early 2015)"
+ - "MacBook Air (13-inch, 2017)"
MACBOOKPRO:
name: MacBook Pro
@@ -318,7 +336,12 @@ MACBOOKPRO:
- "MacBook Pro (Retina, 15-inch, Mid 2014)"
- "MacBook Pro (Retina, 13-inch, Early 2015)"
- "MacBook Pro (Retina, 15-inch, Mid 2015)"
+ - "MacBook Pro (13-inch, 2016, Two Thunderbolt 3 Ports)"
+ - "MacBook Pro (13-inch, 2016, Four Thunderbolt 3 Ports)"
+ - "MacBook Pro (15-inch, 2016)"
- "MacBook Pro (13-inch, Late 2016, Two Thunderbolt 3 Ports)"
+ - "MacBook Pro (13-inch, 2017, Four Thunderbolt 3 Ports)"
+ - "MacBook Pro (15-inch, 2017)"
SERVERS:
name: Server
@@ -389,3 +412,12 @@ WATCH:
- "Watch Sport 42mm"
- "Watch Edition 38mm"
- "Watch Edition 42mm"
+ - "Apple Watch Series 1"
+ - "Apple Watch Series 2"
+ - "Apple Watch Series 3"
+
+AUDIO:
+ name: Audio
+ models:
+ - "AirPods"
+ - "HomePod"
diff --git a/gsxws/repairs.py b/gsxws/repairs.py
index 16a9add..10da94c 100644
--- a/gsxws/repairs.py
+++ b/gsxws/repairs.py
@@ -4,8 +4,8 @@
import sys
import logging
-from core import GsxObject, GsxError, validate
-from lookups import Lookup
+from .core import GsxObject, GsxError, validate
+from .lookups import Lookup
REPAIR_TYPES = (
('CA', 'Carry-In/Non-Replinished'),
@@ -400,7 +400,7 @@ class DepotShipperLabel(GsxObject):
if __name__ == '__main__':
import doctest
- from core import connect
+ from .core import connect
logging.basicConfig(level=logging.DEBUG)
connect(*sys.argv[1:])
doctest.testmod()
diff --git a/gsxws/returns.py b/gsxws/returns.py
index 2789942..c14ed35 100644
--- a/gsxws/returns.py
+++ b/gsxws/returns.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-from core import GsxObject, validate
+from .core import GsxObject, validate
RETURN_TYPES = (
(1, "Dead On Arrival"),
@@ -131,7 +131,7 @@ if __name__ == '__main__':
import sys
import doctest
import logging
- from core import connect
+ from .core import connect
logging.basicConfig(level=logging.DEBUG)
connect(*sys.argv[1:])
doctest.testmod()
diff --git a/gsxws/utils.py b/gsxws/utils.py
new file mode 100644
index 0000000..9d71e83
--- /dev/null
+++ b/gsxws/utils.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+
+import re
+import tempfile
+import requests
+
+
+def fetch_url(url):
+ """Downloads acceptable URL to temporary file
+ """
+ ext = None
+ ALLOWED = ['jpg', 'jpeg', 'png', 'pdf', 'gif',]
+
+ try:
+ ext = re.search(r'\.([a-zA-Z]{3,})$', url).group(1)
+ except AttributeError:
+ raise ValueError('Cannot determine file extension of URL %s' % url)
+
+ ext = ext.lower()
+
+ if ext not in ALLOWED:
+ raise ValueError('File extension should be one of %s, not %s' % (', '.join(ALLOWED), ext))
+
+ try:
+ resp = requests.get(url)
+ except Exception as e:
+ raise Exception('Failed to fetch URL: %s' % e)
+
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.' + ext) as fp:
+ fp.write(resp.content)
+ return fp.name
diff --git a/requirements.pip b/requirements.pip
index a3596c0..7bb3fbf 100644
--- a/requirements.pip
+++ b/requirements.pip
@@ -1,2 +1,3 @@
lxml
+PyYaml
requests
diff --git a/setup.py b/setup.py
index 57861cc..47de023 100644
--- a/setup.py
+++ b/setup.py
@@ -6,7 +6,7 @@ setup(
version=VERSION,
description="Library for communicating with GSX Web Services API.",
long_description=open('README.rst').read(),
- install_requires=['PyYAML', 'lxml'],
+ install_requires=['PyYAML', 'lxml', 'requests'],
classifiers=[
"Environment :: Web Environment",
"Intended Audience :: Developers",
diff --git a/tests/test_gsxws.py b/tests/test_gsxws.py
index 5f3476e..999dc77 100644
--- a/tests/test_gsxws.py
+++ b/tests/test_gsxws.py
@@ -1,17 +1,20 @@
# -*- coding: utf-8 -*-
import os
+import sys
import logging
from datetime import date, datetime
from unittest import TestCase, main, skip
-from gsxws.core import validate, GsxCache
+sys.path.append(os.path.abspath('..'))
+
+from gsxws.core import validate, GsxCache, connect
from gsxws.objectify import parse, gsx_diags_timestamp
from gsxws.products import Product
from gsxws import (repairs, escalations, lookups, returns,
- GsxError, diagnostics, comptia,
- comms,)
+ GsxError, diagnostics, comptia, products,
+ comms, parts,)
def empty(a):
@@ -20,7 +23,6 @@ def empty(a):
class CommsTestCase(TestCase):
def setUp(self):
- from gsxws.core import connect
self.priority = 'HIGH'
self.article_id = 'SN3133'
connect(os.getenv('GSX_USER'), os.getenv('GSX_SOLDTO'), os.getenv('GSX_ENV'))
@@ -45,7 +47,6 @@ class CommsTestCase(TestCase):
class RemoteTestCase(TestCase):
def setUp(self):
- from gsxws.core import connect
connect(os.getenv('GSX_USER'), os.getenv('GSX_SOLDTO'), os.getenv('GSX_ENV'))
self.sn = os.getenv('GSX_SN')
device = Product(sn=self.sn)
@@ -62,7 +63,7 @@ class RemoteTestCase(TestCase):
def assertUnicodeOrInt(self, val):
try:
- self.assertIsInstance(val, unicode)
+ self.assertIsInstance(val, str)
except AssertionError:
self.assertIsInstance(val, int)
@@ -75,7 +76,6 @@ class ComptiaTestCase(RemoteTestCase):
class DiagnosticsTestCase(TestCase):
def setUp(self):
- from gsxws.core import connect
connect(os.getenv('GSX_USER'), os.getenv('GSX_SOLDTO'), os.getenv('GSX_ENV'))
self.sn = os.getenv('GSX_SN')
device = Product(sn=self.sn)
@@ -88,11 +88,11 @@ class DiagnosticsTestCase(TestCase):
res = self.diag.fetch()
for r in res.diagnosticTestData.testResult.result:
- self.assertIsInstance(r.name, unicode)
+ self.assertIsInstance(r.name, str)
self.assertUnicodeOrInt(r.value)
for r in res.diagnosticProfileData.profile.unit.key:
- self.assertIsInstance(r.name, unicode)
+ self.assertIsInstance(r.name, str)
self.assertUnicodeOrInt(r.value)
for r in res.diagnosticProfileData.report.reportData.key:
@@ -107,16 +107,16 @@ class DiagnosticsTestCase(TestCase):
def test_fetch_dc_url(self):
url = self.diag.fetch_dc_url()
- self.assertRegexpMatches(url, r'^https://')
+ self.assertRegex(url, r'^https://')
def test_initiate_email(self):
self.diag.emailAddress = os.getenv('GSX_EMAIL')
res = self.diag.initiate()
- self.assertRegexpMatches(str(res), r'\d+')
+ self.assertRegex(str(res), r'\d+')
def test_initiate_phone(self):
self.diag.phoneNumber = os.getenv('GSX_PHONE')
- with self.assertRaisesRegexp(GsxError, 'SMS sending is not supported'):
+ with self.assertRaisesRegex(GsxError, 'SMS sending is not supported'):
self.diag.initiate()
@@ -155,17 +155,17 @@ class RepairTestCase(RemoteTestCase):
class CoreFunctionTestCase(TestCase):
def test_dump(self):
- rep = repairs.Repair(blaa=u'ääöö')
+ rep = repairs.Repair(blaa='ääöö')
part = repairs.RepairOrderLine()
part.partNumber = '661-5571'
rep.orderLines = [part]
- self.assertRegexpMatches(rep.dumps(),
+ self.assertRegex(rep.dumps(),
'<GsxObject><blaa>ääöö</blaa><orderLines>')
def test_cache(self):
"""Make sure the cache is working."""
c = GsxCache('test').set('spam', 'eggs')
- self.assertEquals(c.get('spam'), 'eggs')
+ self.assertEqual(c.get('spam'), 'eggs')
class TestTypes(TestCase):
@@ -174,7 +174,7 @@ class TestTypes(TestCase):
self.data = parse(xml, 'lookupResponseData')
def test_unicode(self):
- self.assertIsInstance(self.data.lastModifiedBy, unicode)
+ self.assertIsInstance(self.data.lastModifiedBy, str)
def test_timestamp(self):
self.assertIsInstance(self.data.createTimestamp, datetime)
@@ -197,7 +197,7 @@ class TestErrorFunctions(TestCase):
'This unit is not eligible for an Onsite repair from GSX.')
def test_message(self):
- self.assertRegexpMatches(self.data.message, 'Multiple error messages exist.')
+ self.assertRegex(self.data.message, 'Multiple error messages exist.')
def test_exception(self):
msg = 'Connection failed'
@@ -207,7 +207,7 @@ class TestErrorFunctions(TestCase):
def test_error_ca_fmip(self):
from gsxws.core import GsxResponse
xml = open('tests/fixtures/error_ca_fmip.xml', 'r').read()
- with self.assertRaisesRegexp(GsxError, 'A repair cannot be created'):
+ with self.assertRaisesRegex(GsxError, 'A repair cannot be created'):
GsxResponse(xml=xml, el_method='CreateCarryInResponse',
el_response='repairConfirmation')
@@ -276,7 +276,7 @@ class TestSympomIssueFunctions(RemoteTestCase):
def test_issue_code(self):
self._issues = repairs.SymptomIssue(reportedSymptomCode=self.symptom).fetch()
self.issue = self._issues[0][0]
- self.assertRegexpMatches(self.issue, r'[A-Z]+')
+ self.assertRegex(self.issue, r'[A-Z]+')
class TestRepairFunctions(RepairTestCase):
@@ -367,13 +367,28 @@ class TestRepairFunctions(RepairTestCase):
class TestPartFunction(RemoteTestCase):
def test_product_parts(self):
parts = Product(os.getenv('GSX_SN')).parts()
- self.assertIsInstance(parts[0].partNumber, basestring)
+ self.assertIsInstance(parts[0].partNumber, str)
+
+
+class TestProductData(TestCase):
+ def test_models(self):
+ models = products.models()
+
+ def test_product_image(self):
+ product = Product(os.getenv('GSX_SN', '123456789'))
+ product.description = 'MacBook Air (13-inch min 2013)'
+ img = product.fetch_image('https://static.servoapp.com/images/products/macbook-air-13-inchmid-2013.jpg')
+ self.assertTrue(os.path.exists(img))
+
+ def test_part_image(self):
+ part = parts.Part(partNumber='661-1234')
+ img = part.fetch_image()
+ self.assertTrue(os.path.exists(img))
class TestRemoteWarrantyFunctions(TestCase):
@classmethod
def setUpClass(cls):
- from gsxws.core import connect
connect(os.getenv('GSX_USER'), os.getenv('GSX_SOLDTO'), os.getenv('GSX_ENV'))
def setUp(self):
@@ -580,7 +595,7 @@ class TestCarryinRepairDetail(TestCase):
self.assertEqual(self.data.dispatchId, 'G2093174681')
def test_unicode_name(self):
- self.assertEqual(self.data.primaryAddress.firstName, u'Ääkköset')
+ self.assertEqual(self.data.primaryAddress.firstName, 'Ääkköset')
class ConnectionTestCase(TestCase):
@@ -588,11 +603,12 @@ class ConnectionTestCase(TestCase):
def test_access_denied(self):
"""Make sure we fail with 403 when connecting from non-whitelisted IP."""
- from gsxws.core import connect
- with self.assertRaisesRegexp(GsxError, 'Access denied'):
- connect(os.getenv('GSX_USER'), os.getenv('GSX_SOLDTO'), os.getenv('GSX_ENV'))
+ with self.assertRaisesRegex(GsxError, 'Access denied'):
+ connect(os.getenv('GSX_USER'), os.getenv('GSX_SOLDTO'),
+ os.getenv('GSX_ENV'))
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG)
+ GsxCache.nukeall() # to avoid pickle errors between different Python versions
main()