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

V2.1 #307

Draft
wants to merge 49 commits into
base: master
Choose a base branch
from
Draft

V2.1 #307

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
fdc2cf3
Bump version to 2.1
okennedy Nov 30, 2023
ba60db6
Add a state-specific icon to the ToC (closes #290)
okennedy Nov 30, 2023
17267b1
Merge branch 'master' into v2.1
okennedy Jan 3, 2024
e79e4c0
Fixing merge bug.
okennedy Jan 3, 2024
ecd17de
Move documentation list to help menu (closes #295)
okennedy Jan 3, 2024
8e6e026
WIP: Adding a script editor (re: #294)
okennedy Jan 3, 2024
d9b8c0c
Safety: Drop implicit tag rendering
okennedy Jan 4, 2024
af87729
Prototype of Script operations.
okennedy Jan 5, 2024
b387f61
Add copyright headers.
okennedy Jan 5, 2024
585b2a4
Finishing the ScriptEditor (re #294)
okennedy Jan 5, 2024
17a1256
Round out Vizier Scripts
okennedy Jan 6, 2024
f0c3df3
Minor script execution bugfixes.
okennedy Jan 6, 2024
c06e264
Python show dataset now works on externally provided datasets contain…
okennedy Jan 20, 2024
580a98f
Python run_script now correctly invalidates cached artifacts
okennedy Jan 21, 2024
c18b7ab
Add a parameter to enable/disable script outputs.
okennedy Jan 21, 2024
c3b91dd
Improve error reporting.
okennedy Jan 21, 2024
16929e0
Add a quick re-run button (closes #300)
okennedy Jan 27, 2024
70fb59f
Fix transient matplotlib resource leak on vizierdb.show(figure)
okennedy Jan 27, 2024
3d73d5b
Include Project/Branch name in tab title
okennedy Jan 28, 2024
15dd8f3
Tentatively, dynamically loaded plugins seem to work. (re: #288)
okennedy Jan 28, 2024
4c3473e
Clean up plugin loading
okennedy Jan 29, 2024
55cc965
Add 'show output' field to SQL cells
okennedy Feb 10, 2024
121078f
Contributors doc
okennedy Feb 28, 2024
3e9d739
Merge branch 'v2.1' of github.com:VizierDB/vizier-scala into v2.1
okennedy Feb 28, 2024
975f501
CDF goes on the y-axis
okennedy Mar 23, 2024
c2fda06
Adding support for the map type
okennedy Apr 7, 2024
ce5657a
Minor Bugfixes / QOL
okennedy Apr 7, 2024
16776c5
Adding safe export support for Binary Types via base64
okennedy Apr 24, 2024
86c91b8
Minor bugfixes
okennedy Apr 27, 2024
0c1d557
Plugin jars are now loaded into the context of Scala cells
okennedy Apr 27, 2024
3405a2f
Minor bugfixes to sampling
okennedy Apr 28, 2024
bf516d1
Support for maps
okennedy May 19, 2024
7b79260
Merge remote-tracking branch 'github/master' into v2.0
okennedy May 19, 2024
c3cda34
2.0.0 release
okennedy May 19, 2024
4684e8b
Version bump to 2.0.2
okennedy May 19, 2024
7a2dcda
Minor bug/workflow fixes
okennedy May 19, 2024
9db1e12
Tentatively Replacing AnnotateWithSequenceNumber with AttachDistribut…
okennedy May 31, 2024
24ce521
Merge remote-tracking branch 'origin/v2.1' into v2.1
okennedy May 31, 2024
3f3d627
Minor QOL
okennedy Aug 5, 2024
0676a7e
Merge remote-tracking branch 'origin/v2.0' into v2.1
okennedy Aug 5, 2024
02aea5b
Minor Papercut Fixes
okennedy Aug 8, 2024
0808e06
Merge remote-tracking branch 'origin/v2.0' into v2.1
okennedy Aug 8, 2024
7aee4ec
Merge branch 'v2.1' of github.com:VizierDB/vizier-scala into v2.1
okennedy Aug 9, 2024
a8d7ce3
Housekeeping
okennedy Sep 20, 2024
c70a3b2
More housekeeping.
okennedy Sep 20, 2024
35db2a6
Asynchronously created modules now inserted correctly (closes #319)
okennedy Sep 20, 2024
766297c
Missing file in last commit
okennedy Sep 20, 2024
f204d9d
Properly clean up when the user cancels a spreadsheet edit.
okennedy Sep 22, 2024
76a65bc
Temporary workaround for #320
okennedy Sep 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Contributing to Vizier

## General Guidelines

We want everyone to be able to participate here, so when contributing (issues, documentation, code, etc...), please keep the following two guidelines in mind: (i) Think about how your words will be perceived by others before writing them, and (ii) give others the benefit of the doubt when interpreting their words.

## Style

#### Branches

- The main Vizier branch represents the most recent release candidate.
- No one pushes directly to the main branch.
- Development branches are labeled `v[major].[minor]` (e.g., v2.1).
- Pull requests for new features will only be accepted for the most recent development branch.
- Only pull requests for bugfixes will be accepted for earlier branches.
- Pull requests must pass the default test case suite:
- `mill vizier.test` for backend changes
- `mill vizier.ui.test` for frontend changes

#### Commits

- A single commit should address a single issue. Spread distinct changes across multiple commits.
- The first line should be an at-most 100 character summary of the commit, containing:
- The prefix WIP: if the commit is broken.
- A brief description of the goal of the commit's changes.
- An issue reference:
- (re: #[issue number]) to mark work towards a specific ticket
- (closes: #[issue number]) to signify that work towards a ticket is done
- A brief list of behaviors of the system that were changed: One line per behavior. For example:
- [system component] no longer hangs when passed a [type of input]
- Added [field] to the schema of [category] to store [summary]
- UI can now display [state].
- If the reason for the behavioral change is not clear from the summary, add a short discussion providing any necessary context. For example "[external component] has a bug where if you ask it to [action] then it deletes your hard drive. Obviously, this would be bad, so we need to sanitize our inputs."

#### Pull Requests

- Ideally, a pull request focuses on one issue, or a linked set of issues.
- Pull requests for features must be made to the latest development branch.
- Only pull requests for bug fixes will be accepted to an earlier branch.
- Pull requests must pass all test cases.
- ... excepting any test cases that are broken on a development branch.
- The text of the pull request should briefly summarize the key changes made in terms of behaviors of the system that are different (see commit messages above).
- The text should clearly identify which tickets the pull request is responding to.
2 changes: 1 addition & 1 deletion LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (C) 2017-2021 University at Buffalo,
Copyright (C) 2017-2024 University at Buffalo,
New York University,
Illinois Institute of Technology.
Licensed under the Apache License, Version 2.0 (the "License");
Expand Down
17 changes: 12 additions & 5 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import java.util.Calendar
*** The Vizier Backend
*************************************************/
object vizier extends ScalaModule with PublishModule {
val VERSION = "2.0.0-rc2"
val VERSION = "2.1.0-SNAPSHOT"
val PLAY_JS = ivy"com.typesafe.play::play-json::2.9.2"

val MIMIR_CAVEATS = ivy"info.vizierdb::mimir-caveats::0.3.6"
Expand All @@ -25,7 +25,7 @@ object vizier extends ScalaModule with PublishModule {
"log4j" -> "*",
)

def scalaVersion = "2.12.15"
def scalaVersion = "2.12.20"

def repositoriesTask = T.task { super.repositoriesTask() ++ Seq(
MavenRepository("https://maven.mimirdb.org/"),
Expand Down Expand Up @@ -75,6 +75,9 @@ object vizier extends ScalaModule with PublishModule {

f"$VERSION (revision $gitVersion-$gitRevision; built ${date.get(Calendar.YEAR)}%04d-${date.get(Calendar.MONTH)}%02d-${date.get(Calendar.DAY_OF_MONTH)}%02d)"
}
def version = T {
VERSION
}

def internalJavaVersion = T {
try {
Expand Down Expand Up @@ -165,7 +168,7 @@ object vizier extends ScalaModule with PublishModule {
ivy"info.vizierdb::vega:1.0.0",

// Scala Cell
ivy"org.scala-lang:scala-compiler:2.12.15",
ivy"org.scala-lang:scala-compiler:${scalaVersion}",

// Python
ivy"me.shadaj::scalapy-core:0.5.2",
Expand Down Expand Up @@ -212,7 +215,7 @@ object vizier extends ScalaModule with PublishModule {
*** Backend Resources
*************************************************/
def buildRoutesScript = T.sources { os.pwd / "scripts" / "build_routes.sc" }
def routesFile = T.sources { millSourcePath / "shared" / "resources" / "vizier-routes.txt" }
def routesFile = T.sources { millSourcePath / "resources" / "vizier-routes.txt" }

def routes = T {
println("Recompiling routes from "+routesFile().head.path);
Expand Down Expand Up @@ -245,7 +248,7 @@ object vizier extends ScalaModule with PublishModule {
object ui extends ScalaJSModule {

def scalaVersion = vizier.scalaVersion
def scalaJSVersion = "1.7.1"
def scalaJSVersion = "1.16.0"

/*************************************************
*** Frontend Dependencies
Expand All @@ -261,6 +264,10 @@ object vizier extends ScalaModule with PublishModule {
millSourcePath / "src",
vizier.millSourcePath / "shared" / "src"
)

override def scalacOptions: Target[Seq[String]] = T { Seq(
"-P:scalajs:nowarnGlobalExecutionContext"
)}

override def compile = T {
routes()
Expand Down
Binary file added plugins/mimir-pip.jar
Binary file not shown.
12 changes: 10 additions & 2 deletions scripts/bootstrap.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
ARTIFACT=info.vizierdb:vizier_2.12:2.0.0-rc2
MAVEN_BASE=info.vizierdb:vizier_2.12
VERSION=$(
mill show vizier.versionString 2> /dev/null |
jq -r |
sed 's/ .*//'
)
ARTIFACT=$MAVEN_BASE:$VERSION

echo $ARTIFACT

coursier bootstrap $ARTIFACT\
-r https://s01.oss.sonatype.org/content/groups/public/ \
-r https://repo.osgeo.org/repository/release/ \
-r https://maven.mimirdb.org/ \
-M info.vizierdb.Vizier \
-o bin/vizier -f
-o bin/vizier -f
18 changes: 18 additions & 0 deletions scripts/build_routes.sc
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,13 @@ def websocketAPICall(route: Route): String =
"additionalProperties" -> extra,
)

def mkAnyOf(options: JsValue*) =
{
Json.obj(
"anyOf" -> options
)
}

def mkArray(elem: JsValue) = Json.obj("type" -> "array", "items" -> elem)

define { "Identifier" -> Json.obj(
Expand Down Expand Up @@ -562,6 +569,17 @@ def websocketAPICall(route: Route): String =
"version" -> Json.obj("type" -> "string"),
"packages" -> mkArray(typeRef("PythonPackage")),
)}
define { "VizierScriptModule" -> mkAnyOf(
mkObject()(
"type" -> Json.obj("const" -> "inline"),
"spec" -> typeRef("JsValue"),
),
mkObject()(
"type" -> Json.obj("const" -> "in_out"),
"imports" -> typeRef("JsValue"),
"exports" -> typeRef("JsValue"),
)
)}

val aliases = Map(
"CommandArgumentList.T" -> "Seq[CommandArgument]",
Expand Down
2 changes: 1 addition & 1 deletion scripts/fix_copyrights.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from glob import glob
import re

LICENSE_VERSION = 2
LICENSE_VERSION = 3

with open("LICENSE.txt") as f:
LICENSE = [
Expand Down
1 change: 1 addition & 0 deletions scripts/lib/akkagen.sc
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ def decodePath(route: Route, handler: AkkaDirective): AkkaDirective =
case PathVariable(_, "long") => "LongNumber"
case PathVariable(_, "subpath") => "Remaining"
case PathVariable(_, "string") => "Segment"
case PathVariable(_, pvt) => throw new RuntimeException(s"Invalid path variable type '$pvt' (expecting 'int', 'long', 'subpath', or 'string')")
}

val (pathParamInputs, pathParamOutputs) =
Expand Down
3 changes: 3 additions & 0 deletions scripts/lib/routes.sc
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,15 @@ case class Route(

def readRoutes(path: os.Path): Seq[Route] =
os.read(path).split("\n")
.toIndexedSeq
.map { description =>
val components = description.split("\\s+")
val pathAndArguments = components(0).split("\\?")
val path = pathAndArguments(0).split("/").toSeq
val pathQuery:Seq[PathVariable] =
if(pathAndArguments.size > 1){
pathAndArguments(1).split("&")
.toIndexedSeq
.map { _.split(":").toSeq }
.map {
case Seq(identifier, dataType) => PathVariable(identifier, dataType)
Expand All @@ -147,6 +149,7 @@ def readRoutes(path: os.Path): Seq[Route] =
components(6) match {
case "-" | "_" => Seq()
case x => x.split(";")
.toIndexedSeq
.map { _.split(":").toSeq }
.map {
case Seq(identifier, dataType) => Param(identifier, dataType)
Expand Down
23 changes: 20 additions & 3 deletions scripts/publish.sh
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
#!/bin/bash

# This script expects credentials stored in `pass`
# (https://www.passwordstore.org/). Create a `pass` archive for
# sonatype.org and make sure it includes two lines:
# ```
# token_user: ...
# token_pass: ...
# ```
# The values from these lines can be populated from the user token
# which can be obtained from your user profile (instructions here):
# https://central.sonatype.org/publish/generate-token/


cd `dirname $0`/..

# Fix Copyrights
python3 scripts/fix_copyrights.py

export SONATYPE_USERNAME="$(
pass sonatype.org |
grep '^login:' |
sed 's/login: //'
grep '^token_user:' |
sed 's/token_user: //' |
head -n 1
)"

export SONATYPE_PASSWORD="$(
pass sonatype.org |
grep '^token_pass:' |
sed 's/token_pass: //' |
head -n 1
)"


mill mill.scalalib.PublishModule/publishAll \
vizier.publishArtifacts \
--release true\
Expand Down
15 changes: 14 additions & 1 deletion vizier/backend/src/info/vizierdb/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,17 @@ class Config(arguments: Seq[String])
descr = "Set the SparkSQL warehouse directory (default: {cache-dir}/spark-warehouse)"
)

val extraPlugins = opt[List[File]]("plugin",
short = 'P',
descr = "Enable a plugin for this session",
default = Some(List())
)

lazy val plugins:Seq[File] =
Option(defaults.getProperty("vizier-plugins"))
.map { _.split(":").map { new File(_) }.toSeq }
.getOrElse { Seq() } ++ extraPlugins()

def workingDirectoryFile: File =
new File(
workingDirectory
Expand Down Expand Up @@ -168,7 +179,9 @@ class Config(arguments: Seq[String])
lazy val pythonVenvDirFile = new File(cacheDirFile, "python")

def resolveToDataDir(path: String) = { new File(dataDirFile, path).getAbsoluteFile }

def resolveToWorkingDir(path: File): File =
if(path.isAbsolute()) { path }
else { workingDirectoryFile.toPath.resolve(path.toPath).toFile }

////////////////////////// Ingest //////////////////////////

Expand Down
107 changes: 107 additions & 0 deletions vizier/backend/src/info/vizierdb/Plugin.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/* -- copyright-header:v2 --
* Copyright (C) 2017-2021 University at Buffalo,
* New York University,
* Illinois Institute of Technology.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* -- copyright-header:end -- */
package info.vizierdb

import play.api.libs.json._
import java.net.URLClassLoader
import java.net.URL
import java.io.File
import java.io.FileNotFoundException
import com.typesafe.scalalogging.LazyLogging
import scala.collection.mutable
import info.vizierdb.util.ClassLoaderUtils

case class Plugin(
name: String,
schema_version: Int,
plugin_class: String,
description: String,
documentation: Option[String],
)
{
}

object Plugin
extends LazyLogging
{

val loaded = mutable.Map[String, Plugin]()
val jars = mutable.Buffer[URL]()


implicit val pluginFormat: Format[Plugin] = Json.format

def load(file: File): Plugin =
{
val jar =
if(file.isAbsolute){ file }
else {
Vizier.config.workingDirectoryFile.toPath
.resolve(file.toPath)
.toFile
}


if(!jar.exists()){ throw new FileNotFoundException(jar.getAbsoluteFile.toString) }
val url = jar.getAbsoluteFile().toURI().toURL()


// This classloader is used only to load the vizier-plugin.json file.
// and then discarded
val preloader = new URLClassLoader(
Array(jar.toURI.toURL),
Vizier.mainClassLoader
)

val plugin =
Json.parse(
preloader.getResourceAsStream("vizier-plugin.json")
).asOpt[Plugin]
.getOrElse {
throw new RuntimeException(s"$jar is not a valid Vizier Plugin")
}

Vizier.sparkSession.sparkContext.addJar(jar.getAbsoluteFile().toString)
val loader = Vizier.sparkSession.sharedState.jarClassLoader
loader.addURL(url)

val detail = s"${plugin.name} [$jar]"

assert(
plugin.schema_version > 0 && plugin.schema_version <= 1,
s"Unsupported version '${plugin.schema_version} for plugin $detail"
)

assert(
!loaded.contains(plugin.name),
s"Plugin ${plugin.name} is already loaded."
)

loaded.put(plugin.name, plugin)
jars.append(jar.toURI.toURL)

val clazz = Class.forName(plugin.plugin_class, true, loader)
val singleton = clazz.getDeclaredField("MODULE$").get()
val initMethod = clazz.getMethod("init", Vizier.sparkSession.getClass)

ClassLoaderUtils.withContextClassLoader(loader) {
initMethod.invoke(singleton, Vizier.sparkSession)
}

return plugin
}

def loadedJars = jars.toSeq
}
Loading