diff --git a/os_traits/__init__.py b/os_traits/__init__.py index 109423c..c246abb 100644 --- a/os_traits/__init__.py +++ b/os_traits/__init__.py @@ -20,8 +20,12 @@ __version__ = pbr.version.VersionInfo( 'os_traits').version_string() -# Conveniently import all the constants into the main module "namespace" -from os_traits.const import * # noqa +# Any user-specified feature/trait is prefixed with the custom namespace +CUSTOM_NAMESPACE = 'CUSTOM_' + +# Each submodule registers its symbols with the os_traits module namespace +from os_traits.hw.cpu import x86 # noqa +from os_traits.storage import disk # noqa def get_symbol_names(prefix=None): @@ -30,15 +34,10 @@ def get_symbol_names(prefix=None): :param prefix: Optional string prefix to filter by. e.g. 'HW_' """ - excluded_keys = ('NAMESPACES',) - excluded_values = NAMESPACES.values() - return [ k for k, v in sys.modules[__name__].__dict__.items() if isinstance(v, six.string_types) and not k.startswith('_') and - k not in excluded_keys and - v not in excluded_values and (prefix is None or v.startswith(prefix)) ] @@ -49,15 +48,10 @@ def get_traits(prefix=None): :param prefix: Optional string prefix to filter by. e.g. 'HW_' """ - excluded_keys = ('NAMESPACES',) - excluded_values = NAMESPACES.values() - return [ v for k, v in sys.modules[__name__].__dict__.items() if isinstance(v, six.string_types) and not k.startswith('_') and - k not in excluded_keys and - v not in excluded_values and (prefix is None or v.startswith(prefix)) ] @@ -82,4 +76,4 @@ def is_custom(trait): :param trait: String name of the trait """ - return trait.startswith(NAMESPACES['CUSTOM']) + return trait.startswith(CUSTOM_NAMESPACE) diff --git a/os_traits/const.py b/os_traits/const.py deleted file mode 100644 index c6839e7..0000000 --- a/os_traits/const.py +++ /dev/null @@ -1,91 +0,0 @@ -# -*- coding: utf-8 -*- - -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# Any user-specified feature/trait is prefixed with the custom namespace -_CUSTOM_NS = 'CUSTOM_' - -# All hardware-specific features are prefixed with this namespace -_HW_NS = 'HW_' - -# All CPU-specific features are prefixed with this namespace -_CPU_NS = _HW_NS + 'CPU_' - -_CPU_X86_NS = _CPU_NS + 'X86_' - -# ref: https://en.wikipedia.org/wiki/Streaming_SIMD_Extensions -HW_CPU_X86_AVX = _CPU_X86_NS + 'AVX' -HW_CPU_X86_AVX2 = _CPU_X86_NS + 'AVX2' -HW_CPU_X86_CLMUL = _CPU_X86_NS + 'CLMUL' -HW_CPU_X86_FMA3 = _CPU_X86_NS + 'FMA3' -HW_CPU_X86_FMA4 = _CPU_X86_NS + 'FMA4' -HW_CPU_X86_F16C = _CPU_X86_NS + 'F16C' -HW_CPU_X86_MMX = _CPU_X86_NS + 'MMX' -HW_CPU_X86_SSE = _CPU_X86_NS + 'SSE' -HW_CPU_X86_SSE2 = _CPU_X86_NS + 'SSE2' -HW_CPU_X86_SSE3 = _CPU_X86_NS + 'SSE3' -HW_CPU_X86_SSSE3 = _CPU_X86_NS + 'SSSE3' -HW_CPU_X86_SSE41 = _CPU_X86_NS + 'SSE41' -HW_CPU_X86_SSE42 = _CPU_X86_NS + 'SSE42' -HW_CPU_X86_SSE4A = _CPU_X86_NS + 'SSE4A' -HW_CPU_X86_XOP = _CPU_X86_NS + 'XOP' -HW_CPU_X86_3DNOW = _CPU_X86_NS + '3DNOW' -# ref: https://en.wikipedia.org/wiki/AVX-512 -HW_CPU_X86_AVX512F = _CPU_X86_NS + 'AVX512F' # foundation -HW_CPU_X86_AVX512CD = _CPU_X86_NS + 'AVX512CD' # conflict detection -HW_CPU_X86_AVX512PF = _CPU_X86_NS + 'AVX512PF' # prefetch -HW_CPU_X86_AVX512ER = _CPU_X86_NS + 'AVX512ER' # exponential + reciprocal -HW_CPU_X86_AVX512VL = _CPU_X86_NS + 'AVX512VL' # vector length extensions -HW_CPU_X86_AVX512BW = _CPU_X86_NS + 'AVX512BW' # byte + word -HW_CPU_X86_AVX512DQ = _CPU_X86_NS + 'AVX512DQ' # double word + quad word -# ref: https://en.wikipedia.org/wiki/Bit_Manipulation_Instruction_Sets -HW_CPU_X86_ABM = _CPU_X86_NS + 'ABM' -HW_CPU_X86_BMI = _CPU_X86_NS + 'BMI' -HW_CPU_X86_BMI2 = _CPU_X86_NS + 'BMI2' -HW_CPU_X86_TBM = _CPU_X86_NS + 'TBM' -# ref: https://en.wikipedia.org/wiki/AES_instruction_set -HW_CPU_X86_AESNI = _CPU_X86_NS + 'AES-NI' -# ref: https://en.wikipedia.org/wiki/Intel_SHA_extensions -HW_CPU_X86_SHA = _CPU_X86_NS + 'SHA' -# ref: https://en.wikipedia.org/wiki/Intel_MPX -HW_CPU_X86_MPX = _CPU_X86_NS + 'MPX' -# ref: https://en.wikipedia.org/wiki/Software_Guard_Extensions -HW_CPU_X86_SGX = _CPU_X86_NS + 'SGX' -# ref: https://en.wikipedia.org/wiki/Transactional_Synchronization_Extensions -HW_CPU_X86_TSX = _CPU_X86_NS + 'TSX' -# ref: https://en.wikipedia.org/wiki/Advanced_Synchronization_Facility -HW_CPU_X86_ASF = _CPU_X86_NS + 'ASF' -# ref: https://en.wikipedia.org/wiki/VT-x -HW_CPU_X86_VMX = _CPU_X86_NS + 'VMX' -# ref: https://en.wikipedia.org/wiki/AMD-V -HW_CPU_X86_SVM = _CPU_X86_NS + 'SVM' - -# All storage-specific features are prefixed with this namespace -_STORAGE_NS = 'STORAGE_' - -# All disk storage-specific features are prefixed with this namespace (as -# opposed to object storage) -_DISK_NS = _STORAGE_NS + 'DISK_' - -STORAGE_DISK_HDD = _DISK_NS + 'HDD' # spinning oxide -STORAGE_DISK_SSD = _DISK_NS + 'SSD' # solid-state disks - -NAMESPACES = { - 'CUSTOM': _CUSTOM_NS, - 'HARDWARE': _HW_NS, - 'HW': _HW_NS, - 'CPU': _CPU_NS, - 'X86': _CPU_X86_NS, - 'STORAGE': _STORAGE_NS, - 'DISK': _DISK_NS, -} diff --git a/os_traits/hw/__init__.py b/os_traits/hw/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/os_traits/hw/cpu/__init__.py b/os_traits/hw/cpu/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/os_traits/hw/cpu/x86.py b/os_traits/hw/cpu/x86.py new file mode 100644 index 0000000..7d5df6e --- /dev/null +++ b/os_traits/hw/cpu/x86.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- + +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from os_traits import utils + +register = utils.register_fn(__name__) + +# ref: https://en.wikipedia.org/wiki/Streaming_SIMD_Extensions +register('AVX') +register('AVX2') +register('CLMUL') +register('FMA3') +register('FMA4') +register('F16C') +register('MMX') +register('SSE') +register('SSE2') +register('SSE3') +register('SSSE3') +register('SSE41') +register('SSE42') +register('SSE4A') +register('XOP') +register('3DNOW') +# ref: https://en.wikipedia.org/wiki/AVX-512 +register('AVX512F') # foundation +register('AVX512CD') # conflict detection +register('AVX512PF') # prefetch +register('AVX512ER') # exponential + reciprocal +register('AVX512VL') # vector length extensions +register('AVX512BW') # byte + word +register('AVX512DQ') # double word + quad word +# ref: https://en.wikipedia.org/wiki/Bit_Manipulation_Instruction_Sets +register('ABM') +register('BMI') +register('BMI2') +register('TBM') +# ref: https://en.wikipedia.org/wiki/AES_instruction_set +register('AES-NI') +# ref: https://en.wikipedia.org/wiki/Intel_SHA_extensions +register('SHA') +# ref: https://en.wikipedia.org/wiki/Intel_MPX +register('MPX') +# ref: https://en.wikipedia.org/wiki/Software_Guard_Extensions +register('SGX') +# ref: https://en.wikipedia.org/wiki/Transactional_Synchronization_Extensions +register('TSX') +# ref: https://en.wikipedia.org/wiki/Advanced_Synchronization_Facility +register('ASF') +# ref: https://en.wikipedia.org/wiki/VT-x +register('VMX') +# ref: https://en.wikipedia.org/wiki/AMD-V +register('SVM') diff --git a/os_traits/storage/__init__.py b/os_traits/storage/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/os_traits/storage/disk.py b/os_traits/storage/disk.py new file mode 100644 index 0000000..87709dd --- /dev/null +++ b/os_traits/storage/disk.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- + +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from os_traits import utils + +register = utils.register_fn(__name__) + + +register('HDD') # spinning oxide +register('SSD') # solid-state disks diff --git a/os_traits/tests/test_os_traits.py b/os_traits/tests/test_os_traits.py index 8c14105..d84a5b5 100644 --- a/os_traits/tests/test_os_traits.py +++ b/os_traits/tests/test_os_traits.py @@ -12,37 +12,33 @@ # License for the specific language governing permissions and limitations # under the License. -""" -test_os_traits ----------------------------------- - -Tests for `os_traits` module. -""" - import os_traits as ot +from os_traits.hw.cpu import x86 from os_traits.tests import base -class TestOs_traits(base.TestCase): +class TestSymbols(base.TestCase): def test_trait(self): + """Simply tests that the constants from submodules are imported into + the primary os_traits module space. + """ trait = ot.HW_CPU_X86_SSE42 self.assertEqual("HW_CPU_X86_SSE42", trait) + # And the "leaf-module" namespace... + self.assertEqual(x86.SSE42, ot.HW_CPU_X86_SSE42) + def test_get_symbol_names(self): names = ot.get_symbol_names() self.assertIn("HW_CPU_X86_AVX2", names) self.assertIn("STORAGE_DISK_SSD", names) - def test_namespaces(self): - namespaces = ot.NAMESPACES - self.assertIn(("HARDWARE", "HW_"), namespaces.items()) - self.assertEqual(7, len(namespaces)) - def test_get_traits(self): - traits = ot.get_traits(ot.NAMESPACES['X86']) + traits = ot.get_traits('HW_CPU') self.assertIn("HW_CPU_X86_SSE42", traits) - self.assertEqual(35, len(traits)) + self.assertIn(ot.HW_CPU_X86_AVX2, traits) + self.assertNotIn(ot.STORAGE_DISK_SSD, traits) def test_check_traits(self): traits = set(["HW_CPU_X86_SSE42", "HW_CPU_X86_XOP"]) diff --git a/os_traits/utils.py b/os_traits/utils.py new file mode 100644 index 0000000..1e8bb50 --- /dev/null +++ b/os_traits/utils.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import functools +import sys + +import os_traits + + +def symbolize(mod_name, name): + """Given a reference to a Python module object and a short string name for + a trait, registers a symbol in the module that corresponds to the full + namespaced trait name. + + For example, if called like so: + + :code: + + # In file /os_traits/hw/cpu/x86.py + + import functools + + from os_traits import utils + + mod_register = functools.partial(utils.symbolize, __name__) + + mod_register('AVX2') + mod_register('SSE') + + Would end up creating the following symbols: + + os_traits.hw.cpu.x86.AVX2 with the value of 'HW_CPU_X86_AVX2' + os_traits.hw.cpu.x86.SSE with the value of 'HW_CPU_X86_SSE' + os_traits.HW_CPU_X86_AVX2 with the value of 'HW_CPU_X86_AVX2' + os_traits.HW_CPU_X86_SSE with the value of 'HW_CPU_X86_SSE' + """ + leaf_mod = sys.modules[mod_name] + value_base = '_'.join([m.upper() for m in mod_name.split('.')[1:]]) + value = value_base + '_' + name.upper() + setattr(os_traits, value, value) # os_traits.HW_CPU_X86_SSE + setattr(leaf_mod, name.upper(), value) # os_traits.hw.cpu.x86.SSE + + +def register_fn(mod_name): + return functools.partial(symbolize, mod_name)