Add classmethod to generate JSON schemas - #79
Conversation
|
@theCapypara should I move everything related to JSON schema generation to a new file? |
|
Moving everything to a new file requires the |
Sorry, didn't see your comment earlier. Sounds good to me! |
Split schema functions into smaller units
5f97af7 to
e518030
Compare
This should hopefully make the function signatures a bit more readable.
e518030 to
8dfcbd4
Compare
|
Hi! I haven't forgotten this, but I need a bit more time to work through it. In the meantime some questions:
>>> Project.json_schema(None)
Traceback (most recent call last):
File "<python-input-3>", line 1, in <module>
Project.json_schema(None)
~~~~~~~~~~~~~~~~~~~^^^^^^
TypeError: argument 'main_schema_id': 'NoneType' object cannot be cast as 'str'
>>> Project.json_schema("project")
Traceback (most recent call last):
File "<python-input-2>", line 1, in <module>
Project.json_schema("project")
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
TypeError: 'NoneType' object cannot be cast as 'str'In any case the error message should probably be better. |
At first I only added it because So if the function is invoked with the URL that the schema(s) will be published at, the resulting schemas could be used directly and all the references to other documents/schemas already work. I guess we could just fallback to the name of the schema or the name of the document class if the argument isn't provided, but I hadn't thought about that before.
As far as I can see, the stub marks However The idea is that you probably don't want to have a dedicated JSON Schema for every document, so you only need to add the argument for those references which should be turned into their own JSON Schema.
|
|
@theCapypara just wanted to check in. Don't worry about taking more time, just want to know whether this PR is still on your radar. |
|
Jep, still have this on my list, need to find some time to dive into it, sorry. |
theCapypara
left a comment
There was a problem hiding this comment.
Thanks again and again sorry for taking so long.
Here's my thoughts
- it would be necessary for
schemato merge your PR, as I don't want to have to pull in a fork - alternatively we could ditch
schemaand replace it with something else, but from a short research I haven't really seen anything else I'm happy with (that can also provide JSON schemas)
I still don't really understand why there is so much doubling of schema names and IDs. If every schema has a name, why can't this just be used as the JSON schema ID, same for main_schema_id? This also causes having to map between the two because they don't neccesarily match. We also shouldn't make it necessary to give the schema objects names. I guess it's because JSON Schema is an afterthought in schema and its names have a different semantic than JSON schema IDs? But I don't like we have to add names to schemas now for no reason, just to make the schema library happy.
Please correct me if any of my understanding of this is wrong, but I thought of it for a while and in general I think this as-is unfortunately too complex for me to want to maintain as-is.
I also think adding a fallback for non Schema-schemas is too overkill.
Some options:
- We simplify the scope of this PR:
- Keep using
schemabut do not rely on it'snames oridsinjson_schemaorDocReference:json_schema()becomes a method without a parameter and DocReference constructor has it's second parameter remved. Instead all documents that want to be compatible withjson_schemahave to have a new propertyjson_schema_idand provides their ID. - AND Require
json_schema()to have the document and all$refed documents return aschemaobject, remove compatibility code for dicts and list.
- Keep using
- Or if we want first-class JSON schema support we should ditch
schemaand maybe switch to a schema library that works with jsonschema out of the box. Then we require new versions to haveschemareturn that and can just use the functionality of that library. I would prefer that.
| #[pymethods] | ||
| impl YamlConfigDocument { | ||
| #[classmethod] | ||
| pub(crate) fn json_schema<'py>(_cls: Bound<'py, PyType>, main_schema_id: String, py: Python<'py>) -> PyResult<HashMap<String, Bound<'py, PyDict>>> { |
There was a problem hiding this comment.
nit: Since this is also exposed via the Python API, this can just be pub
| } | ||
|
|
||
| // Return the (modified) object | ||
| return Ok(schema); |
There was a problem hiding this comment.
nit: Since this only applies to the first if-branch this return should be moved there for readability
|
|
||
| impl<'py> JsonSchemaBuilder<'py> { | ||
| pub fn new() -> Self { | ||
| return Self { |
There was a problem hiding this comment.
Unnecessary return, please run cargo clippy
The main thought behind this decision was that people might want to have a different ids when publishing schemas, but maybe that was overkill. I agree it's unnecessarily complicated, so I'd simplify that by using the names everywhere.
I like this option the best, since that would require the least amount of effort for existing projects using
In terms of maintainability I think this would be best, but that would also require more effort for existing projects and that was the initial reason why I didn't go that route initially and instead tried to make it work with the existing schema library.
Since the maintainers of I don't want to add a larger maintenance burden for you, so I'd like to go with whatever you think is the best way to ensure you can still maintain this library without problems! |
This PR adds a new classmethod
json_schema()to generate JSON schemas forYamlConfigDocumentclasses.The main motivation for this is getting schemas for riptide config files, but making it possible for all
YamlConfigDocumentclasses might help other projects as well.I'm not really confident in my Rust programming abilities, but I hope most of the code is fine.
Sadly this relies on my fork of
schemafor now, as the features required to generate useful JSON schemas have not been added yet.If keleshev/schema#340 gets merged and a new release is created we could switch back to the original version.
The only reason I'm currently doing it this way, is because it requires the least amount of changes to existing projects using
configcrunchright now.In the future it's probably better to replace
schemawith a different library, which supports everythingconfigcrunchneeds out of the box.