Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c320a4a
cElementTree is long deprecated.
Mab879 Oct 31, 2025
18eef84
Remove unicode_func
Mab879 Oct 31, 2025
318d6a5
Remove this try catch for Queue as this a Python 2ism
Mab879 Oct 31, 2025
5861b15
Remove legacy import for urllib quote
Mab879 Oct 31, 2025
5bccb5b
Move to shlex shell_quote
Mab879 Oct 31, 2025
c19e068
Fix typing syntax error in ssg/controls.py
Mab879 Oct 31, 2025
b53238b
Fix types for XCCDFEntity keys
Mab879 Oct 31, 2025
cf48916
Be honest about global variable hack for Jinja Enviroment
Mab879 Oct 31, 2025
3459d7c
Ignore yaml loader and dumper import errors
Mab879 Oct 31, 2025
9a1c473
Fix mypy namedtuple naming convention errors
Mab879 Oct 31, 2025
97759f5
Add typing info for optional FileLinker attributes
Mab879 Oct 31, 2025
f25fac9
Add type hints for CCE_POOLS
Mab879 Oct 31, 2025
57994c8
Remove Python 2.6 hack for ET namespaces
Mab879 Oct 31, 2025
2b50c98
Type clean up in ssg/variables.py
Mab879 Oct 31, 2025
423c02d
Remove Python 2 hacks in ssg/ext/boolean/boolean.py
Mab879 Oct 31, 2025
7ca3031
Type clean up in ssg/ext/boolean/boolean.py
Mab879 Oct 31, 2025
5ed930b
Just ignore the double assignment in ssg/ext/boolean/boolean.py
Mab879 Oct 31, 2025
7e5b855
Remove Python 2 hack and add type hints to ssg.templates.load_module
Mab879 Oct 31, 2025
1d33675
Type clean up in load_module
Mab879 Oct 31, 2025
ad4bb85
Add type to ssg.products.load_product_yaml
Mab879 Oct 31, 2025
29c8622
Remove return in finally in ssg/xml.py
Mab879 Oct 31, 2025
6f0301a
Skip typing get for importlib.util seems type checker doesn't have in…
Mab879 Oct 31, 2025
1da84ae
Add ssg to mypy tests
Mab879 Oct 31, 2025
c95f151
Fix type for older python
Mab879 Oct 31, 2025
7478562
Add better return type for ssg.variables._convert_defaultdict_to_dict
Mab879 Nov 3, 2025
60bead6
Use dict/tuple literals
Mab879 Nov 3, 2025
e26c871
Remove unused typing imports
Mab879 Nov 3, 2025
8f4cf02
Fix return type on ssg.profiles._get_extended_profile_path
Mab879 Nov 3, 2025
54aea13
fix pkg_resources
Mab879 Nov 3, 2025
edb34f5
Fix type hint for policies in ControlsManager
Mab879 Nov 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,7 @@ git_describe_command = ["sh", "-c", "tag=$(git tag | grep -v '-' | sort | tail -

[tool.setuptools.packages.find]
include = ["ssg*"]

[[tool.mypy.overrides]]
module = "pkg_resources"
ignore_missing_imports = true
6 changes: 3 additions & 3 deletions ssg/build_cpe.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from __future__ import print_function
import os
import sys
import ssg.id_translate

import ssg.id_translate
from .constants import oval_namespace
from .constants import PREFIX_TO_NS
from .utils import required_key, apply_formatting_on_dict_values
Expand Down Expand Up @@ -207,9 +207,9 @@ class CPEItem(XCCDFEntity, Templatable):
)
KEYS.update(**Templatable.KEYS)

MANDATORY_KEYS = [
MANDATORY_KEYS = {
"name",
]
}

prefix = "cpe-dict"
ns = PREFIX_TO_NS[prefix]
Expand Down
2 changes: 1 addition & 1 deletion ssg/build_remediations.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
'strategy']
REMEDIATION_ELM_KEYS = ['complexity', 'disruption', 'reboot', 'strategy']

RemediationObject = namedtuple('remediation', ['contents', 'config'])
RemediationObject = namedtuple('RemediationObject', ['contents', 'config'])


def is_supported_filename(remediation_type, filename):
Expand Down
6 changes: 3 additions & 3 deletions ssg/build_renumber.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from __future__ import print_function
import sys
import os

from typing import Optional

from .constants import (
OSCAP_RULE, OSCAP_VALUE, oval_namespace, XCCDF12_NS, cce_uri, ocil_cs,
Expand All @@ -26,8 +26,8 @@ class FileLinker(object):
Bass class which represents the linking of checks to their identifiers.
"""

CHECK_SYSTEM = None
CHECK_NAMESPACE = None
CHECK_SYSTEM: Optional[str] = None
CHECK_NAMESPACE: Optional[str] = None

def __init__(self, translator, xccdftree, checks, output_file_name):
self.translator = translator
Expand Down
4 changes: 2 additions & 2 deletions ssg/build_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -3426,13 +3426,13 @@ class Platform(XCCDFEntity):
** XCCDFEntity.KEYS
)

MANDATORY_KEYS = [
MANDATORY_KEYS = {
"name",
"xml_content",
"original_expression",
"bash_conditional",
"ansible_conditional"
]
}

prefix = "cpe-lang"
ns = PREFIX_TO_NS[prefix]
Expand Down
5 changes: 2 additions & 3 deletions ssg/cce.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
import re
import random
import os


CCE_POOLS = dict()
from typing import Dict, Type


class CCEFile:
Expand Down Expand Up @@ -136,6 +134,7 @@ def absolute_path(self):
return os.path.join(self.project_root, "shared", "references", "cce-sle15-avail.txt")


CCE_POOLS: Dict[str, Type[CCEFile]] = {}
CCE_POOLS["redhat"] = RedhatCCEFile
CCE_POOLS["sle12"] = SLE12CCEFile
CCE_POOLS["sle15"] = SLE15CCEFile
Expand Down
6 changes: 3 additions & 3 deletions ssg/controls.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import copy
import sys
from glob import glob
from typing import List, Dict
from typing import Dict, List, Set

import ssg.entities.common
import ssg.yaml
Expand Down Expand Up @@ -144,7 +144,7 @@ class Control(ssg.entities.common.SelectionHandler, ssg.entities.common.XCCDFEnt
description=str,
rationale=str,
automated=str,
status=None,
status=lambda: None,
mitigation=str,
artifact_description=str,
status_justification=str,
Expand Down Expand Up @@ -812,7 +812,7 @@ def __init__(self, controls_dirs: List[str], env_yaml=None, existing_rules=None)
self.controls_dirs = [os.path.abspath(controls_dir) for controls_dir in controls_dirs]
self.env_yaml = env_yaml
self.existing_rules = existing_rules
self.policies = {}
self.policies: Dict = {}

def _load(self, format):
for controls_dir in self.controls_dirs:
Expand Down
10 changes: 5 additions & 5 deletions ssg/entities/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
import yaml
from collections import defaultdict
from copy import deepcopy
from typing import Set, Dict, Callable, Any, Optional

from ssg.yaml import yaml_Dumper

from ..xml import ElementTree as ET, add_xhtml_namespace
from ..yaml import DocumentationNotComplete, open_and_expand
from ..shims import unicode_func

from ..constants import (
xhtml_namespace,
Expand Down Expand Up @@ -112,7 +112,7 @@ def add_sub_element(parent, tag, ns, data):
# and therefore it does not add child elements
# we need to do a hack instead
# TODO: Remove this function after we move to Markdown everywhere in SSG
ustr = unicode_func('<{0} xmlns="{3}" xmlns:xhtml="{2}">{1}</{0}>').format(
ustr = str('<{0} xmlns="{3}" xmlns:xhtml="{2}">{1}</{0}>').format(
tag, namespaced_data, xhtml_namespace, ns)

try:
Expand Down Expand Up @@ -156,15 +156,15 @@ class XCCDFEntity(object):
when entities are defined in the benchmark tree,
and they are compiled into flat YAMLs to the build directory.
"""
KEYS = dict(
KEYS: Dict[str, Callable[[], Optional[Any]]] = dict(
id_=lambda: "",
title=lambda: "",
definition_location=lambda: "",
)

MANDATORY_KEYS = set()
MANDATORY_KEYS: Set[str] = set()

ALTERNATIVE_KEYS = dict()
ALTERNATIVE_KEYS: Dict[str, str] = {}

GENERIC_FILENAME = ""
ID_LABEL = "id"
Expand Down
41 changes: 15 additions & 26 deletions ssg/ext/boolean/boolean.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,8 @@
from operator import and_ as and_operator
from operator import or_ as or_operator

# Python 2 and 3
try:
basestring # NOQA
except NameError:
basestring = str # NOQA

# Python 2 and 3
try:
# Python 2
reduce # NOQA
except NameError:
# Python 3
from functools import reduce # NOQA
from functools import reduce
from typing import Optional, Any

# Set to True to enable tracing for parsing
TRACE_PARSE = False
Expand Down Expand Up @@ -208,7 +197,7 @@ def parse(self, expr, simplify=False):

precedence = {self.NOT: 5, self.AND: 10, self.OR: 15, TOKEN_LPAR: 20}

if isinstance(expr, basestring):
if isinstance(expr, str):
tokenized = self.tokenize(expr)
else:
tokenized = iter(expr)
Expand Down Expand Up @@ -445,7 +434,7 @@ def tokenize(self, expr):
- True symbols: 1 and True
- False symbols: 0, False and None
"""
if not isinstance(expr, basestring):
if not isinstance(expr, str):
raise TypeError('expr must be string but it is %s.' % type(expr))

# mapping of lowercase token strings to a token type id for the standard
Expand Down Expand Up @@ -556,17 +545,17 @@ class Expression(object):
variable symbols.
"""
# Defines sort and comparison order between expressions arguments
sort_order = None
sort_order: Optional[int] = None

# Store arguments aka. subterms of this expressions.
# subterms are either literals or expressions.
args = tuple()
args: Any = ()

# True is this is a literal expression such as a Symbol, TRUE or FALSE
isliteral = False
isliteral: bool = False

# True if this expression has been simplified to in canonical form.
iscanonical = False
iscanonical: bool = False

# these class attributes are configured when a new BooleanAlgebra is created
TRUE = None
Expand Down Expand Up @@ -809,7 +798,7 @@ def __lt__(self, other):
return self == self.FALSE
return NotImplemented

__nonzero__ = __bool__ = lambda s: None
__nonzero__ = __bool__ = lambda s: None # type: ignore

def pretty(self, indent=0, debug=False):
"""
Expand Down Expand Up @@ -843,7 +832,7 @@ def __repr__(self):
def __call__(self):
return self

__nonzero__ = __bool__ = lambda s: True
__nonzero__ = __bool__ = lambda s: True # type: ignore


class _FALSE(BaseElement):
Expand Down Expand Up @@ -871,7 +860,7 @@ def __repr__(self):
def __call__(self):
return self

__nonzero__ = __bool__ = lambda s: False
__nonzero__ = __bool__ = lambda s: False # type: ignore


class Symbol(Expression):
Expand Down Expand Up @@ -920,7 +909,7 @@ def __str__(self):
return str(self.obj)

def __repr__(self):
obj = "'%s'" % self.obj if isinstance(self.obj, basestring) else repr(self.obj)
obj = "'%s'" % self.obj if isinstance(self.obj, str) else repr(self.obj)
return '%s(%s)' % (self.__class__.__name__, obj)

def pretty(self, indent=0, debug=False):
Expand All @@ -931,7 +920,7 @@ def pretty(self, indent=0, debug=False):
if debug:
debug_details += '<isliteral=%r, iscanonical=%r>' % (self.isliteral, self.iscanonical)

obj = "'%s'" % self.obj if isinstance(self.obj, basestring) else repr(self.obj)
obj = "'%s'" % self.obj if isinstance(self.obj, str) else repr(self.obj)
return (' ' * indent) + ('%s(%s%s)' % (self.__class__.__name__, debug_details, obj))


Expand Down Expand Up @@ -1470,7 +1459,7 @@ class AND(DualBase):
"""

sort_order = 10
_pyoperator = and_operator
_pyoperator = and_operator # type: ignore

def __init__(self, arg1, arg2, *args):
super(AND, self).__init__(arg1, arg2, *args)
Expand All @@ -1496,7 +1485,7 @@ class OR(DualBase):
"""

sort_order = 25
_pyoperator = or_operator
_pyoperator = or_operator # type: ignore

def __init__(self, arg1, arg2, *args):
super(OR, self).__init__(arg1, arg2, *args)
Expand Down
45 changes: 20 additions & 25 deletions ssg/jinja.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,8 @@
import sys
import jinja2

try:
from urllib.parse import quote
except ImportError:
from urllib import quote

try:
from shlex import quote as shell_quote
except ImportError:
from pipes import quote as shell_quote
from urllib.parse import quote
from shlex import quote as shell_quote

from .constants import JINJA_MACROS_DIRECTORY
from .utils import (required_key,
Expand Down Expand Up @@ -126,6 +119,10 @@ def __init__(self, bytecode_cache=None):
)


# Module-level cached environment for jinja environment
_jinja_env = None


def _get_jinja_environment(substitutions_dict):
"""
Initializes and returns a Jinja2 Environment with custom settings and filters.
Expand All @@ -145,30 +142,28 @@ def _get_jinja_environment(substitutions_dict):
Returns:
jinja2.Environment: The configured Jinja2 Environment instance.
"""
if _get_jinja_environment.env is None:
global _jinja_env
if _jinja_env is None:
bytecode_cache = None
if substitutions_dict.get("jinja2_cache_enabled") == "true":
bytecode_cache = jinja2.FileSystemBytecodeCache(
required_key(substitutions_dict, "jinja2_cache_dir")
)

# TODO: Choose better syntax?
_get_jinja_environment.env = JinjaEnvironment(bytecode_cache=bytecode_cache)
_jinja_env = JinjaEnvironment(bytecode_cache=bytecode_cache)
add_python_functions(substitutions_dict)
_get_jinja_environment.env.filters['banner_anchor_wrap'] = banner_anchor_wrap
_get_jinja_environment.env.filters['banner_regexify'] = banner_regexify
_get_jinja_environment.env.filters['escape_id'] = escape_id
_get_jinja_environment.env.filters['escape_regex'] = escape_regex
_get_jinja_environment.env.filters['escape_yaml_key'] = escape_yaml_key
_get_jinja_environment.env.filters['quote'] = shell_quote
_get_jinja_environment.env.filters['sha256'] = sha256
_get_jinja_environment.env.globals.update(substitutions_dict)
preload_macros(_get_jinja_environment.env)

return _get_jinja_environment.env


_get_jinja_environment.env = None
_jinja_env.filters['banner_anchor_wrap'] = banner_anchor_wrap
_jinja_env.filters['banner_regexify'] = banner_regexify
_jinja_env.filters['escape_id'] = escape_id
_jinja_env.filters['escape_regex'] = escape_regex
_jinja_env.filters['escape_yaml_key'] = escape_yaml_key
_jinja_env.filters['quote'] = shell_quote
_jinja_env.filters['sha256'] = sha256
_jinja_env.globals.update(substitutions_dict)
preload_macros(_jinja_env)

return _jinja_env


def initialize(substitutions_dict):
Expand Down
9 changes: 2 additions & 7 deletions ssg/oval.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,8 @@

ASSUMED_OVAL_VERSION_STRING = "5.11"
# globals, to make recursion easier in case we encounter extend_definition
try:
ET.register_namespace("oval", ovalns)
except AttributeError:
# Legacy Python 2.6 fix, see e.g.
# https://www.programcreek.com/python/example/57552/xml.etree.ElementTree._namespace_map
from xml.etree import ElementTree as ET
ET._namespace_map[ovalns] = "oval"
ET.register_namespace("oval", ovalns)



def applicable_platforms(oval_file, oval_version_string=None):
Expand Down
2 changes: 1 addition & 1 deletion ssg/products.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ def read_properties_from_directory(self, path):
self.expand_by_acquired_data(new_symbols)


def load_product_yaml(product_yaml_path):
def load_product_yaml(product_yaml_path: str) -> Product:
"""
Reads a product data from disk and returns it.

Expand Down
Loading
Loading