-
Notifications
You must be signed in to change notification settings - Fork 124
Feat/python npm packaging #430
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
Draft
jnorthrup
wants to merge
15
commits into
kscripting:master
Choose a base branch
from
jnorthrup:feat/python-npm-packaging
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
…age alignment This commit addresses a 'missing linkage' issue where kscript's wrapper could fail to load the main class compiled from a .kts script, resulting in a ClassNotFoundException. **Problem Analysis:** 1. For `.kts` scripts without an explicit `package` declaration, kscript internally assigns a default package (e.g., `kscript.scriplet`). 2. A wrapper class (e.g., `Main_ScriptName.kt`) is generated to provide a standard `main` method entry point. This wrapper attempts to load the compiled `.kts` script's class using reflection, qualified with the assigned package name (e.g., `kscript.scriplet.ScriptName`). 3. However, the original `.kts` file content (without an explicit package statement) was written to a temporary file and compiled by `kotlinc`. `kotlinc` would place such a class in the default (unnamed) package. 4. This mismatch (wrapper expecting `kscript.scriplet.ScriptName`, but class actually being `ScriptName` in the default package) caused the `ClassNotFoundException`. **Solution Implemented:** The `JarArtifactCreator.create()` method has been modified. Before a `.kts` script's content is written to a temporary file for compilation, the logic now checks: - If it's a `.kts` file. - If kscript has determined a package name for it (either parsed or defaulted). - If the script content itself does not already start with a `package` declaration. If these conditions are met, the determined package declaration (e.g., `package kscript.scriplet;`) is prepended to the script content. This ensures that `kotlinc` compiles the `.kts` script's class into the same package that the wrapper expects, resolving the ClassNotFoundException. **Further Considerations for Full Robustness (Future Work):** While this commit fixes a critical classloading issue for `.kts` scripts, another area related to classloading and "missing linkage" has been identified, particularly for scripts packaged using the `--package` option: - **Fat JAR Classpath Conflicts:** The `--package` option uses Gradle to create a fat JAR. The current Gradle template uses `DuplicatesStrategy.INCLUDE`. This can lead to runtime issues (e.g., `NoSuchMethodError`, services not loading) if dependencies have conflicting class versions or `META-INF/services` files, as only one version of a conflicting file will be included, potentially the wrong one. - **Recommendation:** For more robust packaged scripts, the Gradle template should be updated to use a dedicated fat JAR plugin like `com.github.johnrengelman.shadow`, which offers better strategies for dependency conflict resolution and resource merging. This fix provides a significant improvement in the reliable execution of .kts files. Further work on the packaging mechanism can enhance robustness for distributed scripts.
fix: Resolve ClassNotFoundException for .kts scripts by ensuring pack…
This commit fixes a ClassNotFoundException that occurred when running KTS scripts. The issue was caused by your script class not being packaged into the scriplet.jar during compilation. The fix involves combining your script code and the wrapper code into a single string before compilation. This ensures that kotlinc treats them as a single compilation unit and packages all necessary classes into the resulting JAR. Specifically, the changes are: - In `JarArtifactCreator.kt`: - For KTS scripts, your script content and the generated wrapper content are now concatenated into a single string. - This combined string is written to a single temporary .kt file, which is then passed to the Kotlin compiler. - In `Templates.kt`: - `createWrapperForScript` now ensures the wrapper code has the correct package declaration, consistent with your script. This approach should resolve the ClassNotFoundException and allow KTS scripts to be compiled and executed correctly.
Fix: Resolve ClassNotFoundException for KTS scripts
This commit updates the primary Kotlin version used by kscript for its own build and for the Gradle scripts it generates (e.g., for --idea and --package) from 1.7.21 to 2.1.21-embedded. Changes include: 1. **`build.gradle.kts`:** * The `kotlinVersion` property has been changed to "2.1.21-embedded". * The `kotlin("jvm")` plugin version has been updated to "2.1.21-embedded". * Dependencies on `org.jetbrains.kotlin:*` artifacts were already parameterized to use `kotlinVersion`, so they will automatically adopt the new version. 2. **`GradleTemplates.kt`:** * Verified that generated Gradle scripts for `--idea` and `--package` already use `KotlinVersion.CURRENT` to dynamically set their Kotlin plugin and `kotlin-script-runtime` versions. This ensures they will use the new "2.1.21-embedded" version. * Updated `kotlin-stdlib` declarations within these templates to also explicitly use the dynamic `kotlinVersion` for consistency and clarity. No other hardcoded references to the old Kotlin version were found in kscript's core operational code that required changes for this update. Runtime version information displayed to you (e.g., via `kscript --version`) should dynamically reflect this new version through `BuildConfig.KOTLIN_VERSION`.
feat: Update internal Kotlin version to 2.1.21-embedded
This change introduces the necessary files and build modifications to enable you to package kscript for Python (pip) and JavaScript (npm) environments. Key changes include: - Added Python wrapper script (`wrappers/kscript_py_wrapper.py`) to execute kscript.jar. - Added `setup.py` to define the Python package, making `kscript` available as a console script. - Added Node.js wrapper script (`wrappers/kscript_js_wrapper.js`) to execute kscript.jar. - Added `package.json` to define the NPM package, making `kscript` available via the bin field. - Modified `build.gradle.kts`: - To copy `kscript.jar` into the `wrappers/` directory. - To include `setup.py`, `package.json`, and the `wrappers/` directory (containing the JAR and wrapper scripts) in the main kscript distribution zip. - Added basic test scripts (`test/test_python_wrapper.py`, `test/test_js_wrapper.js`) to verify the functionality of the wrapper scripts with a sample kscript (`examples/test_wrapper.kts`). - Updated `README.adoc` with a new section detailing how you can build and install the Python and NPM packages from the distributed files. This provides a foundation for you if you wish to integrate kscript into Python or Node.js workflows by building the packages themselves from the kscript release distribution.
I've upgraded the Gradle wrapper to use Gradle version 8.14.1. This updates the `distributionUrl` in `gradle/wrapper/gradle-wrapper.properties` and ensures associated wrapper scripts are consistent. Using a more recent Gradle version helps with performance, compatibility with modern JDKs and Kotlin, and access to new Gradle features.
Feat/python npm packaging
Updated README.adoc to provide more current information and accurately reflect the project's state in 2024. Key changes include: - Introduction: Replaced outdated "Good News about Kotlin 1.4 scripting" section with a more timeless description of kscript's value. Removed a very dated (2017) conference link. - Installation: - Added a note clarifying that package manager versions (SDKMAN, Homebrew, Scoop) may not be the absolute latest, and recommending the "Build it yourself" section for cutting-edge use. - Updated the "Build it yourself" section to encourage its use for modern Kotlin/Java versions (e.g., Kotlin 2.2.0+, Java 21+), and to note JDK requirements. - Script Configuration / Annotations: - Added a cautionary note regarding the age of the `kscript-annotations:1.5` artifact and potential compatibility considerations with modern Kotlin 2.x. - Clarified that kscript historically used v1.5 internally. - Feature Descriptions: - Verified that no unmerged/non-existent features like Proguard were mentioned (none were, so no changes needed on this point). - How to contribute?: - Removed outdated, specific YouTrack issue links from 2017-2019. - Replaced with general guidance to use the kscript GitHub issue tracker and the official JetBrains YouTrack for IDE/Kotlin issues. - FAQ: - Updated the answer comparing Kotlin and Python scripting performance to be more nuanced and cover JVM startup/compilation overhead vs. peak performance. These changes aim to improve clarity, set realistic expectations for you, and ensure the documentation is more helpful and up-to-date.
This commit introduces the new command-line option `--export-to-gradle-project <script> <output_dir>`, which allows you to generate a complete, standalone Gradle project from an existing kscript file. This "last mile toolkit" feature facilitates graduating a kscript into a more formal project structure, ready for further development, testing, and packaging using standard Gradle workflows. Key functionalities implemented in `ProjectGenerator.kt`: - Parses the input kscript for dependencies, Maven repositories, package name, and entry point using kscript's internal resolvers. - Creates the specified output directory. - Determines project properties (group, name, version), intelligently deriving the group and main class from script annotations or defaults. - Generates `settings.gradle.kts` with the project name. - Generates a comprehensive `build.gradle.kts` including: - Kotlin JVM and Application plugins (using kscript's own Kotlin version, e.g., 2.2.0-RC2, and targeting Java 21). - Project group and version. - Maven Central and any custom repositories from the script. - Kotlin standard library and all dependencies from the script. - Application main class configuration. - Standard Kotlin compiler options and Java toolchain settings. - Creates the standard Maven/Gradle directory structure: - `src/main/kotlin/[package_path]` - `src/main/resources` - `src/test/kotlin/[package_path]` - `src/test/resources` - Transforms the original kscript content by: - Removing the shebang and kscript-specific file-level annotations. - Adding an appropriate package declaration. - Saves the result as a `.kt` file within `src/main/kotlin/[package_path]`. - Generates a `.gitignore` file with common Kotlin/Gradle patterns. - Copies and configures the Gradle Wrapper (`gradlew`, `gradlew.bat`, `gradle/wrapper/*`) from kscript's own project, ensuring the generated project uses a consistent and recent Gradle version (e.g., 8.14.1). The command-line interface in `Kscript.kt` and option parsing in `OptionsUtils.kt` have been updated to support this new feature.
This commit enhances the `--export-to-gradle-project` feature by allowing kscripts to define their own target Maven coordinates (groupId, artifactId, version) via a new `@file:ProjectCoordinates` annotation. Key changes: 1. **Annotation Parsing (`Script.kt`, `Parser.kt`, `model/ProjectCoordinates.kt`):** - I introduced a new data class `model.ProjectCoordinates` to hold `group`, `artifact`, and `version`. - The `Script` model now includes an optional `projectCoordinates` field. - I updated `LineParser.kt` and `Parser.kt` to recognize and parse `@file:ProjectCoordinates(group="...", artifact="...", version="...")` annotations from script files. - The parsed coordinates are stored in the `Script` object via `ResolutionContext` and `SectionResolver`. 2. **Project Generation (`generator/ProjectGenerator.kt`):** - The `exportToGradleProject` function now retrieves any `ProjectCoordinates` defined in the script. - These script-defined coordinates are prioritized when setting: - `group` in `build.gradle.kts`. - `version` in `build.gradle.kts`. - `rootProject.name` in `settings.gradle.kts` (derived from the artifactId). - Fallback logic (using script package name, output directory name, or defaults) is retained if the annotation or specific attributes are missing. - The package path for source files (`src/main/kotlin/...`, `src/test/kotlin/...`) and the `package` declaration in the generated `.kt` file are now based on the `effectiveProjectGroup` (derived from the annotation or fallbacks). - Default `mainClassName` derivation also uses `effectiveProjectGroup`. This makes the project generation feature more declarative, allowing the script itself to be the source of truth for its intended Maven identity when being "graduated" into a full Gradle project.
Feat/python npm packaging
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.