Skip to content

Commit

Permalink
fix: pr suggesstions
Browse files Browse the repository at this point in the history
  • Loading branch information
Angel-Dijoux committed Nov 14, 2024
1 parent d6b95e6 commit ec715ec
Show file tree
Hide file tree
Showing 10 changed files with 242 additions and 74 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ mime = "0.3"
open = "5.0"
owo-colors = { version = "4.0", features = ["supports-colors"] }
passterm = "2.0"
pyo3 = { version = "0.20", features = ["serde"]}
pyo3 = { version = "0.20", features = ["serde"] }
pyo3-asyncio = { version = "0.20", features = ["attributes", "tokio-runtime"] }
rand = "0.8"
reqwest = { version = "0.11", default-features = false, features = [
Expand Down
24 changes: 11 additions & 13 deletions src/commands/new/use_case.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use std::path::{Path, PathBuf};
use std::path::PathBuf;

use aqora_template::UseCaseTemplate;
use clap::Args;
use graphql_client::GraphQLQuery;
use indicatif::ProgressBar;
use serde::Serialize;

use crate::error::{self, Error, Result};
use crate::error::{self, Result};
use crate::graphql_client::{custom_scalars::*, GraphQLClient};

use super::GlobalArgs;
Expand Down Expand Up @@ -53,20 +53,18 @@ pub async fn use_case(args: UseCase, global: GlobalArgs) -> Result<()> {
.competition(args.competition)
.title(competition.title)
.render(&dest)
.map_err(|e| format_permission_error("create use case", &dest, &e))?;
.map_err(|e| {
error::user(
&format!("Failed to create use case at '{}': {}", dest.display(), e),
&format!(
"Make sure you have the correct permissions for '{}'",
dest.display()
),
)
})?;
pb.finish_with_message(format!(
"Created use case in directory '{}'",
dest.display()
));
Ok(())
}

fn format_permission_error(action: &str, dest: &Path, error: &impl std::fmt::Display) -> Error {
error::user(
&format!("Failed to {} at '{}': {}", action, dest.display(), error),
&format!(
"Make sure you have the correct permissions for '{}'",
dest.display()
),
)
}
45 changes: 26 additions & 19 deletions src/commands/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
ipynb::{convert_submission_notebooks, convert_use_case_notebooks},
print::wrap_python_output,
python::LastRunResult,
readme::get_readme_path,
};
use aqora_config::{AqoraUseCaseConfig, PyProject};
use aqora_runner::{
Expand Down Expand Up @@ -230,21 +231,24 @@ fn run_pipeline(

async fn update_score_badge_in_file(
path: PathBuf,
competition: impl AsRef<str>,
competition: Option<String>,
score: &Py<PyAny>,
url: Url,
) -> Result<()> {
let badge_url = build_shield_score_badge(
score,
url.join(&format!("competitions/{}", competition.as_ref()))?,
url.join(&competition.map_or_else(
|| "competitons".to_string(),
|name| format!("competitions/{}", name),
))?,
)?;
with_locked_file(
|file| {
async move {
let mut contents = String::new();
file.read_to_string(&mut contents).await?;
let updated_content = regex_replace_all!(
r"(?:<!--- score_badge -->)|(!\[Aqora Score Badge\]\([^\)]+\))",
r"(?:<!--\s*aqora:score:start\s*-->.*?<!--\s*aqora:score:end\s*-->)|(!\[Aqora Score Badge\]\([^\)]+\))",
&contents,
badge_url.clone()
);
Expand Down Expand Up @@ -272,14 +276,17 @@ pub async fn run_submission_tests(
.aqora()
.and_then(|aqora| aqora.as_submission())
.ok_or_else(|| error::user("Submission config is not valid", ""))?;
let project_readme_path = project
.project
.as_ref()
.and_then(|p| p.readme.as_ref())
.and_then(|readme| match readme {
aqora_config::ReadMe::RelativePath(path) => Some(path),
aqora_config::ReadMe::Table { file, .. } => file.as_ref(),
});
let project_readme_path = get_readme_path(
&global.project,
project.project.as_ref().and_then(|p| p.readme.as_ref()),
)
.await
.map_err(|err| {
error::user(
&format!("Could not read readme: {}", err),
"Please make sure the readme is valid",
)
})?;
let use_case_toml_path = project_use_case_toml_path(&global.project);
let data_path = project_data_dir(&global.project, "data");
if !use_case_toml_path.exists() || !data_path.exists() {
Expand Down Expand Up @@ -387,11 +394,10 @@ pub async fn run_submission_tests(
})
.collect::<Result<Vec<_>>>()?;

let competition = modified_use_case.clone().competition.unwrap_or_default();
let (num_inputs, aggregated) = run_pipeline(
&env,
RunPipelineConfig {
use_case: modified_use_case,
use_case: modified_use_case.clone(),
pipeline_config: config,
tests: tests.clone(),
last_run_dir,
Expand All @@ -408,14 +414,15 @@ pub async fn run_submission_tests(
"Score".if_supports_color(OwoStream::Stdout, |text| { text.bold() }),
score
));
let path = global.project.join(project_readme_path.ok_or_else(|| {
error::user(
"Project must contain a README file",
"See : https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#readme",
if let Some(path) = project_readme_path {
update_score_badge_in_file(
global.project.join(path),
modified_use_case.competition,
&score,
global.aqora_url()?,
)
})?);
update_score_badge_in_file(path, &competition, &score, global.aqora_url().unwrap())
.await?;
};
pipeline_pb.finish_and_clear();
Ok(score)
}
Expand Down
79 changes: 41 additions & 38 deletions src/readme.rs
Original file line number Diff line number Diff line change
@@ -1,82 +1,85 @@
use aqora_config::ReadMe;
use mime::Mime;
use std::path::Path;
use std::path::{Path, PathBuf};
use thiserror::Error;

#[derive(Debug, Error)]
pub enum ReadMeError {
pub enum ReadmeError {
#[error(transparent)]
Io(#[from] std::io::Error),
#[error("Readme not found")]
#[error("README not found")]
NotFound,
#[error("Readme content type not supported. Only markdown and plaintext supported")]
#[error("README content type not supported. Only markdown and plaintext supported")]
ContentTypeNotSupported,
}

pub async fn read_readme(
pub async fn get_readme_path(
project_dir: impl AsRef<Path>,
readme: Option<&ReadMe>,
) -> Result<Option<String>, ReadMeError> {
) -> Result<Option<PathBuf>, ReadmeError> {
let path = match readme {
Some(ReadMe::Table {
ref file,
text,
text: _,
content_type,
}) => {
let path: Option<&Path> = file.as_deref().map(str::as_ref);
if let Some(content_type) = content_type {
let mime: Mime = content_type
.parse()
.map_err(|_| ReadMeError::ContentTypeNotSupported)?;
.map_err(|_| ReadmeError::ContentTypeNotSupported)?;
if !(mime.type_() == mime::TEXT
&& (mime.subtype() == mime::PLAIN || mime.subtype() == "markdown"))
{
return Err(ReadMeError::ContentTypeNotSupported);
return Err(ReadmeError::ContentTypeNotSupported);
}
}
if let Some(text) = text {
return Ok(Some(text.to_owned()));
}
path
path.map(|p| p.to_path_buf())
}
Some(ReadMe::RelativePath(ref path)) => Some(path.as_ref()),
Some(ReadMe::RelativePath(ref path)) => Some(PathBuf::from(path)),
None => None,
};
let path = if let Some(path) = path {
project_dir.as_ref().join(path)
} else {
let mut dir = tokio::fs::read_dir(&project_dir).await?;
let mut path = None;
while let Some(entry) = dir.next_entry().await? {
match entry.file_name().to_string_lossy().to_lowercase().as_str() {
"readme.md" | "readme.txt" => {}
_ => continue,
}
let metadata = entry.metadata().await?;
if !metadata.is_file() {
continue;
}
path = Some(entry.path());
break;

if let Some(path) = path {
return Ok(Some(path));
}

let mut dir = tokio::fs::read_dir(&project_dir).await?;
while let Some(entry) = dir.next_entry().await? {
match entry.file_name().to_string_lossy().to_lowercase().as_str() {
"readme.md" | "readme.txt" => {}
_ => continue,
}
if let Some(path) = path {
path
} else {
return Ok(None);
let metadata = entry.metadata().await?;
if metadata.is_file() {
return Ok(Some(entry.path()));
}
}

Ok(None)
}

pub async fn read_readme(
project_dir: impl AsRef<Path>,
readme: Option<&ReadMe>,
) -> Result<Option<String>, ReadmeError> {
let path = match get_readme_path(project_dir, readme).await? {
Some(path) => path,
None => return Ok(None),
};

match path
.extension()
.map(|ext| ext.to_string_lossy().to_lowercase())
.as_deref()
{
Some("md") | Some("txt") | None => {}
_ => {
return Err(ReadMeError::ContentTypeNotSupported);
}
_ => return Err(ReadmeError::ContentTypeNotSupported),
}

if !tokio::fs::try_exists(&path).await? {
return Err(ReadMeError::NotFound);
return Err(ReadmeError::NotFound);
}

Ok(Some(tokio::fs::read_to_string(path).await?))
}
2 changes: 0 additions & 2 deletions template/assets/use_case/README.md.hbs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
<!--- score_badge -->

![Aqora badge](https://img.shields.io/badge/aqora-4328e5?logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAIWSURBVHgBjZI%2FbBJxFMe%2F7%2F5x3BE9D2waCeZiEwNxECcbHSwmGt3qZkwcnB2Q0cFAR6d2Mk6KgcHNQSeHwmJaJ06XYmICprEq1PbaUk7ugJ93p1ToYPpb3svv5fve5%2F2%2BP8IRjqqdS4MGiwDTQFx1f2stx4%2BKip7Mi3KsKIVj87Kq7zj2z%2FqoJoajK15IAzTtxVlRiREFIi2ZB6Hg57yoIHEpC0k7lTGL16oRLTk3JFQmGcjkgkA0H4gEBWfSWShyHFIoet%2B%2FEyCbh9GJ2B%2Bhx24JvILU2SwiYhyCA4Q5feb6I3bRskyLGMuN6ZriEAsBqo9z3nhYkY%2FF0Q8BQznUjSQuvBseV9sshNzbArU0zdAAWbOsejOYOmpzY7ZiSJL%2BhMJKQoqeXh%2BqkuOogCuj48h4tlyg5Qncw%2Fz3brKrjoLbfRlTfQWwQ46w6zRmHM7edn5Zd8xi5t9EH8MVVUN0B5aPcvcWmwKHxX2%2Bc7Jtm5ddsaf4K2z9WEXrYznT2axXOVlLGg7JNdYf1BxCI6ynHpReUYvv4aVrfU1wdk8ResDel1V8r5XBBsj7wzie8NyLxgE7Q94nKL6h17B3Pglet%2B2N91hfK0%2BsxLEx0V9rgtfzM9feXdpsr6DRLI2V8SLw3PtmJ7xN58Z92rPqC37yeaPU7Pa%2FffDq0wSyGKPHXav%2B9OBxVD215HW64k1vSp7ZI6%2F%2Bd34DKO3EcR6BAbMAAAAASUVORK5CYII%3D&labelColor=eceafc&link=https%3A%2F%2Faqora.io%2Fcompetitions%2F{{competition}}%2F)

## {{title}}
Expand Down
2 changes: 1 addition & 1 deletion template/assets/use_case/template/README.md.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!--- score_badge -->
<!-- aqora:score:start --><!-- aqora:score:end -->

![Aqora badge](https://img.shields.io/badge/aqora-4328e5?logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAIWSURBVHgBjZI%2FbBJxFMe%2F7%2F5x3BE9D2waCeZiEwNxECcbHSwmGt3qZkwcnB2Q0cFAR6d2Mk6KgcHNQSeHwmJaJ06XYmICprEq1PbaUk7ugJ93p1ToYPpb3svv5fve5%2F2%2BP8IRjqqdS4MGiwDTQFx1f2stx4%2BKip7Mi3KsKIVj87Kq7zj2z%2FqoJoajK15IAzTtxVlRiREFIi2ZB6Hg57yoIHEpC0k7lTGL16oRLTk3JFQmGcjkgkA0H4gEBWfSWShyHFIoet%2B%2FEyCbh9GJ2B%2Bhx24JvILU2SwiYhyCA4Q5feb6I3bRskyLGMuN6ZriEAsBqo9z3nhYkY%2FF0Q8BQznUjSQuvBseV9sshNzbArU0zdAAWbOsejOYOmpzY7ZiSJL%2BhMJKQoqeXh%2BqkuOogCuj48h4tlyg5Qncw%2Fz3brKrjoLbfRlTfQWwQ46w6zRmHM7edn5Zd8xi5t9EH8MVVUN0B5aPcvcWmwKHxX2%2Bc7Jtm5ddsaf4K2z9WEXrYznT2axXOVlLGg7JNdYf1BxCI6ynHpReUYvv4aVrfU1wdk8ResDel1V8r5XBBsj7wzie8NyLxgE7Q94nKL6h17B3Pglet%2B2N91hfK0%2BsxLEx0V9rgtfzM9feXdpsr6DRLI2V8SLw3PtmJ7xN58Z92rPqC37yeaPU7Pa%2FffDq0wSyGKPHXav%2B9OBxVD215HW64k1vSp7ZI6%2F%2Bd34DKO3EcR6BAbMAAAAASUVORK5CYII%3D&labelColor=eceafc&link=https%3A%2F%2Faqora.io%2Fcompetitions%2F{{competition}}%2F)

Expand Down
55 changes: 55 additions & 0 deletions test/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]

# C extensions
*.so

# Distribution / packaging
bin/
build/
develop-eggs/
dist/
eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
.tox/
.coverage
.cache
nosetests.xml
coverage.xml

# Translations
*.mo

# Mr Developer
.mr.developer.cfg
.project
.pydevproject

# Rope
.ropeproject

# Django stuff:
*.log
*.pot

# Sphinx documentation
docs/_build/

# aqora
.aqora
.venv
__aqora__/
19 changes: 19 additions & 0 deletions test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
![Aqora Score Badge](https://img.shields.io/badge/score-0-4328e5?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAIWSURBVHgBjZI/bBJxFMe//5x3BE9D2waCeZiEwNxECcbHSwmGt3qZkwcnB2Q0cFAR6d2Mk6KgcHNQSeHwmJaJ06XYmICprEq1PbaUk7ugJ93p1ToYPpb3svv5fve5/2+P8IRjqqdS4MGiwDTQFx1f2stx4+Kip7Mi3KsKIVj87Kq7zj2z/qoJoajK15IAzTtxVlRiREFIi2ZB6Hg57yoIHEpC0k7lTGL16oRLTk3JFQmGcjkgkA0H4gEBWfSWShyHFIoet+/EyCbh9GJ2B+hx24JvILU2SwiYhyCA4Q5feb6I3bRskyLGMuN6ZriEAsBqo9z3nhYkY/F0Q8BQznUjSQuvBseV9sshNzbArU0zdAAWbOsejOYOmpzY7ZiSJL+hMJKQoqeXh+qkuOogCuj48h4tlyg5Qncw/z3brKrjoLbfRlTfQWwQ46w6zRmHM7edn5Zd8xi5t9EH8MVVUN0B5aPcvcWmwKHxX2+c7Jtm5ddsaf4K2z9WEXrYznT2axXOVlLGg7JNdYf1BxCI6ynHpReUYvv4aVrfU1wdk8ResDel1V8r5XBBsj7wzie8NyLxgE7Q94nKL6h17B3Pglet+2N91hfK0+sxLEx0V9rgtfzM9feXdpsr6DRLI2V8SLw3PtmJ7xN58Z92rPqC37yeaPU7Pa/ffDq0wSyGKPHXav+9OBxVD215HW64k1vSp7ZI6/+d34DKO3EcR6BAbMAAAAASUVORK5CYII=&labelColor=eceafc&link=http://localhost:8080/competitions/test)
rr
![Aqora badge](https://img.shields.io/badge/aqora-4328e5?logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAIWSURBVHgBjZI%2FbBJxFMe%2F7%2F5x3BE9D2waCeZiEwNxECcbHSwmGt3qZkwcnB2Q0cFAR6d2Mk6KgcHNQSeHwmJaJ06XYmICprEq1PbaUk7ugJ93p1ToYPpb3svv5fve5%2F2%2BP8IRjqqdS4MGiwDTQFx1f2stx4%2BKip7Mi3KsKIVj87Kq7zj2z%2FqoJoajK15IAzTtxVlRiREFIi2ZB6Hg57yoIHEpC0k7lTGL16oRLTk3JFQmGcjkgkA0H4gEBWfSWShyHFIoet%2B%2FEyCbh9GJ2B%2Bhx24JvILU2SwiYhyCA4Q5feb6I3bRskyLGMuN6ZriEAsBqo9z3nhYkY%2FF0Q8BQznUjSQuvBseV9sshNzbArU0zdAAWbOsejOYOmpzY7ZiSJL%2BhMJKQoqeXh%2BqkuOogCuj48h4tlyg5Qncw%2Fz3brKrjoLbfRlTfQWwQ46w6zRmHM7edn5Zd8xi5t9EH8MVVUN0B5aPcvcWmwKHxX2%2Bc7Jtm5ddsaf4K2z9WEXrYznT2axXOVlLGg7JNdYf1BxCI6ynHpReUYvv4aVrfU1wdk8ResDel1V8r5XBBsj7wzie8NyLxgE7Q94nKL6h17B3Pglet%2B2N91hfK0%2BsxLEx0V9rgtfzM9feXdpsr6DRLI2V8SLw3PtmJ7xN58Z92rPqC37yeaPU7Pa%2FffDq0wSyGKPHXav%2B9OBxVD215HW64k1vSp7ZI6%2F%2Bd34DKO3EcR6BAbMAAAAASUVORK5CYII%3D&labelColor=eceafc&link=https%3A%2F%2Faqora.io%2Fcompetitions%2Ftest%2F)

# test Submission

You can find a template notebook in `submission/solution.ipynb`.
Fill in your solution. You can run the notebook locally to test your
solution by running the following in the terminal

```bash
aqora test
```

And when you are ready to submit run

```bash
aqora upload
```
28 changes: 28 additions & 0 deletions test/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[project]
name = "submission"
version = "0.1.3"
requires-python = ">=3.8"
readme = "README.md"

# You can add dependencies with `aqora add`
dependencies = []

[build-system]
requires = [
"uv>=0.4.20",
"setuptools>=75",
"wheel>=0.44",
]
build-backend = "setuptools.build_meta"

[tool.setuptools.packages.find]
where = ["."]
[tool.setuptools.package-data]
submission = ["*"]

[tool.aqora]
type = "submission"
competition = "test"

[tool.aqora.refs]
solution = { path = "submission.solution", notebook = true }
Loading

0 comments on commit ec715ec

Please sign in to comment.