diff --git a/.gitignore b/.gitignore
index eb56fde..7a5e1bd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,20 +1,11 @@
-test-scripts/
-*.cache/
-*.egg-info/
-*.eggs/
-
-*.pyc
-*.pdf
-*.cache
-*.cre.js
-*.default.js
-*.settings.js
-
-dist/
+.eggs/
+.idea/workspace.xml
+.idea/tasks.xml
+.idea/libraries/
+.idea/dictionaries/
+.cache/
+*.iml
+*.egg-info
build/
-
-.installed.cfg
-.DS_Store
-
-cr8000.js
-translate.xml
+dist/
+**/__pycache__/
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..6374de0
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..9ab5580
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 4b16683..9f8f978 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# PyBar
-Generate asset QR codes for a physical inventory procedure
+Generate a QR code for a physical inventory procedure based on an individual asset's hardware specifications
### Install
@@ -8,4 +8,4 @@ Generate asset QR codes for a physical inventory procedure
### Test
-`python3 setup.py pytest`
+`python3 setup.py test`
diff --git a/pybar/asset.py b/pybar/asset.py
index 9913fdc..380d830 100644
--- a/pybar/asset.py
+++ b/pybar/asset.py
@@ -1,7 +1,27 @@
-class Asset:
- """The current machine and it's associated specs"""
- def __init__(self):
- pass
+class Asset(object):
+ """
+ Represents the object to be entered into a Snipe-IT inventory database.
- def is_valid(self):
+ An Asset object is built from a SystemProfile object and it's
+ attributes, which is then used to assemble the QR code.
+ """
+
+ def __init__(self, systemprofile):
+ """
+ Instantiates an Asset object with several attributes,
+ all which can be used to build a QR code.
+ """
+ self.systemprofile = systemprofile
+ self.cpu_name = systemprofile.cpu_name
+ self.cpu_processors = systemprofile.cpu_processors
+ self.cpu_speed = systemprofile.cpu_speed
+ self.cpu_cores = systemprofile.cpu_cores
+ self.memory = systemprofile.memory
+ self.serial = systemprofile.serial
+ self.model = systemprofile.model
+ self.name = systemprofile.name
+
+ @staticmethod
+ def is_valid():
+ """TODO"""
return None
diff --git a/pybar/diskutil.py b/pybar/diskutil.py
new file mode 100644
index 0000000..bc3303b
--- /dev/null
+++ b/pybar/diskutil.py
@@ -0,0 +1,27 @@
+import re
+import shlex
+import subprocess
+
+BASE_COMMAND = '/usr/sbin/diskutil'
+
+
+def get_physical_disk_identifiers(diskutil_list_output=None):
+ diskutil_list_output = diskutil_list_output or list_all()
+ physical_disk_id_pattern = re.compile(r'(/dev/disk\d+) \(\w+, physical\).*')
+
+ return re.findall(physical_disk_id_pattern, diskutil_list_output)
+
+
+def get_disk_info(disk_identifier):
+ return _get_output_of_diskutil_command(arguments=f'info {disk_identifier}')
+
+
+def list_all():
+ return _get_output_of_diskutil_command(arguments='list')
+
+
+def _get_output_of_diskutil_command(arguments=None):
+ arguments = arguments or ''
+ full_command = shlex.split(' '.join([BASE_COMMAND, arguments]))
+
+ return subprocess.check_output(full_command).decode('utf-8')
diff --git a/pybar/gui.py b/pybar/gui.py
new file mode 100644
index 0000000..7be6d98
--- /dev/null
+++ b/pybar/gui.py
@@ -0,0 +1,18 @@
+import tkinter as tk
+
+win = tk.Tk()
+win.title("PyBar")
+# tk.Label()(win, text="Label").grid(column=0, row=0)
+label = tk.Label(win, text="Hello")
+label.grid(column=0, row=0)
+
+
+def click():
+ action.configure()
+ label.configure(foreground="red")
+
+
+action = tk.Button(win, text="Generate QR Code", command=click)
+action.grid(column=1, row=0)
+
+win.mainloop()
diff --git a/pybar/instructions.py b/pybar/instructions.py
new file mode 100644
index 0000000..accb3be
--- /dev/null
+++ b/pybar/instructions.py
@@ -0,0 +1,6 @@
+class Instructions:
+ """Create Instructions object"""
+
+ def __init__(self):
+ """TODO"""
+ pass
diff --git a/pybar/ios.py b/pybar/ios.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pybar/macdisk.py b/pybar/macdisk.py
new file mode 100644
index 0000000..fa1156e
--- /dev/null
+++ b/pybar/macdisk.py
@@ -0,0 +1,52 @@
+import re
+import yaml
+from pybar import diskutil
+
+
+def create_from_diskutil_info_output(output):
+ return Disk(yaml.load(output))
+
+
+def get_all_physical_disks():
+ return [
+ create_from_diskutil_info_output(diskutil.get_disk_info(disk_identifier))
+ for disk_identifier in diskutil.get_physical_disk_identifiers()
+ ]
+
+
+class Disk:
+
+ def __init__(self, attributes=None):
+ self.attributes = attributes or {}
+
+ @property
+ def device_location(self):
+ return self.attributes.get('Device Location')
+
+ @property
+ def is_internal(self):
+ return self.device_location == 'Internal'
+
+ @property
+ def is_external(self):
+ return self.device_location == 'External'
+
+ @property
+ def device_name(self):
+ return self.attributes.get('Device / Media Name')
+
+ @property
+ def is_ssd(self):
+ return self.attributes.get('Solid State')
+
+ @property
+ def verbose_disk_size(self):
+ return self.attributes.get('Disk Size') or self.attributes.get('Total Size')
+
+ @property
+ def size(self):
+ disk_size_pattern = re.compile(r'(?P\d+\.?\d* [MGT]?B) .*$')
+ disk_size_match = re.match(disk_size_pattern, self.verbose_disk_size)
+
+ if disk_size_match:
+ return disk_size_match.group('disk_size')
diff --git a/pybar/osx.py b/pybar/osx.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pybar/qr_builder.py b/pybar/qr_builder.py
index f9cd951..c838792 100644
--- a/pybar/qr_builder.py
+++ b/pybar/qr_builder.py
@@ -1,6 +1,9 @@
-import instructions
+from qrcode import QRCode
-fieldset = {'trashcan': instructions.trashcan}
-for fieldset in fieldsets:
- pass
+class AssetQRCode(QRCode):
+ """TODO"""
+
+ def __init__(self):
+ """TODO"""
+ pass
diff --git a/pybar/system_profile.py b/pybar/system_profile.py
deleted file mode 100644
index 71e4e75..0000000
--- a/pybar/system_profile.py
+++ /dev/null
@@ -1,3 +0,0 @@
-class SystemProfile:
- def __init__(self):
- pass
diff --git a/pybar/systemprofile.py b/pybar/systemprofile.py
new file mode 100644
index 0000000..fc97918
--- /dev/null
+++ b/pybar/systemprofile.py
@@ -0,0 +1,116 @@
+import platform
+import subprocess
+import yaml
+
+
+class SystemProfile(object):
+ """Represents the machine's "system profile" before it is parsed and
+ converted into an Asset object.
+
+ A SystemProfile object should be able to be used to access several system
+ profile specs, even if they are not used by the Asset class.
+
+ A SystemProfile object should also be able to be used the same way,
+ regardless of which operating system the specs were generated from"""
+
+ def __init__(self):
+ """TODO"""
+ self.os_type = platform.system()
+
+ def operating_system(self):
+ if self.os_type == 'Darwin':
+ mac_hardware()
+ elif self.os_type == 'Windows':
+ windows()
+ else:
+ raise OSError(
+ '{os}: Unknown operating system'.format(os=self.os_type))
+
+ def storage(self):
+ pass
+
+ @property
+ def serial(self):
+ serial = mac_hardware().get('Serial Number (system)')
+ assert isinstance(serial, str)
+ return serial
+
+ @property
+ def cpu_name(self):
+ name = mac_hardware().get('Processor Name')
+ assert isinstance(name, str)
+ return name
+
+ @property
+ def cpu_processors(self):
+ processors = mac_hardware().get('Number of Processors')
+ assert isinstance(processors, int)
+ return processors
+
+ @property
+ def cpu_cores(self):
+ cores = mac_hardware().get('Total Number of Cores')
+ assert isinstance(cores, int)
+ return cores
+
+ @property
+ def cpu_speed(self):
+ speed = mac_hardware().get('Processor Speed')
+ assert isinstance(speed, str)
+ return speed
+
+ @property
+ def memory(self):
+ memory = mac_hardware().get('Memory')
+ return memory
+
+ @property
+ def model(self):
+ model = mac_hardware().get('Model Identifier')
+ return model
+
+ @property
+ def name(self):
+ name = mac_hardware().get('Model Name')
+ return name
+
+
+def _mac_system_profiler(data_type):
+ """
+ This function is passed one of several strings that is then parsed using
+ the yaml module and can then be utilized in other mac_data_type functions.
+
+ Used only for '/usr/sbin/system_profiler' argument 'SPHardwareDataType'
+ :param data_type:
+ :return: data
+ """
+ command = [
+ '/usr/sbin/system_profiler', 'SP' + str.title(data_type) + 'DataType']
+ data = yaml.load(subprocess.check_output(command))
+ return data
+
+
+def mac_hardware():
+ """
+ This function is used as the primary means of obtaining basic Mac
+ hardware components.
+ """
+ system_profiler_hardware = _mac_system_profiler('hardware')
+ hardware_components = system_profiler_hardware['Hardware']['Hardware Overview']
+ return hardware_components
+
+
+def mac_storage():
+ """
+ This function will be used as the primary means of obtaining data about
+ the a Mac's storage specifications.
+ """
+ pass
+
+
+def windows():
+ """
+ This function is used as the primary means of obtaining basic Windows
+ machine hardware components.
+ """
+ pass
diff --git a/pybar/windows.py b/pybar/windows.py
deleted file mode 100644
index e69de29..0000000
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..b7e4789
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,2 @@
+[aliases]
+test=pytest
diff --git a/setup.py b/setup.py
index c26a36d..465e5af 100644
--- a/setup.py
+++ b/setup.py
@@ -1,16 +1,21 @@
-#!/usr/bin/env python
-
-from setuptools import setup
+try:
+ from setuptools import setup
+except ImportError:
+ from distutils.core import setup
setup(name='PyBar',
- version='0.0.1',
+ version='0.0.2',
license='MIT',
- description='Generate QRCodes for a Physical Inventory',
+ description='Generate QRCodes for a physical inventory',
author='Eric Hanko',
author_email='v-erhank@microsoft.com',
packages=['pybar'],
long_description=open('README.md').read(),
- install_requires=["qrcode >= 5.3.0"],
+ install_requires=[
+ "qrcode >= 5.3.0",
+ "PyYAML >= 3.12",
+ "pytest-runner",
+ "pytest"],
setup_requires=['pytest-runner'],
tests_require=['pytest'],
)
diff --git a/test/__init__.py b/test/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/test/asset_test.py b/test/asset_test.py
deleted file mode 100644
index 9dbaead..0000000
--- a/test/asset_test.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import pytest
-from pybar.asset import Asset
-
-test_data = {
- 'owner': 'Hanko',
- 'serial': 'HZ1KF3L90',
- 'cpu': ('Intel', 'Core i7', '2.9GHz')
-}
-
-
-class TestAsset:
- def test_empty_asset_instantiation_works(self):
- Asset()
-
- def test_empty_asset_is_not_valid(self):
- asset = Asset()
- assert not asset.is_valid()
-
- def test_asset_is_valid_with_known_good_test_data(self):
- pass
diff --git a/test/system_profile_test.py b/test/system_profile_test.py
deleted file mode 100644
index 91ef63b..0000000
--- a/test/system_profile_test.py
+++ /dev/null
@@ -1,7 +0,0 @@
-import pytest
-from pybar.system_profile import SystemProfile
-
-
-class TestSystemProfile:
- def test_empty_profile_instantiation_works(self):
- SystemProfile()
diff --git a/tests/test_asset_object.py b/tests/test_asset_object.py
new file mode 100644
index 0000000..a3e986d
--- /dev/null
+++ b/tests/test_asset_object.py
@@ -0,0 +1,88 @@
+import pytest
+from pybar.asset import Asset
+from pybar.systemprofile import SystemProfile
+
+
+sp = SystemProfile()
+asset = Asset(sp)
+
+
+def test_empty_asset_instantiation_works():
+ Asset(sp)
+
+
+def test_empty_asset_is_not_valid():
+ assert not asset.is_valid()
+
+
+def test_presence_of_cpu_name_attribute():
+ assert hasattr(asset, 'cpu_name')
+
+
+def test_cpu_attribute_is_tuple():
+ assert isinstance(asset.cpu_name, str)
+
+
+def test_presence_of_cpu_speed_attribute():
+ assert hasattr(asset, 'cpu_speed')
+
+
+def test_cpu_speed_is_integer():
+ assert isinstance(asset.cpu_speed, str)
+
+
+def test_presence_of_cpu_processors_attribute():
+ assert hasattr(asset, 'cpu_processors')
+
+
+def test_cpu_processor_is_string():
+ assert isinstance(asset.cpu_processors, int)
+
+
+def test_presence_of_cpu_cores_attribute():
+ assert hasattr(asset, 'cpu_cores')
+
+
+def test_cpu_cores_is_integer():
+ assert isinstance(asset.cpu_cores, int)
+
+
+def test_presence_of_memory_attribute():
+ assert hasattr(asset, 'memory')
+
+
+def test_memory_attribute_is_string():
+ assert isinstance(asset.memory, str)
+
+
+def test_presence_of_serial_attribute():
+ assert hasattr(asset, 'serial')
+
+
+def test_serial_attribute_is_string():
+ assert isinstance(asset.serial, str)
+
+
+def test_presence_of_name_attribute():
+ assert hasattr(asset, 'name')
+
+
+def test_name_attribute_is_string():
+ assert isinstance(asset.model, str)
+
+
+def test_presence_of_model_attribute():
+ assert hasattr(asset, 'model')
+
+
+def test_model_attribute_is_string():
+ assert isinstance(asset.model, str)
+
+
+def test_serial_is_correct_length():
+ assert len(asset.serial) == 12
+
+
+@pytest.mark.skip
+def test_asset_is_valid_with_known_good_test_data():
+ pass
diff --git a/tests/test_getting_physical_disk_identifiers.py b/tests/test_getting_physical_disk_identifiers.py
new file mode 100644
index 0000000..f26efea
--- /dev/null
+++ b/tests/test_getting_physical_disk_identifiers.py
@@ -0,0 +1,58 @@
+from pybar import diskutil
+
+diskutil_list_output = '''/dev/disk0 (internal, physical):
+ #: TYPE NAME SIZE IDENTIFIER
+ 0: GUID_partition_scheme *751.3 GB disk0
+ 1: EFI EFI 209.7 MB disk0s1
+ 2: Apple_CoreStorage Macintosh HD 750.4 GB disk0s2
+ 3: Apple_Boot Recovery HD 650.1 MB disk0s3
+/dev/disk1 (internal, virtual):
+ #: TYPE NAME SIZE IDENTIFIER
+ 0: Apple_HFS Macintosh HD +750.1 GB disk1
+ Logical Volume on disk0s2
+ 2F555A8B-D884-485F-985A-3B7ADF7BFCB5
+ Unlocked Encrypted
+/dev/disk2 (disk image):
+ #: TYPE NAME SIZE IDENTIFIER
+ 0: Apple_partition_scheme +19.8 MB disk2
+ 1: Apple_partition_map 32.3 KB disk2s1
+ 2: Apple_HFS Flash Player 19.7 MB disk2s2
+/dev/disk3 (disk image):
+ #: TYPE NAME SIZE IDENTIFIER
+ 0: GUID_partition_scheme +35.8 MB disk3
+ 1: Apple_HFS Synergy 35.8 MB disk3s1
+/dev/disk4 (external, physical):
+ #: TYPE NAME SIZE IDENTIFIER
+ 0: FDisk_partition_scheme *2.0 TB disk4
+ 1: Windows_NTFS My Passport 2.0 TB disk4s1
+/dev/disk5 (external, physical):
+ #: TYPE NAME SIZE IDENTIFIER
+ 0: GUID_partition_scheme *2.0 TB disk5
+ 1: EFI EFI 209.7 MB disk5s1
+ 2: Apple_HFS Builds 1.5 TB disk5s2
+ 3: Apple_HFS Source 499.7 GB disk5s3
+/dev/disk6 (external, physical):
+ #: TYPE NAME SIZE IDENTIFIER
+ 0: GUID_partition_scheme *1.0 TB disk6
+ 1: EFI EFI 209.7 MB disk6s1
+ 2: Apple_RAID 999.9 GB disk6s2
+ 3: Apple_Boot Boot OS X 134.2 MB disk6s3
+/dev/disk7 (external, physical):
+ #: TYPE NAME SIZE IDENTIFIER
+ 0: GUID_partition_scheme *1.0 TB disk7
+ 1: EFI EFI 209.7 MB disk7s1
+ 2: Apple_RAID 999.9 GB disk7s2
+ 3: Apple_Boot Boot OS X 134.2 MB disk7s3
+/dev/disk8 (external, virtual):
+ #: TYPE NAME SIZE IDENTIFIER
+ 0: Apple_HFS RedBackup +2.0 TB disk8
+
+'''
+
+
+def test_only_physical_drives_included():
+ expected_physical_disks = [
+ '/dev/disk0', '/dev/disk4', '/dev/disk5', '/dev/disk6', '/dev/disk7']
+
+ assert expected_physical_disks == diskutil.get_physical_disk_identifiers(
+ diskutil_list_output)
diff --git a/tests/test_qr_builder.py b/tests/test_qr_builder.py
new file mode 100644
index 0000000..1af521d
--- /dev/null
+++ b/tests/test_qr_builder.py
@@ -0,0 +1,10 @@
+from pybar.qr_builder import AssetQRCode
+
+
+def test_empty_asset_qr_code_can_be_instantiated():
+ AssetQRCode()
+
+
+def test_asset_qr_code_as_attributes_of_inherited_class():
+ qr = AssetQRCode()
+ assert hasattr(qr, 'add_data')
diff --git a/tests/test_representing_external_hdd.py b/tests/test_representing_external_hdd.py
new file mode 100644
index 0000000..02c3279
--- /dev/null
+++ b/tests/test_representing_external_hdd.py
@@ -0,0 +1,54 @@
+from pybar import macdisk
+
+diskutil_output = ''' Device Identifier: disk5
+ Device Node: /dev/disk5
+ Whole: Yes
+ Part of Whole: disk2
+ Device / Media Name: G-DRIVE PRO Thunderbolt
+
+ Volume Name: Not applicable (no file system)
+ Mounted: Not applicable (no file system)
+ File System: None
+
+ Content (IOContent): GUID_partition_scheme
+ OS Can Be Installed: No
+ Media Type: Generic
+ Protocol: SATA
+ SMART Status: Verified
+
+ Disk Size: 2.0 TB (2000179691520 Bytes) (exactly 3906600960 512-Byte-Units)
+ Device Block Size: 512 Bytes
+
+ Read-Only Media: No
+ Read-Only Volume: Not applicable (no file system)
+
+ Device Location: External
+ Removable Media: Fixed
+
+ Solid State: No
+ Virtual: No
+ OS 9 Drivers: No
+ Low Level Format: Not supported
+'''
+
+test_disk = macdisk.create_from_diskutil_info_output(diskutil_output)
+
+
+def test_disk_is_not_internal():
+ assert test_disk.is_internal is False
+
+
+def test_disk_is_external():
+ assert test_disk.is_external
+
+
+def test_device_name_is_correct():
+ assert test_disk.device_name == 'G-DRIVE PRO Thunderbolt'
+
+
+def test_disk_is_not_ssd():
+ assert test_disk.is_ssd is False
+
+
+def test_size_is_correct():
+ assert test_disk.size == '2.0 TB'
diff --git a/tests/test_representing_internal_ssd.py b/tests/test_representing_internal_ssd.py
new file mode 100644
index 0000000..d8c7389
--- /dev/null
+++ b/tests/test_representing_internal_ssd.py
@@ -0,0 +1,58 @@
+from pybar import macdisk
+
+diskutil_output = ''' Device Identifier: disk0
+ Device Node: /dev/disk0
+ Whole: Yes
+ Part of Whole: disk0
+ Device / Media Name: APPLE SSD SM768E
+
+ Volume Name: Not applicable (no file system)
+
+ Mounted: Not applicable (no file system)
+
+ File System: None
+
+ Content (IOContent): GUID_partition_scheme
+ OS Can Be Installed: No
+ Media Type: Generic
+ Protocol: SATA
+ SMART Status: Verified
+
+ Total Size: 751.3 GB (751277983744 Bytes) (exactly 1467339812 512-Byte-Units)
+ Volume Free Space: Not applicable (no file system)
+ Device Block Size: 512 Bytes
+
+ Read-Only Media: No
+ Read-Only Volume: Not applicable (no file system)
+
+ Device Location: Internal
+ Removable Media: No
+
+ Solid State: Yes
+ Virtual: No
+ OS 9 Drivers: No
+ Low Level Format: Not supported
+
+'''
+
+test_disk = macdisk.create_from_diskutil_info_output(diskutil_output)
+
+
+def test_disk_is_internal():
+ assert test_disk.is_internal
+
+
+def test_disk_is_not_external():
+ assert test_disk.is_external is False
+
+
+def test_device_name_is_correct():
+ assert test_disk.device_name == 'APPLE SSD SM768E'
+
+
+def test_disk_is_ssd():
+ assert test_disk.is_ssd
+
+
+def test_size_is_correct():
+ assert test_disk.size == '751.3 GB'
diff --git a/tests/test_systemprofile_object.py b/tests/test_systemprofile_object.py
new file mode 100644
index 0000000..5ed7bae
--- /dev/null
+++ b/tests/test_systemprofile_object.py
@@ -0,0 +1,120 @@
+import pytest
+from pybar.systemprofile import SystemProfile, mac_hardware
+
+hardware_test_data_as_dict = {
+ 'Hardware':
+ {
+ 'Hardware Overview':
+ {
+ 'Model Name': 'MacBook Pro',
+ 'Model Identifier': 'MacBookPro11,2',
+ 'Processor Name': 'Intel Core i7',
+ 'Processor Speed': '2.2 GHz',
+ 'Number of Processors': 1,
+ 'Total Number of Cores': 4,
+ 'L2 Cache (per Core)': '256 KB',
+ 'L3 Cache': '6 MB', 'Memory': '16 GB',
+ 'Boot ROM Version': 'MBP112.0138.B21',
+ 'SMC Version (system)': '2.18f15',
+ 'Serial Number (system)': 'C02NT9WJG3QC',
+ 'Hardware UUID': '7BE2608D-6373-52C7-B5FB-442C261A71A4'}}}
+
+hardware_test_data_as_yaml = """
+ Hardware:
+
+ Hardware Overview:
+
+ Model Name: Mac Pro
+ Model Identifier: MacPro6,1
+ Processor Name: Quad-Core Intel Xeon E5
+ Processor Speed: 3.7 GHz
+ Number of Processors: 1
+ Total Number of Cores: 4
+ L2 Cache (per Core): 256 KB
+ L3 Cache: 10 MB
+ Memory: 32 GB
+ Boot ROM Version: MP61.0116.B21
+ SMC Version (system): 2.20f18
+ Illumination Version: 1.4a6
+ Serial Number (system): F5KQH0P9F9VN
+ Hardware UUID: 4D4C19C7-19C4-5678-A936-A419C4609AFD"""
+
+
+def test_empty_profile_instantiation_works():
+ SystemProfile()
+
+
+def test_that_system_profile_object_operating_system_attribute():
+ sp = SystemProfile()
+ assert hasattr(sp, "operating_system")
+
+
+def test_that_system_profile_object_has_storage_attribute():
+ sp = SystemProfile()
+ assert hasattr(sp, "storage")
+
+
+def test_that_system_profile_object_has_serial_attribute():
+ sp = SystemProfile()
+ assert hasattr(sp, "serial")
+
+
+def test_that_system_profile_object_has_cpu_name_attribute():
+ sp = SystemProfile()
+ assert hasattr(sp, "cpu_name")
+
+
+def test_that_system_profile_object_has_cpu_speed_attribute():
+ sp = SystemProfile()
+ assert hasattr(sp, "cpu_speed")
+
+
+def test_that_system_profile_object_has_cpu_processors_attribute():
+ sp = SystemProfile()
+ assert hasattr(sp, "cpu_processors")
+
+
+def test_that_system_profile_object_has_cpu_cores_attribute():
+ sp = SystemProfile()
+ assert hasattr(sp, "cpu_cores")
+
+
+def test_that_system_profile_object_has_model_attribute():
+ sp = SystemProfile()
+ assert hasattr(sp, "model")
+
+
+def test_that_system_profile_object_has_name_attribute():
+ sp = SystemProfile()
+ assert hasattr(sp, "name")
+
+
+def test_that_system_profile_object_has_memory_attribute():
+ sp = SystemProfile()
+ assert hasattr(sp, "memory")
+
+
+@pytest.mark.skip
+def test_when_ios_device_is_connected():
+ pass
+
+
+@pytest.mark.skip
+def test_ability_to_get_components_from_system_profile_object():
+ pass
+
+
+def test_mac_hardware_method_output_data_type_is_dictionary():
+ assert isinstance(mac_hardware(), dict)
+
+
+def test_system_profiler_has_os_type_attribute():
+ sp = SystemProfile()
+ assert sp.os_type
+
+
+def test_operating_system_method_fails_when_operating_system_is_not_darwin_or_windows():
+ sp = SystemProfile()
+ sp.os_type = 'Linux'
+ with pytest.raises(OSError):
+ sp.operating_system()