Skip to content

Commit

Permalink
feat: Refine the constructor of Project to hide repositories (#1194)
Browse files Browse the repository at this point in the history
Closes #1160

This PR intends to ease the project API by centralizing all the action
in the constructor.

To note:
- Remove all actions from the CLI except "launch UI", which implicitly
create the specified project.
- Rename the command `skore` to `skore-ui`.
- Release the constraints on project name.
- Remove all project management scripts and `open` function in favor of
the project class constructor.
- Create implicitly the project when calling the constructor.
- Add project `clear` function to allow user to **explicitly** clear a
project.

---

```python
# create project

import skore
project = skore.Project("project.skore")
```
```python
# work on existing project

import skore
project = skore.Project("project.skore", exist_ok=True)
```
```python
# work on existing project and clear explicitly

import skore
project = skore.Project("project.skore", exist_ok=True)
project.clear()
```
```python
# work on existing project, but without knowing it

import skore
project = skore.Project("project.skore")

---------------------------------------------------------------------------
FileExistsError                           Traceback (most recent call last)
[...]
FileExistsError: Project 'project.skore' already exists.
```
  • Loading branch information
thomass-dev authored Jan 29, 2025
1 parent 66ca391 commit a8301b8
Show file tree
Hide file tree
Showing 34 changed files with 228 additions and 837 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ You can find information on the latest version [here](https://anaconda.org/conda
1. From your Python code, create and load a skore project:
```python
import skore
my_project = skore.open("my_project", create=True)
my_project = skore.Project("my_project")
```
This will create a skore project directory named `my_project.skore` in your current working directory.

Expand Down
2 changes: 1 addition & 1 deletion examples/getting_started/plot_quick_start.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
temp_dir_path = Path(temp_dir.name)
os.chdir(temp_dir_path)
# sphinx_gallery_end_ignore
my_project = skore.open("my_project", create=True)
my_project = skore.Project("my_project")

# %%
# This will create a skore project directory named ``my_project.skore`` in your
Expand Down
2 changes: 1 addition & 1 deletion examples/getting_started/plot_skore_getting_started.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
temp_dir_path = Path(temp_dir.name)
os.chdir(temp_dir_path)
# sphinx_gallery_end_ignore
my_project = skore.open("my_project", create=True)
my_project = skore.Project("my_project")

# %%
# Now that the project exists, we can write some Python code (in the same
Expand Down
2 changes: 1 addition & 1 deletion examples/model_evaluation/plot_cross_validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
temp_dir_path = Path(temp_dir.name)
os.chdir(temp_dir_path)
# sphinx_gallery_end_ignore
my_project = skore.open("my_project", create=True)
my_project = skore.Project("my_project")


# %%
Expand Down
2 changes: 1 addition & 1 deletion examples/skore_project/plot_tracking_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
os.chdir(temp_dir_path)
# sphinx_gallery_end_ignore

my_project = skore.open("my_project", create=True)
my_project = skore.Project("my_project")

# %%
# Tracking an integer
Expand Down
2 changes: 1 addition & 1 deletion examples/skore_project/plot_working_with_projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
temp_dir_path = Path(temp_dir.name)
os.chdir(temp_dir_path)
# sphinx_gallery_end_ignore
my_project = skore.open("my_project", create=True)
my_project = skore.Project("my_project")

# %%
# Storing integers
Expand Down
2 changes: 1 addition & 1 deletion examples/use_cases/plot_employee_salaries.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
temp_dir_path = Path(temp_dir.name)
os.chdir(temp_dir_path)
# sphinx_gallery_end_ignore
my_project = skore.open("my_project", create=True)
my_project = skore.Project("my_project")

# %%
#
Expand Down
2 changes: 1 addition & 1 deletion skore/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Issues = "https://github.com/probabl-ai/skore/issues"
"Release notes" = "https://github.com/probabl-ai/skore/releases"

[project.scripts]
skore = "skore.__main__:main"
skore-ui = "skore.__main__:main"

[build-system]
requires = ["hatchling"]
Expand Down
3 changes: 1 addition & 2 deletions skore/src/skore/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from rich.console import Console
from rich.theme import Theme

from skore.project import Project, open
from skore.project import Project
from skore.sklearn import (
CrossValidationReport,
CrossValidationReporter,
Expand All @@ -19,7 +19,6 @@
"CrossValidationReporter",
"CrossValidationReport",
"EstimatorReport",
"open",
"Project",
"show_versions",
"train_test_split",
Expand Down
119 changes: 29 additions & 90 deletions skore/src/skore/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,35 @@
from importlib.metadata import version

from skore.cli.color_format import ColorArgumentParser
from skore.cli.launch_dashboard import __launch
from skore.cli.quickstart_command import __quickstart
from skore.project.create import _create
from skore.ui.launch import launch


def cli(args: list[str]):
"""CLI for Skore."""
parser = ColorArgumentParser(prog="skore")
def argumentparser():
"""Argument parser for the Skore CLI."""
parser = ColorArgumentParser(
prog="skore-ui",
description="Launch the skore UI on a defined skore project.",
)

parser.add_argument(
"--version", action="version", version=f"%(prog)s {version('skore')}"
"--version",
action="version",
version=f"%(prog)s {version('skore')}",
)

subparsers = parser.add_subparsers(dest="subcommand")

parser_launch = subparsers.add_parser("launch", help="Launch the web UI")
parser_launch.add_argument(
parser.add_argument(
"project_name",
help="the name or path of the project to open",
help="the name or path of the project to be created or opened",
)
parser_launch.add_argument(

parser.add_argument(
"--port",
type=int,
help="the port at which to bind the UI server (default: %(default)s)",
default=22140,
)
parser_launch.add_argument(

parser.add_argument(
"--open-browser",
action=argparse.BooleanOptionalAction,
help=(
Expand All @@ -39,87 +41,24 @@ def cli(args: list[str]):
),
default=True,
)
parser_launch.add_argument(
"--verbose",
action="store_true",
help="increase logging verbosity",
)

parser_create = subparsers.add_parser("create", help="Create a project")
parser_create.add_argument(
"project_name",
nargs="?",
help="the name or path of the project to create (default: %(default)s)",
default="project",
)
parser_create.add_argument(
"--overwrite",
action="store_true",
help="overwrite an existing project with the same name",
)
parser_create.add_argument(
parser.add_argument(
"--verbose",
action="store_true",
help="increase logging verbosity",
)

parser_quickstart = subparsers.add_parser(
"quickstart", help='Create a "project.skore" file and start the UI'
)
parser_quickstart.add_argument(
"project_name",
nargs="?",
help="the name or path of the project to create (default: %(default)s)",
default="project",
)
parser_quickstart.add_argument(
"--overwrite",
action="store_true",
help="overwrite an existing project with the same name",
)
parser_quickstart.add_argument(
"--port",
type=int,
help="the port at which to bind the UI server (default: %(default)s)",
default=22140,
)
parser_quickstart.add_argument(
"--open-browser",
action=argparse.BooleanOptionalAction,
help=(
"whether to automatically open a browser tab showing the web UI "
"(default: %(default)s)"
),
default=True,
)
parser_quickstart.add_argument(
"--verbose",
action="store_true",
help="increase logging verbosity",
)
return parser

parsed_args: argparse.Namespace = parser.parse_args(args)

if parsed_args.subcommand == "launch":
__launch(
project_name=parsed_args.project_name,
port=parsed_args.port,
open_browser=parsed_args.open_browser,
verbose=parsed_args.verbose,
)
elif parsed_args.subcommand == "create":
_create(
project_name=parsed_args.project_name,
overwrite=parsed_args.overwrite,
verbose=parsed_args.verbose,
)
elif parsed_args.subcommand == "quickstart":
__quickstart(
project_name=parsed_args.project_name,
overwrite=parsed_args.overwrite,
port=parsed_args.port,
open_browser=parsed_args.open_browser,
verbose=parsed_args.verbose,
)
else:
parser.print_help()
def cli(args: list[str]):
"""CLI for Skore."""
parser = argumentparser()
arguments = parser.parse_args(args)

launch(
project_name=arguments.project_name,
port=arguments.port,
open_browser=arguments.open_browser,
verbose=arguments.verbose,
)
10 changes: 10 additions & 0 deletions skore/src/skore/cli/color_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,13 @@ def print_help(self, file=None):
"""Print the help message."""
console = Console(file=file)
console.print(self.format_help())

def error(self, message):
"""Print error message with Rich formatting and exit."""
console = Console(stderr=True, theme=skore_console_theme)
console.print(f"[red bold]error:[/red bold] {message}")

console.print(f"\n{self.format_usage()}")

console.print("\nFor more information, try '[cyan]--help[/cyan]'")
self.exit(2)
56 changes: 0 additions & 56 deletions skore/src/skore/cli/quickstart_command.py

This file was deleted.

4 changes: 4 additions & 0 deletions skore/src/skore/persistence/view/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
"""Implement view primitives and storage."""

from .view import View

__all__ = ["View"]
2 changes: 0 additions & 2 deletions skore/src/skore/project/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
"""Alias top level function and class of the project submodule."""

from .open import open
from .project import Project

__all__ = [
"open",
"Project",
]
Loading

0 comments on commit a8301b8

Please sign in to comment.