Skip to content

Commit

Permalink
fix: don't use lexical sorting for version numbers in codegen
Browse files Browse the repository at this point in the history
Previously, python-libjuju iterated over schemas keyed by their version
string (e.g. '3.1.9') using lexical sorting. For a given facade version,
a definition in a higher versioned schema was intended to overwrite any
prior definition saved (see generate_facades function in facade.py).
With lexical sorting, '3.1.10' would be sorted in between '3.1.1' and
'3.1.2', which would not lead to the desired behaviour. This commit
fixes this problem by using a tuple of integers as the sorting key. A
special case is requried for the version string 'latest', and we use
(9000, 9000, 9000).
  • Loading branch information
james-garner-canonical committed Oct 18, 2024
1 parent 0e8c45f commit 337d749
Showing 1 changed file with 14 additions and 3 deletions.
17 changes: 14 additions & 3 deletions juju/client/facade.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from collections import defaultdict
from glob import glob
from pathlib import Path
from typing import Any, Mapping, Sequence, TypeVar
from typing import Any, Dict, List, Mapping, Sequence, Tuple, TypeVar

import typing_inspect

Expand Down Expand Up @@ -926,11 +926,22 @@ def generate_definitions(schemas):
return definitions


def generate_facades(schemas):
def sortable_schema_version(version_string: str) -> Tuple[int, int, int]:
"""Return a sorting key in the form (major, minor, micro) from a version string."""
# 'latest' is special cased in load_schemas and should come last
if version_string == 'latest':
return (9000, 9000, 9000)
# raise ValueError if string isn't in the format A.B.C
major, minor, micro = version_string.split('.')
# raise ValueError if major, minor, and micro aren't int strings
return (int(major), int(minor), int(micro))


def generate_facades(schemas: Dict[str, List[Schema]]) -> Dict[str, Dict[int, codegen.Capture]]:
captures = defaultdict(codegen.Capture)

# Build the Facade classes
for juju_version in sorted(schemas.keys()):
for juju_version in sorted(schemas.keys(), key=sortable_schema_version):
for schema in schemas[juju_version]:
cls, source = buildFacade(schema)
cls_name = "{}Facade".format(schema.name)
Expand Down

0 comments on commit 337d749

Please sign in to comment.