-
Notifications
You must be signed in to change notification settings - Fork 62
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
POJO toDataFrame support (and array improvements) #650
Conversation
…. If no memberProperties are available, fall back to getter-like memberFunctions. Also, it now tries to sort by any constructor if there are multiple (common in java with a no-arg constructor)
core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/api/toDataFrame.kt
Outdated
Show resolved
Hide resolved
core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/api/toDataFrame.kt
Outdated
Show resolved
Hide resolved
core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/Utils.kt
Outdated
Show resolved
Hide resolved
core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/toDataFrame.kt
Outdated
Show resolved
Hide resolved
…operty order sorting with multiple constructors.
b918f1b
to
a22f863
Compare
core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/Utils.kt
Outdated
Show resolved
Hide resolved
core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/api/toDataFrame.kt
Outdated
Show resolved
Hide resolved
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.
Add a little bit more work on clarification and refactoring for future generations
Let's add a check in isValueType for different arrays. Maybe there's a simple check? If there's no, below code from compiler for reference.
|
Let's filter out functions that have type arguments too
|
lucky for us, static functions aren't in |
…it, updating convertToDataFrame implementation to be clearer too. Testing for different types of primitives from java pojo
…ys as values in toDataFrame { properties() }
I tried to add your requests to the PR and even added a little extra I needed for debugging/testing (see top comment). I also spawned a couple of new related issues: |
|
||
/** Returns the column name for this callable. | ||
* If the callable contains the [ColumnName][org.jetbrains.kotlinx.dataframe.annotations.ColumnName] annotation, its [ColumnName.name][org.jetbrains.kotlinx.dataframe.annotations.ColumnName.name] is returned. | ||
* Otherwise, the name of the callable is returned with proper getter-trimming iff it's a [KFunction]. */ |
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.
Let's not introduce comments that are essentially exactly follow the code? Code is easier to read and is always factual, unlike plain text here
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.
I agree in the same file, but if you're calling the code from another place, all you see is the signature and the KDoc. I don't want to navigate to a piece of code to figure out what it does.
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.
ctrl+shift+i?
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.
haha okay that might work, but still, I think there's no such thing as "unnecessary docs". If university programming has taught me anything is that documentation, no matter how useless it may seem to write, will help you in some way in the future.
val box = kClass.java.methods.single { it.name == "box-impl" } | ||
val valueClassConverter = ValueClassConverter(unbox, box) | ||
valueClassConverter | ||
if (!kClass.isValue) return@let null |
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.
Is it really needed? It was reviewed and merged, not sure why it needs to be changed without actual functional changes. I don't like when PR has things like this
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.
Well, the complexity of this huge function is someting @zaleslaw stuggeled with and I agree. Lowering the cognitive complexity, like here, improves the codebase as a whole. And face it, we're not gonna do a refactor of everything anytime soon, so I think it's okay to do this along with PRs. I will try to do it in separate commits when I can though, so you can more easily skip it in reviews
* It prefers the primary constructor if it exists, else it falls back to the other constructors to do the sorting. | ||
* Finally, it falls back to lexicographical sorting if a property does not exist in any constructor. | ||
*/ | ||
internal fun <T> Iterable<KCallable<T>>.sortWithConstructors(klass: KClass<*>): List<KCallable<T>> { |
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.
Honestly i still don't understand what to expect from this as a user. (regarding secondary constructors etc) I'd like something simpler
Btw, by default reflection probably returns properties / functions in some specific order too?
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.
nope :/ reflection returns them completely random.
The idea was to come as close to what a user expects the order of columns to be as possible. So if they have a weird class like
class A {
constructor()
constructor(foo: Int, bar: Int)
constructor(bar: Int, too: Int)
...
}
well, you expect foo
to be before bar
and too
after it, right? That's what this function achieves. It sorts the columns according to the order of all constructors. If there's a primary constructor, obviously that is used first.
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.
Now simplified to just sorting lexicographically and by primary/single constructor
core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/toDataFrame.kt
Show resolved
Hide resolved
core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/TypeUtils.kt
Outdated
Show resolved
Hide resolved
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.
Looks good, thank you!
Fixes #380
This PR relaxes, the
toDataFrame()
properties()
DSL to allow for getter functions too.If no
memberProperties
are available, it'll fall back to getter-likememberFunctions
.Also, it now tries to sort by any constructor if there are multiple (common in java with a no-arg constructor).
EDIT:
toDataFrame { properties }
treats arrays as values using newisArray
reflection helpers.