Skip to content

Conversation

@ross
Copy link

@ross ross commented Oct 16, 2025

As part of working through octodns/octodns#1315 I wanted to add support for <<: !include some-file.yaml and ran into the same problems as others: #632 and #814.

After a few false starts and unworkable ideas I landed on adding the ability to have pluggable flattening the same way that constructors are now. It's a fairly trivial change in the repo and I'm able to port the existing map and seq blocks over and have all the tests passing.

More interestingly it allows 3rd parties to add new flatteners, so in the case of !include I can do something like:

class IncludingLoader(SafeLoader):

    def construct_include(self, node):
        mark = self.get_mark()
        directory = dirname(mark.name)

        filename = join(directory, self.construct_scalar(node))

        with open(filename, 'r') as fh:
            return load(fh, self.__class__)

    def flatten_include(self, node):
        mark = self.get_mark()
        directory = dirname(mark.name)

        filename = join(directory, self.construct_scalar(node))

        with open(filename, 'r') as fh:
            yield compose(fh, self.__class__).value

IncludingLoader.add_constructor('!include', IncludingLoader.construct_include)
IncludingLoader.add_flattener('!include', IncludingLoader.flatten_include)

In the context of octoDNS that allows config like:

# octodns.yaml
...

_zones: &a
  first.com.:
    sources:
      - config
    targets:
      - out

zones:
  <<: *a

  <<: !include zones.yaml

  primary.com.:
    sources:
      - config
    processors:
      - ownership
    targets:
      - out
# zones.yaml
---
other.com.:
  sources:
    - config
  targets:
    - out

To work exactly as expected.

I'm out of time for now, but I plan to come back to this PR and look at adding specific tests around the ability to add custom flatteners and verify that the more complex versions of <<: work, i.e. arrays and custom flatterers in anchors.

Thoughts and suggestions welcomed.

@ingydotnet
Copy link
Member

Not specifically related to this PR, but I'd lean towards !load over !include unless it's already in heavy use.
That would be my current direction if we try to standardize around some kind of yaml stdlib.

@ingydotnet
Copy link
Member

Well, then again, if pyyaml offered a !load in the future, it wouldn't conflict with a custom !include. 🤷

@ross
Copy link
Author

ross commented Oct 16, 2025

I have no preference and haven't implemented anything "real" on the octoDNS side yet. Only testing out what I've been playing around with here. I've pushed up a test case for the simplest path. Looking at the details of supporting things like:

foo:
  <<: [!custom ..., !custom, ...]

Now as the current implementation doesn't support them. flatten_yaml_seq assumes each value item in the sequence is a MappingNode and doesn't "flatten" them.

@ross
Copy link
Author

ross commented Oct 16, 2025

Ok. Fixed the sequence case so that it will also handle custom flatteners. Was a trivial change and it actually works much more like map now so that's probably an added benefit. Test cases for the original handling of maps in sequences along with custom flatteners added as well.

Going to move this out of draft as I believe it's now at least to the point where it's ready for 👀 and 💭s

@ross ross marked this pull request as ready for review October 16, 2025 22:54
@ingydotnet
Copy link
Member

Out of time for today, but I'll try to follow up more tomorrow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants