зеркало из https://github.com/microsoft/InQRy.git
Merged PR 43599: Merge pybar to master
This code is not yet ready for production. However, it should be reviewed regularly during the development process. Please verify the code "builds" successfully using `python3 setup.py install` and that all tests pass using `pytest` Any and all feedback is appreciated! Related work items: #1409731
This commit is contained in:
Родитель
f2a5eb93b7
Коммит
8cfbed127e
|
@ -1,20 +1,11 @@
|
||||||
test-scripts/
|
.eggs/
|
||||||
*.cache/
|
.idea/workspace.xml
|
||||||
*.egg-info/
|
.idea/tasks.xml
|
||||||
*.eggs/
|
.idea/libraries/
|
||||||
|
.idea/dictionaries/
|
||||||
*.pyc
|
.cache/
|
||||||
*.pdf
|
*.iml
|
||||||
*.cache
|
*.egg-info
|
||||||
*.cre.js
|
|
||||||
*.default.js
|
|
||||||
*.settings.js
|
|
||||||
|
|
||||||
dist/
|
|
||||||
build/
|
build/
|
||||||
|
dist/
|
||||||
.installed.cfg
|
**/__pycache__/
|
||||||
.DS_Store
|
|
||||||
|
|
||||||
cr8000.js
|
|
||||||
translate.xml
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6.0 (~/.pyenv/versions/3.6.0/bin/python)" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/lab_inventory.iml" filepath="$PROJECT_DIR$/.idea/lab_inventory.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -1,5 +1,5 @@
|
||||||
# PyBar
|
# 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
|
### Install
|
||||||
|
|
||||||
|
@ -8,4 +8,4 @@ Generate asset QR codes for a physical inventory procedure
|
||||||
|
|
||||||
### Test
|
### Test
|
||||||
|
|
||||||
`python3 setup.py pytest`
|
`python3 setup.py test`
|
||||||
|
|
|
@ -1,7 +1,27 @@
|
||||||
class Asset:
|
class Asset(object):
|
||||||
"""The current machine and it's associated specs"""
|
"""
|
||||||
def __init__(self):
|
Represents the object to be entered into a Snipe-IT inventory database.
|
||||||
pass
|
|
||||||
|
|
||||||
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
|
return None
|
||||||
|
|
|
@ -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')
|
|
@ -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()
|
|
@ -0,0 +1,6 @@
|
||||||
|
class Instructions:
|
||||||
|
"""Create Instructions object"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""TODO"""
|
||||||
|
pass
|
|
@ -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<disk_size>\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')
|
|
@ -1,6 +1,9 @@
|
||||||
import instructions
|
from qrcode import QRCode
|
||||||
|
|
||||||
fieldset = {'trashcan': instructions.trashcan}
|
|
||||||
|
|
||||||
for fieldset in fieldsets:
|
class AssetQRCode(QRCode):
|
||||||
pass
|
"""TODO"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""TODO"""
|
||||||
|
pass
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
class SystemProfile:
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
||||||
|
[aliases]
|
||||||
|
test=pytest
|
17
setup.py
17
setup.py
|
@ -1,16 +1,21 @@
|
||||||
#!/usr/bin/env python
|
try:
|
||||||
|
from setuptools import setup
|
||||||
from setuptools import setup
|
except ImportError:
|
||||||
|
from distutils.core import setup
|
||||||
|
|
||||||
setup(name='PyBar',
|
setup(name='PyBar',
|
||||||
version='0.0.1',
|
version='0.0.2',
|
||||||
license='MIT',
|
license='MIT',
|
||||||
description='Generate QRCodes for a Physical Inventory',
|
description='Generate QRCodes for a physical inventory',
|
||||||
author='Eric Hanko',
|
author='Eric Hanko',
|
||||||
author_email='v-erhank@microsoft.com',
|
author_email='v-erhank@microsoft.com',
|
||||||
packages=['pybar'],
|
packages=['pybar'],
|
||||||
long_description=open('README.md').read(),
|
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'],
|
setup_requires=['pytest-runner'],
|
||||||
tests_require=['pytest'],
|
tests_require=['pytest'],
|
||||||
)
|
)
|
||||||
|
|
|
@ -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
|
|
|
@ -1,7 +0,0 @@
|
||||||
import pytest
|
|
||||||
from pybar.system_profile import SystemProfile
|
|
||||||
|
|
||||||
|
|
||||||
class TestSystemProfile:
|
|
||||||
def test_empty_profile_instantiation_works(self):
|
|
||||||
SystemProfile()
|
|
|
@ -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
|
|
@ -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)
|
|
@ -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')
|
|
@ -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'
|
|
@ -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'
|
|
@ -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()
|
Загрузка…
Ссылка в новой задаче