Utilities

Key Normalization

hfortix_core.utils.normalize_keys(data)[source]

Recursively normalize dictionary keys from hyphen to underscore format.

FortiOS API returns keys with hyphens (e.g., ‘tcp-portrange’), but Python identifiers cannot contain hyphens. This function converts all keys to use underscores (e.g., ‘tcp_portrange’) to match TypedDict definitions.

Parameters:

data (Any) – Data to normalize (dict, list, or other types)

Return type:

Any

Returns:

Normalized data with hyphenated keys converted to underscored keys

Examples

>>> normalize_keys({"tcp-portrange": "8080", "name": "test"})
{"tcp_portrange": "8080", "name": "test"}
>>> normalize_keys([{"srcaddr": [{"name": "test-addr"}]}])
[{"srcaddr": [{"name": "test-addr"}]}]

Deprecation Warnings

hfortix_core.check_deprecated_fields(payload, deprecated_fields, endpoint)[source]

Check payload for deprecated fields and emit warnings.

Parameters:
  • payload (dict[str, Any]) – The data payload to check

  • deprecated_fields (dict[str, dict[str, str]]) –

    Dict mapping field names to deprecation info Format: {

    ”field_name”: {

    “reason”: “…”, “alternative”: “…”, “removal_version”: “…”

    }

    }

  • endpoint (str) – API endpoint path

Return type:

None

hfortix_core.warn_deprecated_field(field_name, endpoint, reason=None, alternative=None, removal_version=None)[source]

Emit a deprecation warning for a field.

Parameters:
  • field_name (str) – Name of the deprecated field

  • endpoint (str) – API endpoint path (e.g., “firewall/address”)

  • reason (str | None) – Optional reason for deprecation

  • alternative (str | None) – Optional suggested alternative field

  • removal_version (str | None) – Optional version when field will be removed

Return type:

None

Caching Internals

class hfortix_core.cache.CacheEntry(value, ttl_seconds)[source]

Bases: Generic[T]

A cache entry with expiration time.

Parameters:
  • value (T)

  • ttl_seconds (float)

__init__(value, ttl_seconds)[source]

Initialize cache entry.

Parameters:
  • value (TypeVar(T)) – The cached value

  • ttl_seconds (float) – Time to live in seconds

is_expired()[source]

Check if entry has expired.

Return type:

bool

Formatting Module

The fmt module provides utilities for formatting and handling data structures.

Data formatting utilities for FortiOS objects and data structures.

Provides simple, type-agnostic conversion functions that handle any input gracefully. Never raises exceptions - returns sensible defaults for edge cases.

hfortix_core.fmt.to_json(data, indent=2, **kwargs)[source]

Convert any data to formatted JSON string.

Handles objects with __dict__, converts sets/tuples to lists, and uses str() fallback for non-serializable types.

Parameters:
  • data (Any) – Any Python object to convert to JSON

  • indent (int) – Number of spaces for indentation (default: 2)

  • **kwargs (Any) – Additional arguments passed to json.dumps()

Return type:

str

Returns:

Formatted JSON string

hfortix_core.fmt.to_csv(data, separator=', ')[source]

Convert any data to comma-separated string.

Parameters:
  • data (Any) – Any Python object to convert

  • separator (str) – String to use between items (default: ‘, ‘)

Return type:

str

Returns:

Comma-separated string

Examples

>>> to_csv(['port1', 'port2', 'port3'])
'port1, port2, port3'
>>> to_csv({'x': 1, 'y': 2, 'z': 3})
'x=1, y=2, z=3'
>>> to_csv('already a string')
'already a string'
>>> to_csv(None)
''
>>> to_csv([1, 2, 3], separator=' | ')
'1 | 2 | 3'
>>> class Interface:
...     def __init__(self):
...         self.name = "port1"
...         self.ip = "10.0.0.1"
>>> to_csv(Interface())
'name=port1, ip=10.0.0.1'
hfortix_core.fmt.to_dict(data)[source]

Convert any data to dictionary.

Returns a dict with string keys for most inputs (objects, existing dicts), or integer keys for list/tuple inputs.

Parameters:

data (Any) – Any Python object to convert

Return type:

dict

Returns:

Dictionary representation of the data

Examples

>>> class Policy:
...     def __init__(self):
...         self.name = "Allow-All"
...         self.action = "accept"
>>> to_dict(Policy())
{'name': 'Allow-All', 'action': 'accept'}
>>> to_dict({'already': 'a dict'})
{'already': 'a dict'}
>>> to_dict([('a', 1), ('b', 2)])
{'a': 1, 'b': 2}
>>> to_dict(['x', 'y', 'z'])
{0: 'x', 1: 'y', 2: 'z'}
>>> to_dict('simple string')
{'value': 'simple string'}
>>> to_dict(None)
{'value': None}
hfortix_core.fmt.to_multiline(data, separator='\\n')[source]

Convert any data to newline-separated string.

Parameters:
  • data (Any) – Any Python object to convert

  • separator (str) – String to use between lines (default: ‘n’)

Return type:

str

Returns:

Newline-separated string

Examples

>>> print(to_multiline(['port1', 'port2', 'port3']))
port1
port2
port3
>>> print(to_multiline({'name': 'policy1', 'action': 'accept'}))
name: policy1
action: accept
>>> to_multiline('already a string')
'already a string'
>>> to_multiline(None)
''
>>> class Policy:
...     def __init__(self):
...         self.name = "Allow-All"
...         self.policyid = 1
>>> print(to_multiline(Policy()))
name: Allow-All
policyid: 1
hfortix_core.fmt.to_list(data, delimiter=None)[source]

Convert any data to list.

Parameters:
  • data (Any) – Any Python object to convert

  • delimiter (str | None) – If data is a string, split by this delimiter. If None and data is string with spaces, auto-splits by space. Common delimiters: ‘,’, ‘ ‘, ‘|’, ‘;’, etc.

Return type:

list[Any]

Returns:

List representation of the data

Examples

>>> to_list(['already', 'a', 'list'])
['already', 'a', 'list']
>>> to_list(('tuple', 'to', 'list'))
['tuple', 'to', 'list']
>>> to_list({'a', 'b', 'c'})  # set to list
['a', 'b', 'c']
>>> to_list('port1,port2,port3', delimiter=',')
['port1', 'port2', 'port3']
>>> to_list('port1 port2 port3')  # auto-splits on space
['port1', 'port2', 'port3']
>>> to_list('80 443 8080')  # works with numbers as strings
['80', '443', '8080']
>>> to_list('port1 | port2 | port3', delimiter=' | ')
['port1', 'port2', 'port3']
>>> to_list('single_string')  # no spaces, returns as-is
['single_string']
>>> to_list({'name': 'policy1', 'action': 'accept'})
['policy1', 'accept']
>>> to_list(None)
[]
>>> to_list(42)
[42]
>>> class Policy:
...     def __init__(self):
...         self.name = "Allow-All"
...         self.policyid = 1
>>> to_list(Policy())
['Allow-All', 1]
hfortix_core.fmt.to_quoted(data, quote='"', separator=', ')[source]

Convert any data to quoted string representation.

Parameters:
  • data (Any) – Any Python object to convert

  • quote (str) – Quote character to use (default: ‘”’)

  • separator (str) – String to use between quoted items (default: ‘, ‘)

Return type:

str

Returns:

Quoted string representation

Examples

>>> to_quoted(['port1', 'port2', 'port3'])
'"port1", "port2", "port3"'
>>> to_quoted({'x': 1, 'y': 2})
'"x", "y"'
>>> to_quoted('hello')
'"hello"'
>>> to_quoted(None)
'""'
>>> to_quoted([1, 2, 3], quote="'")
"'1', '2', '3'"
>>> class Interface:
...     def __init__(self):
...         self.name = "port1"
...         self.vlan = 10
>>> to_quoted(Interface())
'"name", "vlan"'
hfortix_core.fmt.to_table(data, headers=True, delimiter=' | ')[source]

Convert data to table format.

Parameters:
  • data (Any) – Any Python object to convert (list of dicts, list of objects, etc.)

  • headers (bool) – Whether to include headers (default: True)

  • delimiter (str) – Column delimiter (default: ‘ | ‘)

Return type:

str

Returns:

Table-formatted string

Examples

>>> policies = [
...     {'name': 'Allow-Web', 'action': 'accept', 'policyid': 1},
...     {'name': 'Block-All', 'action': 'deny', 'policyid': 2}
... ]
>>> print(to_table(policies))
name | action | policyid
Allow-Web | accept | 1
Block-All | deny | 2
>>> to_table(policies, headers=False)
'Allow-Web | accept | 1\nBlock-All | deny | 2'
>>> to_table(policies, delimiter=' || ')
'name || action || policyid\nAllow-Web || accept || 1\nBlock-All || deny || 2'
hfortix_core.fmt.to_yaml(data, indent=2)[source]

Convert data to YAML-like format (simple, no external dependencies).

Parameters:
  • data (Any) – Any Python object to convert

  • indent (int) – Number of spaces for indentation (default: 2)

Return type:

str

Returns:

YAML-style string

Examples

>>> policy = {'name': 'Allow-Web', 'action': 'accept', 'srcintf': ['port1', 'port2']}
>>> print(to_yaml(policy))
name: Allow-Web
action: accept
srcintf:
  - port1
  - port2
>>> print(to_yaml({'nested': {'key': 'value'}}))
nested:
  key: value
hfortix_core.fmt.to_xml(data, root='data', indent=2)[source]

Convert data to simple XML format (no external dependencies).

Parameters:
  • data (Any) – Any Python object to convert

  • root (str) – Root element name (default: ‘data’)

  • indent (int) – Number of spaces for indentation (default: 2)

Return type:

str

Returns:

XML string

Examples

>>> policy = {'name': 'Allow-Web', 'policyid': 1}
>>> print(to_xml(policy, root='policy'))
<policy>
  <name>Allow-Web</name>
  <policyid>1</policyid>
</policy>
>>> policies = [{'name': 'p1'}, {'name': 'p2'}]
>>> print(to_xml(policies, root='policies'))
<policies>
  <item>
    <name>p1</name>
  </item>
  <item>
    <name>p2</name>
  </item>
</policies>
hfortix_core.fmt.to_key_value(data, separator='=', delimiter='\\n')[source]

Convert data to key=value pairs format.

Parameters:
  • data (Any) – Any Python object to convert

  • separator (str) – Separator between key and value (default: ‘=’)

  • delimiter (str) – Delimiter between pairs (default: ‘n’)

Return type:

str

Returns:

Key-value pairs string

Examples

>>> config = {'host': '192.168.1.1', 'port': 443, 'verify': False}
>>> print(to_key_value(config))
host=192.168.1.1
port=443
verify=False
>>> to_key_value(config, separator=': ', delimiter='; ')
'host: 192.168.1.1; port: 443; verify: False'
hfortix_core.fmt.to_markdown_table(data)[source]

Convert data to Markdown table format.

Parameters:

data (Any) – List of dicts or list of objects

Return type:

str

Returns:

Markdown table string

Examples

>>> policies = [
...     {'name': 'Allow-Web', 'action': 'accept'},
...     {'name': 'Block-All', 'action': 'deny'}
... ]
>>> print(to_markdown_table(policies))
| name | action |
| --- | --- |
| Allow-Web | accept |
| Block-All | deny |
hfortix_core.fmt.to_dictlist(data)[source]

Convert dict of lists to list of dicts (columnar to row format).

Useful for transforming columnar data into row-based records.

Parameters:

data (Any) – Dict where values are lists, or any convertible data

Return type:

list[dict[str, Any]]

Returns:

List of dicts where each dict is one row

Examples

>>> columnar = {'name': ['p1', 'p2'], 'action': ['accept', 'deny']}
>>> to_dictlist(columnar)
[{'name': 'p1', 'action': 'accept'}, {'name': 'p2', 'action': 'deny'}]
>>> to_dictlist({'ports': ['80', '443', '8080']})
[{'ports': '80'}, {'ports': '443'}, {'ports': '8080'}]
>>> # Already list of dicts - returns as-is
>>> to_dictlist([{'name': 'p1'}, {'name': 'p2'}])
[{'name': 'p1'}, {'name': 'p2'}]
>>> to_dictlist(None)
[]
hfortix_core.fmt.to_listdict(data)[source]

Convert list of dicts to dict of lists (row to columnar format).

Useful for transforming row-based records into columnar data.

Parameters:

data (Any) – List of dicts, list of objects, or any convertible data

Return type:

dict[str, list[Any]]

Returns:

Dict where keys are field names and values are lists

Examples

>>> rows = [{'name': 'p1', 'action': 'accept'}, {'name': 'p2', 'action': 'deny'}]
>>> to_listdict(rows)
{'name': ['p1', 'p2'], 'action': ['accept', 'deny']}
>>> to_listdict([{'ports': '80'}, {'ports': '443'}, {'ports': '8080'}])
{'ports': ['80', '443', '8080']}
>>> # Single dict becomes dict of single-item lists
>>> to_listdict({'name': 'p1', 'action': 'accept'})
{'name': ['p1'], 'action': ['accept']}
>>> to_listdict(None)
{}