Skip to content

Commit

Permalink
Merge pull request #22 from kleis-technology/release/1.6.5
Browse files Browse the repository at this point in the history
Release/1.6.5
  • Loading branch information
pevab authored Jun 10, 2024
2 parents a4110a6 + d2cfb45 commit 9416eb8
Show file tree
Hide file tree
Showing 48 changed files with 1,119 additions and 299 deletions.
2 changes: 2 additions & 0 deletions cli/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ dependencies {

implementation("com.github.ajalt.clikt:clikt:4.2.2")
implementation("org.apache.commons:commons-csv:1.10.0")

implementation("com.charleskorn.kaml:kaml:0.59.0")
}

tasks.test {
Expand Down
53 changes: 33 additions & 20 deletions cli/src/main/kotlin/ch/kleis/lcaac/cli/cmd/AssessCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,61 @@ import ch.kleis.lcaac.cli.csv.CsvProcessor
import ch.kleis.lcaac.cli.csv.CsvRequest
import ch.kleis.lcaac.cli.csv.CsvRequestReader
import ch.kleis.lcaac.cli.csv.CsvResultWriter
import ch.kleis.lcaac.core.config.LcaacConfig
import ch.kleis.lcaac.core.math.basic.BasicOperations
import ch.kleis.lcaac.grammar.Loader
import ch.kleis.lcaac.grammar.LoaderOption
import com.charleskorn.kaml.Yaml
import com.charleskorn.kaml.decodeFromStream
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.arguments.help
import com.github.ajalt.clikt.parameters.options.*
import com.github.ajalt.clikt.parameters.options.associate
import com.github.ajalt.clikt.parameters.options.default
import com.github.ajalt.clikt.parameters.options.help
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.types.file
import java.io.File
import java.nio.file.Paths

@Suppress("MemberVisibilityCanBePrivate")
@Suppress("MemberVisibilityCanBePrivate", "DuplicatedCode")
class AssessCommand : CliktCommand(name = "assess", help = "Returns the unitary impacts of a process in CSV format") {
val name: String by argument().help("Process name")
val labels: Map<String, String> by option("-l", "--label")
.help(
"""
.help(
"""
Specify a process label as a key value pair.
Example: lcaac assess <process name> -l model="ABC" -l geo="FR".
""".trimIndent())
.associate()
private val getPath = option("-p", "--path").file(canBeFile = false).default(File(".")).help("Path to root folder.")
val path: File by getPath
val dataSourcePath: File by option("--data-path").file(canBeFile = false)
.defaultLazy { getPath.value }
.help("Path to data folder. Default to root folder.")
.associate()
private val getProjectPath = option("-p", "--project").file()
.default(File(defaultLcaacFilename))
.help("Path to project folder or yaml file.")
val projectPath: File by getProjectPath

val file: File? by option("-f", "--file").file(canBeDir = false)
.help("""
.help("""
CSV file with parameter values.
Example: `lcaac assess <process name> -f params.csv`.
""".trimIndent())
val arguments: Map<String, String> by option("-D", "--parameter")
.help(
.help(
"""
Override parameter value as a key value pair.
Example: `lcaac assess <process name> -D x="12 kg" -D geo="UK" -f params.csv`.
""".trimIndent())
.associate()
.associate()

override fun run() {
val files = lcaFiles(path)
val (workingDirectory, lcaacConfigFile) = parseProjectPath(projectPath)
val config = if (lcaacConfigFile.exists()) projectPath.inputStream().use {
Yaml.default.decodeFromStream(LcaacConfig.serializer(), it)
}
else LcaacConfig()

val files = lcaFiles(workingDirectory)
val symbolTable = Loader(BasicOperations).load(files, listOf(LoaderOption.WITH_PRELUDE))
val processor = CsvProcessor(dataSourcePath, symbolTable)
val processor = CsvProcessor(config, symbolTable, workingDirectory.path)
val iterator = loadRequests()
val writer = CsvResultWriter()
var first = true
Expand All @@ -64,7 +77,7 @@ class AssessCommand : CliktCommand(name = "assess", help = "Returns the unitary

private fun loadRequests(): Iterator<CsvRequest> {
return file?.let { loadRequestsFrom(it) }
?: listOf(defaultRequest()).iterator()
?: listOf(defaultRequest()).iterator()
}

private fun loadRequestsFrom(file: File): Iterator<CsvRequest> {
Expand All @@ -77,10 +90,10 @@ class AssessCommand : CliktCommand(name = "assess", help = "Returns the unitary
val header = pairs.mapIndexed { index, pair -> pair.first to index }.toMap()
val record = pairs.map { it.second }
return CsvRequest(
name,
labels,
header,
record,
name,
labels,
header,
record,
)
}
}
3 changes: 1 addition & 2 deletions cli/src/main/kotlin/ch/kleis/lcaac/cli/cmd/LcaacCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@ package ch.kleis.lcaac.cli.cmd
import com.github.ajalt.clikt.core.CliktCommand

class LcaacCommand : CliktCommand(name = "lcaac") {
override fun run() {
}
override fun run() {}
}
43 changes: 33 additions & 10 deletions cli/src/main/kotlin/ch/kleis/lcaac/cli/cmd/TestCommand.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ch.kleis.lcaac.cli.cmd

import ch.kleis.lcaac.core.datasource.CsvSourceOperations
import ch.kleis.lcaac.core.config.LcaacConfig
import ch.kleis.lcaac.core.datasource.DefaultDataSourceOperations
import ch.kleis.lcaac.core.math.basic.BasicOperations
import ch.kleis.lcaac.core.testing.BasicTestRunner
import ch.kleis.lcaac.core.testing.GenericFailure
Expand All @@ -10,39 +11,61 @@ import ch.kleis.lcaac.grammar.CoreTestMapper
import ch.kleis.lcaac.grammar.Loader
import ch.kleis.lcaac.grammar.LoaderOption
import ch.kleis.lcaac.grammar.parser.LcaLangParser
import com.charleskorn.kaml.Yaml
import com.charleskorn.kaml.decodeFromStream
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.ProgramResult
import com.github.ajalt.clikt.parameters.options.*
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.arguments.default
import com.github.ajalt.clikt.parameters.arguments.help
import com.github.ajalt.clikt.parameters.options.default
import com.github.ajalt.clikt.parameters.options.flag
import com.github.ajalt.clikt.parameters.options.help
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.types.file
import java.io.File

private const val greenTick = "\u2705"
private const val redCross = "\u274C"

@Suppress("MemberVisibilityCanBePrivate", "DuplicatedCode")
class TestCommand : CliktCommand(name = "test", help = "Run specified tests") {
private val getPath = option("-p", "--path").file(canBeFile = false).default(File(".")).help("Path to root folder.")
val path: File by getPath
val dataSourcePath: File by option("--data-path").file(canBeFile = false)
.defaultLazy { getPath.value }
.help("Path to data folder. Default to root folder.")
val name: String by argument().help("Process name").default("")

private val getProjectPath = option("-p", "--project").file()
.default(File(defaultLcaacFilename))
.help("Path to project folder or yaml file.")
val projectPath: File by getProjectPath

val file: File? by option("-f", "--file").file(canBeDir = false)
.help("""
.help("""
CSV file with parameter values.
Example: `lcaac assess <process name> -f params.csv`.
""".trimIndent())
val showSuccess: Boolean by option("--show-success").flag(default = false).help("Show successful assertions")

override fun run() {
val files = lcaFiles(path)
val (workingDirectory, lcaacConfigFile) = parseProjectPath(projectPath)

val config = if (lcaacConfigFile.exists()) projectPath.inputStream().use {
Yaml.default.decodeFromStream(LcaacConfig.serializer(), it)
}
else LcaacConfig()

val ops = BasicOperations
val sourceOps = DefaultDataSourceOperations(config, ops, workingDirectory.path)

val files = lcaFiles(workingDirectory)
val symbolTable = Loader(ops).load(files, listOf(LoaderOption.WITH_PRELUDE))
val mapper = CoreTestMapper()
val cases = files
.flatMap { it.testDefinition() }
.map { mapper.test(it) }
.filter { name.isBlank() || it.name == name }
val runner = BasicTestRunner<LcaLangParser.TestDefinitionContext>(
symbolTable,
CsvSourceOperations(dataSourcePath, ops))
sourceOps,
)
val results = cases.map { runner.run(it) }

results.forEach { result ->
Expand Down
35 changes: 24 additions & 11 deletions cli/src/main/kotlin/ch/kleis/lcaac/cli/cmd/TraceCommand.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package ch.kleis.lcaac.cli.cmd

import ch.kleis.lcaac.core.assessment.ContributionAnalysisProgram
import ch.kleis.lcaac.core.datasource.CsvSourceOperations
import ch.kleis.lcaac.core.config.LcaacConfig
import ch.kleis.lcaac.core.datasource.DefaultDataSourceOperations
import ch.kleis.lcaac.core.lang.evaluator.Evaluator
import ch.kleis.lcaac.core.lang.evaluator.EvaluatorException
import ch.kleis.lcaac.core.lang.evaluator.reducer.DataExpressionReducer
Expand All @@ -14,16 +15,21 @@ import ch.kleis.lcaac.core.math.basic.BasicOperations.toDouble
import ch.kleis.lcaac.core.prelude.Prelude.Companion.sanitize
import ch.kleis.lcaac.grammar.Loader
import ch.kleis.lcaac.grammar.LoaderOption
import com.charleskorn.kaml.Yaml
import com.charleskorn.kaml.decodeFromStream
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.arguments.help
import com.github.ajalt.clikt.parameters.options.*
import com.github.ajalt.clikt.parameters.options.associate
import com.github.ajalt.clikt.parameters.options.default
import com.github.ajalt.clikt.parameters.options.help
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.types.file
import org.apache.commons.csv.CSVFormat
import org.apache.commons.csv.CSVPrinter
import java.io.File

@Suppress("MemberVisibilityCanBePrivate")
@Suppress("MemberVisibilityCanBePrivate", "DuplicatedCode")
class TraceCommand : CliktCommand(name = "trace", help = "Trace the contributions") {
val name: String by argument().help("Process name")
val labels: Map<String, String> by option("-l", "--label")
Expand All @@ -33,11 +39,11 @@ class TraceCommand : CliktCommand(name = "trace", help = "Trace the contribution
Example: lcaac assess <process name> -l model="ABC" -l geo="FR".
""".trimIndent())
.associate()
private val getPath = option("-p", "--path").file(canBeFile = false).default(File(".")).help("Path to root folder.")
val path: File by getPath
val dataSourcePath: File by option("--data-path").file(canBeFile = false)
.defaultLazy { getPath.value }
.help("Path to data folder. Default to root folder.")
private val getProjectPath = option("-p", "--project").file()
.default(File(defaultLcaacFilename))
.help("Path to project folder or yaml file.")
val projectPath: File by getProjectPath

val arguments: Map<String, String> by option("-D", "--parameter")
.help(
"""
Expand All @@ -47,9 +53,15 @@ class TraceCommand : CliktCommand(name = "trace", help = "Trace the contribution
.associate()

override fun run() {
val (workingDirectory, lcaacConfigFile) = parseProjectPath(projectPath)
val config = if (lcaacConfigFile.exists()) projectPath.inputStream().use {
Yaml.default.decodeFromStream(LcaacConfig.serializer(), it)
}
else LcaacConfig()
val ops = BasicOperations
val sourceOps = CsvSourceOperations(dataSourcePath, ops)
val files = lcaFiles(path)
val sourceOps = DefaultDataSourceOperations(config, ops, workingDirectory.path)

val files = lcaFiles(workingDirectory)
val symbolTable = Loader(ops).load(files, listOf(LoaderOption.WITH_PRELUDE))
val evaluator = Evaluator(symbolTable, ops, sourceOps)
val template = symbolTable.getTemplate(name, labels)
Expand Down Expand Up @@ -89,7 +101,8 @@ class TraceCommand : CliktCommand(name = "trace", help = "Trace the contribution
val demandedAmount = demandedProduct.quantity.amount
val demandedUnit = demandedProduct.quantity.unit
val demandedProductName = demandedProduct.product.name
val allocationAmount = (demandedProduct.allocation?.amount?.toDouble() ?: 1.0) * (demandedProduct.allocation?.unit?.scale ?: 1.0)
val allocationAmount = (demandedProduct.allocation?.amount?.toDouble()
?: 1.0) * (demandedProduct.allocation?.unit?.scale ?: 1.0)
observablePorts.asSequence()
.map { row ->
val supply = analysis.supplyOf(row)
Expand Down
15 changes: 14 additions & 1 deletion cli/src/main/kotlin/ch/kleis/lcaac/cli/cmd/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,20 @@ import java.io.File
import java.io.InputStream
import java.lang.Double.parseDouble
import java.nio.file.Files
import kotlin.io.path.Path
import kotlin.io.path.isRegularFile

const val defaultLcaacFilename = "lcaac.yaml"

fun parseProjectPath(path: File): Pair<File, File> {
if (path.isDirectory) {
val configFile = Path(defaultLcaacFilename).toFile()
return path to configFile
}
val workingDirectory = path.parentFile ?: Path(".").toFile()
return workingDirectory to path
}

fun lcaFiles(root: File): Sequence<LcaLangParser.LcaFileContext> {
return Files.walk(root.toPath())
.filter { it.isRegularFile() }
Expand Down Expand Up @@ -84,7 +96,8 @@ fun prepareArguments(
EStringLiteral(it)
} ?: defaultValue.toEStringLiteral()

else -> throw EvaluatorException("datasource '${dataSource.location}': column '${schemaEntry.key}': invalid default value")
else -> throw EvaluatorException("datasource '${dataSource.config.name}': column '${schemaEntry
.key}': invalid default value")
}
}
ERecord(entries)
Expand Down
9 changes: 5 additions & 4 deletions cli/src/main/kotlin/ch/kleis/lcaac/cli/csv/CsvProcessor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@ package ch.kleis.lcaac.cli.csv

import ch.kleis.lcaac.cli.cmd.prepareArguments
import ch.kleis.lcaac.core.assessment.ContributionAnalysisProgram
import ch.kleis.lcaac.core.datasource.CsvSourceOperations
import ch.kleis.lcaac.core.config.LcaacConfig
import ch.kleis.lcaac.core.datasource.DefaultDataSourceOperations
import ch.kleis.lcaac.core.lang.SymbolTable
import ch.kleis.lcaac.core.lang.evaluator.Evaluator
import ch.kleis.lcaac.core.lang.evaluator.EvaluatorException
import ch.kleis.lcaac.core.lang.evaluator.reducer.DataExpressionReducer
import ch.kleis.lcaac.core.math.basic.BasicNumber
import ch.kleis.lcaac.core.math.basic.BasicOperations
import java.io.File

class CsvProcessor(
path: File,
config: LcaacConfig,
private val symbolTable: SymbolTable<BasicNumber>,
workingDirectory: String,
) {
private val ops = BasicOperations
private val sourceOps = CsvSourceOperations(path, ops)
private val sourceOps = DefaultDataSourceOperations(config, ops, workingDirectory)
private val dataReducer = DataExpressionReducer(symbolTable.data, symbolTable.dataSources, ops, sourceOps)
private val evaluator = Evaluator(symbolTable, ops, sourceOps)

Expand Down
Loading

0 comments on commit 9416eb8

Please sign in to comment.