Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support frameworks and manifests in ContentLoader #182

Merged
merged 5 commits into from
Oct 13, 2015

Conversation

robyoung
Copy link
Contributor

@robyoung robyoung commented Oct 9, 2015

As we move to handling multiple frameworks the ContentLoader needs to be able to support this. This commit changes the ContentLoader's role so that it is responsible for managing multiple manifests across multiple frameworks. Rather than creating multiple ContentLoader instances we create one, pointing it at the root content directory (digitalmarketplace-frameworks). On application startup we load the manifests we need and then get builders by framework slug and manifest name. If a manifest is not found either when loading or when getting a buidler we error with a ContentNotFound error and should fail fast.

Note that this changes read_yaml so that it raises an error if the file is not found. read_yaml only seems to be used by the content loader so this should not cause errors.

Example app change

At application startup

Old

existing_service_content = ContentLoader(
    'app/content/frameworks/g-cloud-6/manifests/edit_service.yml',
    'app/content/frameworks/g-cloud-6/questions/services/'
)
new_service_content = ContentLoader(
    'app/content/frameworks/g-cloud-7/manifests/edit_submission.yml',
    'app/content/frameworks/g-cloud-7/questions/services/'
)
declaration_content = ContentLoader(
    'app/content/frameworks/g-cloud-7/manifests/declaration.yml',
    'app/content/frameworks/g-cloud-7/questions/declaration/'
)

New

content_loader = ContentLoader('app/content')
content_loader.load_manifest('g-cloud-6', 'edit_service', 'services')
content_loader.load_manifest('g-cloud-7', 'edit_submission', 'services')
content_loader.load_manifest('g-cloud-7', 'declaration', 'declaration')

In the views

Old

content = declaration_content.get_builder()

New

content = content_loader.get_builder(framework_slug, 'declaration')

As we move to handling multiple frameworks the `ContentLoader` needs
to be able to support this. This commit changes the `ContentLoader`'s
role so that it is responsible for managing multiple manifests across
multiple frameworks. Rather than creating multiple `ContentLoader`
instances we create one, pointing it at the root content directory
(`digitalmarketplace-frameworks`). On application startup we load the
manifests we need and then get builders by framework slug and manifest
name. If a manifest is not found either when loading or when getting a
buidler we error with a `ContentNotFound` error and should fail fast.

Example:
```python
loader = ContentLoader('path/to/digitalmarketplace-frameworks')
loader.load_manifest('g-cloud-7', 'declaration', 'declaration')
loader.get_builder('g-cloud-7', 'declaration')
```

Note that this changes `read_yaml` so that it raises an error if the
file is not found. `read_yaml` only seems to be used by the content
loader so this should not cause errors.

def get_builder(self, framework_slug, manifest):
try:
return ContentBuilder(self._content[framework_slug][manifest])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I usually try to avoid defaultdicts since e.g. this will add a framework_slug key to _content whenever it's called with a missing slug. This might be not an issue for our use case, but I'd consider making load_manifest create framework keys explicitly

@quis
Copy link
Contributor

quis commented Oct 13, 2015

Got this working locally in the supplier app. Didn't encounter any problems. I think the level of sophistication is about right when we're still dealing with a low number of frameworks.

except KeyError:
raise ContentNotFoundError("Content not found for {} and {}".format(framework_slug, manifest))

def load_manifest(self, framework_slug, manifest, question_set):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd go with framework_slug, question_set, manifest argument order, since manifests can only cover questions from one question set, and this would highlight the hierarchical order

Thinking about this some more, manifests are tied to the framework/question sets anyway, maybe the manifest file should declare this dependency instead of it being externally added by ContentLoader

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@allait I like your second point, eg changing the manifest from this:

-
  name: Page 1
  editable: True
  questions:
    - example

to something like this:

questions_path: declaration
sections:
  -
    name: Page 1
    editable: True
    questions:
      - example

Not sure if it's something for this PR or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First point yes, I'll do that.

Second point yes, but I didn't want to do that as part of this PR.

@quis quis removed their assignment Oct 13, 2015
defaultdicts will add values if they are accessed. This means that the
_content and _questions properties could grow through the course of the
program running.
@allait
Copy link
Contributor

allait commented Oct 13, 2015

👍

✨ Changelog looks great! ✨

@allait pointed out that manifests can only cover questions from one
question set so there is a hierarchical order here.
@robyoung robyoung force-pushed the multi-framework-content-loader branch from 2d24655 to 6b7f073 Compare October 13, 2015 14:36
robyoung added a commit that referenced this pull request Oct 13, 2015
Support frameworks and manifests in ContentLoader
@robyoung robyoung merged commit 6a207d8 into master Oct 13, 2015
@robyoung robyoung deleted the multi-framework-content-loader branch October 13, 2015 15:19
robyoung added a commit to Crown-Commercial-Service/digitalmarketplace-buyer-frontend that referenced this pull request Oct 16, 2015
The entirety of the changes in this commit are related to the 10.0.0
change.

Crown-Commercial-Service/digitalmarketplace-utils#182
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.

3 participants