Skip to content

Commit

Permalink
Remove flower.toml file from Flower App (#3279)
Browse files Browse the repository at this point in the history
  • Loading branch information
charlesbvll authored Apr 17, 2024
1 parent 7f88d5f commit e2721fc
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Utility to validate the `flower.toml` file."""
"""Utility to validate the `pyproject.toml` file."""

import os
from typing import Any, Dict, List, Optional, Tuple
Expand All @@ -25,7 +25,7 @@
def load_and_validate_with_defaults(
path: Optional[str] = None,
) -> Tuple[Optional[Dict[str, Any]], List[str], List[str]]:
"""Load and validate flower.toml as dict.
"""Load and validate pyproject.toml as dict.
Returns
-------
Expand All @@ -37,7 +37,7 @@ def load_and_validate_with_defaults(

if config is None:
errors = [
"Project configuration could not be loaded. flower.toml does not exist."
"Project configuration could not be loaded. pyproject.toml does not exist."
]
return (None, errors, [])

Expand All @@ -58,10 +58,10 @@ def load_and_validate_with_defaults(


def load(path: Optional[str] = None) -> Optional[Dict[str, Any]]:
"""Load flower.toml and return as dict."""
"""Load pyproject.toml and return as dict."""
if path is None:
cur_dir = os.getcwd()
toml_path = os.path.join(cur_dir, "flower.toml")
toml_path = os.path.join(cur_dir, "pyproject.toml")
else:
toml_path = path

Expand All @@ -74,7 +74,7 @@ def load(path: Optional[str] = None) -> Optional[Dict[str, Any]]:


def validate_fields(config: Dict[str, Any]) -> Tuple[bool, List[str], List[str]]:
"""Validate flower.toml fields."""
"""Validate pyproject.toml fields."""
errors = []
warnings = []

Expand Down Expand Up @@ -106,7 +106,7 @@ def validate_fields(config: Dict[str, Any]) -> Tuple[bool, List[str], List[str]]


def validate(config: Dict[str, Any]) -> Tuple[bool, List[str], List[str]]:
"""Validate flower.toml."""
"""Validate pyproject.toml."""
is_valid, errors, warnings = validate_fields(config)

if not is_valid:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,29 @@
import textwrap
from typing import Any, Dict

from .flower_toml import load, validate, validate_fields
from .config_utils import load, validate, validate_fields


def test_load_flower_toml_load_from_cwd(tmp_path: str) -> None:
def test_load_pyproject_toml_load_from_cwd(tmp_path: str) -> None:
"""Test if load_template returns a string."""
# Prepare
flower_toml_content = """
pyproject_toml_content = """
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "fedgpt"
version = "1.0.0"
description = ""
authors = [
{ name = "The Flower Authors", email = "[email protected]" },
]
license = {text = "Apache License (2.0)"}
dependencies = [
"flwr[simulation]>=1.8.0,<2.0",
"numpy>=1.21.0",
]
[flower.components]
serverapp = "fedgpt.server:app"
Expand All @@ -39,8 +53,14 @@ def test_load_flower_toml_load_from_cwd(tmp_path: str) -> None:
count = 10 # optional
"""
expected_config = {
"build-system": {"build-backend": "hatchling.build", "requires": ["hatchling"]},
"project": {
"name": "fedgpt",
"version": "1.0.0",
"description": "",
"authors": [{"email": "[email protected]", "name": "The Flower Authors"}],
"license": {"text": "Apache License (2.0)"},
"dependencies": ["flwr[simulation]>=1.8.0,<2.0", "numpy>=1.21.0"],
},
"flower": {
"components": {
Expand All @@ -60,8 +80,8 @@ def test_load_flower_toml_load_from_cwd(tmp_path: str) -> None:
try:
# Change into the temporary directory
os.chdir(tmp_path)
with open("flower.toml", "w", encoding="utf-8") as f:
f.write(textwrap.dedent(flower_toml_content))
with open("pyproject.toml", "w", encoding="utf-8") as f:
f.write(textwrap.dedent(pyproject_toml_content))

# Execute
config = load()
Expand All @@ -72,12 +92,26 @@ def test_load_flower_toml_load_from_cwd(tmp_path: str) -> None:
os.chdir(origin)


def test_load_flower_toml_from_path(tmp_path: str) -> None:
def test_load_pyproject_toml_from_path(tmp_path: str) -> None:
"""Test if load_template returns a string."""
# Prepare
flower_toml_content = """
pyproject_toml_content = """
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "fedgpt"
version = "1.0.0"
description = ""
authors = [
{ name = "The Flower Authors", email = "[email protected]" },
]
license = {text = "Apache License (2.0)"}
dependencies = [
"flwr[simulation]>=1.8.0,<2.0",
"numpy>=1.21.0",
]
[flower.components]
serverapp = "fedgpt.server:app"
Expand All @@ -90,8 +124,14 @@ def test_load_flower_toml_from_path(tmp_path: str) -> None:
count = 10 # optional
"""
expected_config = {
"build-system": {"build-backend": "hatchling.build", "requires": ["hatchling"]},
"project": {
"name": "fedgpt",
"version": "1.0.0",
"description": "",
"authors": [{"email": "[email protected]", "name": "The Flower Authors"}],
"license": {"text": "Apache License (2.0)"},
"dependencies": ["flwr[simulation]>=1.8.0,<2.0", "numpy>=1.21.0"],
},
"flower": {
"components": {
Expand All @@ -111,20 +151,20 @@ def test_load_flower_toml_from_path(tmp_path: str) -> None:
try:
# Change into the temporary directory
os.chdir(tmp_path)
with open("flower.toml", "w", encoding="utf-8") as f:
f.write(textwrap.dedent(flower_toml_content))
with open("pyproject.toml", "w", encoding="utf-8") as f:
f.write(textwrap.dedent(pyproject_toml_content))

# Execute
config = load(path=os.path.join(tmp_path, "flower.toml"))
config = load(path=os.path.join(tmp_path, "pyproject.toml"))

# Assert
assert config == expected_config
finally:
os.chdir(origin)


def test_validate_flower_toml_fields_empty() -> None:
"""Test that validate_flower_toml_fields fails correctly."""
def test_validate_pyproject_toml_fields_empty() -> None:
"""Test that validate_pyproject_toml_fields fails correctly."""
# Prepare
config: Dict[str, Any] = {}

Expand All @@ -137,8 +177,8 @@ def test_validate_flower_toml_fields_empty() -> None:
assert len(warnings) == 0


def test_validate_flower_toml_fields_no_flower() -> None:
"""Test that validate_flower_toml_fields fails correctly."""
def test_validate_pyproject_toml_fields_no_flower() -> None:
"""Test that validate_pyproject_toml_fields fails correctly."""
# Prepare
config = {
"project": {
Expand All @@ -159,8 +199,8 @@ def test_validate_flower_toml_fields_no_flower() -> None:
assert len(warnings) == 0


def test_validate_flower_toml_fields_no_flower_components() -> None:
"""Test that validate_flower_toml_fields fails correctly."""
def test_validate_pyproject_toml_fields_no_flower_components() -> None:
"""Test that validate_pyproject_toml_fields fails correctly."""
# Prepare
config = {
"project": {
Expand All @@ -182,8 +222,8 @@ def test_validate_flower_toml_fields_no_flower_components() -> None:
assert len(warnings) == 0


def test_validate_flower_toml_fields_no_server_and_client_app() -> None:
"""Test that validate_flower_toml_fields fails correctly."""
def test_validate_pyproject_toml_fields_no_server_and_client_app() -> None:
"""Test that validate_pyproject_toml_fields fails correctly."""
# Prepare
config = {
"project": {
Expand All @@ -205,8 +245,8 @@ def test_validate_flower_toml_fields_no_server_and_client_app() -> None:
assert len(warnings) == 0


def test_validate_flower_toml_fields() -> None:
"""Test that validate_flower_toml_fields succeeds correctly."""
def test_validate_pyproject_toml_fields() -> None:
"""Test that validate_pyproject_toml_fields succeeds correctly."""
# Prepare
config = {
"project": {
Expand All @@ -228,8 +268,8 @@ def test_validate_flower_toml_fields() -> None:
assert len(warnings) == 0


def test_validate_flower_toml() -> None:
"""Test that validate_flower_toml succeeds correctly."""
def test_validate_pyproject_toml() -> None:
"""Test that validate_pyproject_toml succeeds correctly."""
# Prepare
config = {
"project": {
Expand All @@ -256,8 +296,8 @@ def test_validate_flower_toml() -> None:
assert not warnings


def test_validate_flower_toml_fail() -> None:
"""Test that validate_flower_toml fails correctly."""
def test_validate_pyproject_toml_fail() -> None:
"""Test that validate_pyproject_toml fails correctly."""
# Prepare
config = {
"project": {
Expand Down
1 change: 0 additions & 1 deletion src/py/flwr/cli/new/new.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ def new(
# List of files to render
files = {
"README.md": {"template": "app/README.md.tpl"},
"flower.toml": {"template": "app/flower.toml.tpl"},
"pyproject.toml": {"template": f"app/pyproject.{framework_str}.toml.tpl"},
f"{pnl}/__init__.py": {"template": "app/code/__init__.py.tpl"},
f"{pnl}/server.py": {"template": f"app/code/server.{framework_str}.py.tpl"},
Expand Down
1 change: 0 additions & 1 deletion src/py/flwr/cli/new/new_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ def test_new(tmp_path: str) -> None:
expected_files_top_level = {
"fedgpt",
"README.md",
"flower.toml",
"pyproject.toml",
}
expected_files_module = {
Expand Down
13 changes: 0 additions & 13 deletions src/py/flwr/cli/new/templates/app/flower.toml.tpl

This file was deleted.

4 changes: 4 additions & 0 deletions src/py/flwr/cli/new/templates/app/pyproject.numpy.toml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ dependencies = [

[tool.hatch.build.targets.wheel]
packages = ["."]

[flower.components]
serverapp = "$project_name.server:app"
clientapp = "$project_name.client:app"
4 changes: 4 additions & 0 deletions src/py/flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,7 @@ dependencies = [
[tool.hatch.build.targets.wheel]
packages = ["."]
[flower.components]
serverapp = "$project_name.server:app"
clientapp = "$project_name.client:app"
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ dependencies = [

[tool.hatch.build.targets.wheel]
packages = ["."]

[flower.components]
serverapp = "$project_name.server:app"
clientapp = "$project_name.client:app"
4 changes: 2 additions & 2 deletions src/py/flwr/cli/run/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@

import typer

from flwr.cli import flower_toml
from flwr.cli import config_utils
from flwr.simulation.run_simulation import _run_simulation


def run() -> None:
"""Run Flower project."""
typer.secho("Loading project configuration... ", fg=typer.colors.BLUE)

config, errors, warnings = flower_toml.load_and_validate_with_defaults()
config, errors, warnings = config_utils.load_and_validate_with_defaults()

if config is None:
typer.secho(
Expand Down

0 comments on commit e2721fc

Please sign in to comment.