-
Notifications
You must be signed in to change notification settings - Fork 63
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
OpenAPI/Swagger JSON type schema support + many small fixes I came across #173
Conversation
…rmats without dataframe schema. Intergrated in ksp plugin, needs testing. Gradle plugin is still TODO
…ng from openapi and String -> java.time.dateTime etc conversion support
…bject types in array become Dataframe<Any>
Updated docs
core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/openapi.kt
Outdated
Show resolved
Hide resolved
...symbol-processor/src/test/kotlin/org/jetbrains/dataframe/ksp/DataFrameSymbolProcessorTest.kt
Outdated
Show resolved
Hide resolved
core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/openapi.kt
Outdated
Show resolved
Hide resolved
core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/openapi.kt
Outdated
Show resolved
Hide resolved
okay, I looked over additionalProperties... https://swagger.io/docs/specification/data-models/dictionaries/ |
…n-api # Conflicts: # core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/codeGen/CodeGeneratorImpl.kt
…outside test classes
…rame. Also fixed convertTo with properties of type DataFrame<*> (since DataFrame<Any?> worked fine and is equivalent)
|
||
if (from.isSubtypeOf(to)) try { | ||
return (this as DataColumnInternal<*>).changeType(to.withNullability(hasNulls())) | ||
} catch (e: UnsupportedOperationException) { /* */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you remember why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I believe this fixed a bug where converting from ColumnGroupImpl or FrameColumnImpl to something would crash because it doesn't have the changeType
option. However, convertTo
can now support conversions for any type of column, so the exception is caught here to give any user-given conversions a try first, otherwise, a TypeConverterNotFoundException is thrown.
} | ||
|
||
fun getConverter(from: KType, to: KType): Converter? { | ||
return converters[from.withNullability(false) to to.withNullability(false)] | ||
override fun convertIf( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have some representative example for this API? Honestly, i can't easily understand recursive list thing :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For convertIf
? Sure! It's not that difficult. convert.with
can only support exact type matches, which can be a problem when you cannot define exact types for everything you want to catch. Let's say you want to write a converter that would convert all numbers to strings:
convert<Number>.with { it.toString() }
This wouldn't work, since typeOf<Double>() != typeOf<Number>()
. That's where convertIf
can come in handy. With this function you can manufacture any type of converter you like and you can use the full capabilities of Kotlin reflect you like:
convertIf({ fromType, toSchema ->
fromType.withNullability(false).isSubtypeOf(typeOf<Number>()) &&
toSchema.type.withNullability(false) == typeOf<String>()
}) {
it.toString()
}
For OpenApi I needed to provide a converter for DataRow -> Any
, however, these converters only work on top-level types, so if a DataRow->Any
conversion needs to happen in a List<List<List<DataFrame<*>>>
, then we need my recursive function which makes convertIf
accept any of these types and convert it accordingly.
} | ||
|
||
/** Parse and read OpenApi specification to [DataSchema] interfaces. */ | ||
public fun readOpenApi( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not make DataFrame.Companion receiver?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because you don't create a DataFrame
;)
core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/DataRowApi.kt
Outdated
Show resolved
Hide resolved
core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/openapi.kt
Outdated
Show resolved
Hide resolved
import kotlin.reflect.full.isSubtypeOf | ||
import kotlin.reflect.jvm.jvmErasure | ||
import kotlin.reflect.typeOf | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wdyt about splitting this file? also, at some point we started to put formats in different modules
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might definitely be a good idea
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay splitting off openapi works up 'till the part where I decide to read a file as json or as openapi. Need to think of something clever or universal to make that work elegantly :)
all other references of baseType are now handled by commonType Added lots of tests to stabilize behavior
…dFormat interfaces (to solve json/openapi clashes)
# Conflicts: # core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/api/convert.kt # core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/Integration.kt
As described by #142
This PR contains a custom OpenAPI -> DF Marker conversion and implementation in the Gradle- and KSP plugin.
There are also a lot of tests, but I'm not yet 100% confident I've caught every edge case (there are many...).
Docs are updated too.
Let me know if there are any major things (or minor ones, all are welcome) that need changing or if you have some more testing ideas.
Edit:
Since I changed so much I'm gonna provide a small overview of the changes I made. Might make it easier to review. I'll go through the changed files:
convertIf
in dsl: way more powerful thanconvert(KType, KType)
, allows you to specify via a condition function whether you want to do a certain conversion and provides fromType and toSchema in ConverterScope.convert
still has priority overconvertIf
DataSchemaEnum
to control how they are (en/de)coded from/to datasets instead of using just their name@DataSchema
, the type will no longer be wrapped in aDataRow
since that unneccesary.DefaultReadDfMethod
now provides actualMarker
instead of just a nameMarkersExtractor
regardingnullableProperties
contains
inBaseColumn
is nowoperator fun
commonParents()
andcommonType()
CodeGenerator.Companion.urlReader
is now split intourlDfReader
andurlCodeGenReader
where the former is used to generate a dataframe from the data and types from that, while the latter directly generates types (for openapi)SupportedFormat
intoSupportedDataFrameFormat
andSupportedCodeGenerationFormat
createColumn()
createEmptyColumn
andcreateEmptyDataFrame
variants withnumberOfRows
ColumnSchema
, aside fromtype
now also hascontentType
for extra type info for Group- and Frame columns (instead of just gettingDataRow<*>
orDataFrame<*>
. Very useful for newconvertIf
method.intersectSchema
also tries to merge thesecontentType
s if possible.extractSchema
will make themAny?
.toSnakeCase()
helper functionJsonPath
, the objects will be read asDataFrame<KeyValueProperty>
CodeWithConverter
with allDataSchema
interfaces, type aliases and enums, as well asreadJson
functions which automatically fill in keyValuePaths and other conversions necessary.additionalProperties
will become key/value dataframes.properties
&additionalProperties
will ignoreadditionalProperties
importDataSchema()
function for Jupyter forSupportedCodeGenerationFormat
s like openapiJupyterConfiguration
DataFrame.get(vararg IntRage)
Edit:
suggestedType
is given as list, not automatically anymore. Also adds optionallistifyValues
argument toguessValueType()
andbaseType()