Automate the import of traits

The previous patch broke apart the single monolithic declaration of
traits into a branching directory structure. That was great, but it
added a lot of repetitive code to get the subpackages and submodules
into the proper namespace. This patch automates that for any file in the
tree that contains a 'TRAITS' property.

Change-Id: I904789cbec76d83a14e213ce6bb474c9967d588b
This commit is contained in:
EdLeafe 2017-04-05 20:11:02 +00:00
parent 842a43b515
commit 2eb278ce1b
9 changed files with 156 additions and 190 deletions

View File

@ -12,25 +12,57 @@
# License for the specific language governing permissions and limitations
# under the License.
import importlib
import pkgutil
import sys
import pbr.version
import six
__version__ = pbr.version.VersionInfo(
'os_traits').version_string()
this_name = __name__
this_lib = sys.modules[this_name]
__version__ = pbr.version.VersionInfo(this_name).version_string()
# 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.hw import nic # noqa
from os_traits.hw.nic import accel # noqa
from os_traits.hw.nic import dcb # noqa
from os_traits.hw.nic import offload # noqa
from os_traits.hw.nic import sriov # noqa
from os_traits.storage import disk # noqa
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.
"""
leaf_mod = sys.modules[mod_name]
value_base = '_'.join([m.upper() for m in mod_name.split('.')[1:]])
value = value_base + '_' + name.upper()
setattr(this_lib, value, value) # os_traits.HW_CPU_X86_SSE
setattr(leaf_mod, name.upper(), value) # os_traits.hw.cpu.x86.SSE
def import_submodules(package, recursive=True):
"""Import all submodules of a module, recursively, including subpackages
:param package: package (name or actual module)
:type package: str | module
:rtype: dict[str, types.ModuleType]
"""
if isinstance(package, str):
package = importlib.import_module(package)
for loader, name, is_pkg in pkgutil.walk_packages(package.__path__):
full_name = package.__name__ + '.' + name
test_dir = "%s.tests" % this_name
if test_dir in full_name:
continue
imported = importlib.import_module(full_name)
for prop in getattr(imported, "TRAITS", []):
symbolize(full_name, prop)
if recursive and is_pkg:
import_submodules(full_name)
# This is where the names defined in submodules are imported
import_submodules(sys.modules.get(__name__))
def get_symbol_names(prefix=None):
@ -39,11 +71,12 @@ def get_symbol_names(prefix=None):
:param prefix: Optional string prefix to filter by. e.g. 'HW_'
"""
prefix = prefix or ""
return [
k for k, v in sys.modules[__name__].__dict__.items()
if isinstance(v, six.string_types) and
not k.startswith('_') and
(prefix is None or v.startswith(prefix))
v.startswith(prefix)
]
@ -53,11 +86,12 @@ def get_traits(prefix=None):
:param prefix: Optional string prefix to filter by. e.g. 'HW_'
"""
prefix = prefix or ""
return [
v for k, v in sys.modules[__name__].__dict__.items()
if isinstance(v, six.string_types) and
not k.startswith('_') and
(prefix is None or v.startswith(prefix))
v.startswith(prefix)
]

View File

@ -12,53 +12,54 @@
# License for the specific language governing permissions and limitations
# under the License.
from os_traits import utils
register = utils.register_fn(__name__)
TRAITS = [
# ref: https://en.wikipedia.org/wiki/Streaming_SIMD_Extensions
'AVX',
'AVX2',
'CLMUL',
'FMA3',
'FMA4',
'F16C',
'MMX',
'SSE',
'SSE2',
'SSE3',
'SSSE3',
'SSE41',
'SSE42',
'SSE4A',
'XOP',
'3DNOW',
# 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')
# ref: https://en.wikipedia.org/wiki/AVX-512
'AVX512F', # foundation
'AVX512CD', # conflict detection
'AVX512PF', # prefetch
'AVX512ER', # exponential + reciprocal
'AVX512VL', # vector length extensions
'AVX512BW', # byte + word
'AVX512DQ', # double word + quad word
# ref: https://en.wikipedia.org/wiki/Bit_Manipulation_Instruction_Sets
'ABM',
'BMI',
'BMI2',
'TBM',
# ref: https://en.wikipedia.org/wiki/AES_instruction_set
'AES-NI',
# ref: https://en.wikipedia.org/wiki/Intel_SHA_extensions
'SHA',
# ref: https://en.wikipedia.org/wiki/Intel_MPX
'MPX',
# ref: https://en.wikipedia.org/wiki/Software_Guard_Extensions
'SGX',
# ref:
# https://en.wikipedia.org/wiki/Transactional_Synchronization_Extensions
'TSX',
# ref: https://en.wikipedia.org/wiki/Advanced_Synchronization_Facility
'ASF',
# ref: https://en.wikipedia.org/wiki/VT-x
'VMX',
# ref: https://en.wikipedia.org/wiki/AMD-V
'SVM',
]

View File

@ -12,14 +12,12 @@
# License for the specific language governing permissions and limitations
# under the License.
from os_traits import utils
register = utils.register_fn(__name__)
# A few generalized capabilities of some NICs
register('SRIOV') # NIC supports partitioning via SR-IOV
register('MULTIQUEUE') # >1 receive and transmit queues
register('VMDQ') # Virtual machine device queues
# Some NICs allow processing pipelines to be programmed via FPGAs embedded in
# the NIC itself...
register('PROGRAMMABLE_PIPELINE')
TRAITS = [
'SRIOV', # NIC supports partitioning via SR-IOV
'MULTIQUEUE', # >1 receive and transmit queues
'VMDQ', # Virtual machine device queues
# Some NICs allow processing pipelines to be programmed via FPGAs embedded
# in the NIC itself...
'PROGRAMMABLE_PIPELINE',
]

View File

@ -12,15 +12,13 @@
# License for the specific language governing permissions and limitations
# under the License.
from os_traits import utils
register = utils.register_fn(__name__)
register('SSL') # SSL crypto
register('IPSEC') # IP-Sec crypto
register('TLS') # TLS crypto
register('DIFFIEH') # Diffie-Hellmann crypto
register('RSA') # RSA crypto
register('ECC') # Eliptic Curve crypto
register('LZS') # LZS compression
register('DEFLATE') # Deflate compression
TRAITS = [
'SSL', # SSL crypto
'IPSEC', # IP-Sec crypto
'TLS', # TLS crypto
'DIFFIEH', # Diffie-Hellmann crypto
'RSA', # RSA crypto
'ECC', # Eliptic Curve crypto
'LZS', # LZS compression
'DEFLATE', # Deflate compression
]

View File

@ -12,13 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
from os_traits import utils
register = utils.register_fn(__name__)
# IEEE 802.1Qbb Priority-flow control
register('PFC')
# IEEE 802.1Qaz Enhanced Transmission Selection
register('ETS')
# IEEE 802.1Qau Quantized Congestion Notification
register('QCN')
TRAITS = [
# IEEE 802.1Qbb Priority-flow control
'PFC',
# IEEE 802.1Qaz Enhanced Transmission Selection
'ETS',
# IEEE 802.1Qau Quantized Congestion Notification
'QCN',
]

View File

@ -12,27 +12,25 @@
# License for the specific language governing permissions and limitations
# under the License.
from os_traits import utils
register = utils.register_fn(__name__)
register('TSO') # TCP segmentation
register('GRO') # Generic receive
register('GSO') # Generic segmentation
register('UFO') # UDP Fragmentation
register('LRO') # Large receive
register('LSO') # Large send
register('TCS') # TCP Checksum
register('UCS') # UDP Checksum
register('SCS') # SCTP Checksum
register('L2CRC') # Layer-2 CRC
register('FDF') # Intel Flow-Director Filter
register('RXVLAN') # VLAN receive tunnel segmentation
register('TXVLAN') # VLAN transmit tunnel segmentation
register('VXLAN') # VxLAN tunneling
register('GRE') # GRE tunneling
register('GENEVE') # Geneve tunneling
register('TXUDP') # UDP transmit tunnel segmentation
register('QINQ') # QinQ specification
register('RDMA') # remote direct memory access
register('RXHASH') # receive hashing
TRAITS = [
'TSO', # TCP segmentation
'GRO', # Generic receive
'GSO', # Generic segmentation
'UFO', # UDP Fragmentation
'LRO', # Large receive
'LSO', # Large send
'TCS', # TCP Checksum
'UCS', # UDP Checksum
'SCS', # SCTP Checksum
'L2CRC', # Layer-2 CRC
'FDF', # Intel Flow-Director Filter
'RXVLAN', # VLAN receive tunnel segmentation
'TXVLAN', # VLAN transmit tunnel segmentation
'VXLAN', # VxLAN tunneling
'GRE', # GRE tunneling
'GENEVE', # Geneve tunneling
'TXUDP', # UDP transmit tunnel segmentation
'QINQ', # QinQ specification
'RDMA', # remote direct memory access
'RXHASH', # receive hashing
]

View File

@ -12,14 +12,12 @@
# License for the specific language governing permissions and limitations
# under the License.
from os_traits import utils
register = utils.register_fn(__name__)
# The function (virtual or physical) can restrict transmit rates
register('QOS_TX')
# The function (virtual or physical) can restrict receive rates
register('QOS_RX')
# The function (virtual or physical) can set up multiple receive and transmit
# queues for receive-side scaling
register('MULTIQUEUE')
TRAITS = [
# Individual virtual functions can restrict transmit rates
'QOS_TX',
# Individual virtual functions can restrict receive rates
'QOS_RX',
# Individual virtual functions can set up multiple receive and transmit
# queues for receive-side scaling
'MULTIQUEUE',
]

View File

@ -12,10 +12,7 @@
# 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
TRAITS = [
'HDD', # spinning oxide
'SSD', # solid-state disks
]

View File

@ -1,56 +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.
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)