flwr-nightly 1.9.0.dev20240410__py3-none-any.whl → 1.9.0.dev20240411__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of flwr-nightly might be problematic. Click here for more details.

flwr/cli/new/new.py CHANGED
@@ -22,7 +22,12 @@ from typing import Dict, Optional
22
22
  import typer
23
23
  from typing_extensions import Annotated
24
24
 
25
- from ..utils import prompt_options, prompt_text
25
+ from ..utils import (
26
+ is_valid_project_name,
27
+ prompt_options,
28
+ prompt_text,
29
+ sanitize_project_name,
30
+ )
26
31
 
27
32
 
28
33
  class MlFramework(str, Enum):
@@ -81,6 +86,16 @@ def new(
81
86
  ] = None,
82
87
  ) -> None:
83
88
  """Create new Flower project."""
89
+ if project_name is None:
90
+ project_name = prompt_text("Please provide project name")
91
+ if not is_valid_project_name(project_name):
92
+ project_name = prompt_text(
93
+ "Please provide a name that only contains "
94
+ "characters in {'_', 'a-zA-Z', '0-9'}",
95
+ predicate=is_valid_project_name,
96
+ default=sanitize_project_name(project_name),
97
+ )
98
+
84
99
  print(
85
100
  typer.style(
86
101
  f"🔨 Creating Flower project {project_name}...",
@@ -89,9 +104,6 @@ def new(
89
104
  )
90
105
  )
91
106
 
92
- if project_name is None:
93
- project_name = prompt_text("Please provide project name")
94
-
95
107
  if framework is not None:
96
108
  framework_str = str(framework.value)
97
109
  else:
flwr/cli/utils.py CHANGED
@@ -14,18 +14,23 @@
14
14
  # ==============================================================================
15
15
  """Flower command line interface utils."""
16
16
 
17
- from typing import List, cast
17
+ from typing import Callable, List, Optional, cast
18
18
 
19
19
  import typer
20
20
 
21
21
 
22
- def prompt_text(text: str) -> str:
22
+ def prompt_text(
23
+ text: str,
24
+ predicate: Callable[[str], bool] = lambda _: True,
25
+ default: Optional[str] = None,
26
+ ) -> str:
23
27
  """Ask user to enter text input."""
24
28
  while True:
25
29
  result = typer.prompt(
26
- typer.style(f"\n💬 {text}", fg=typer.colors.MAGENTA, bold=True)
30
+ typer.style(f"\n💬 {text}", fg=typer.colors.MAGENTA, bold=True),
31
+ default=default,
27
32
  )
28
- if len(result) > 0:
33
+ if predicate(result) and len(result) > 0:
29
34
  break
30
35
  print(typer.style("❌ Invalid entry", fg=typer.colors.RED, bold=True))
31
36
 
@@ -65,3 +70,54 @@ def prompt_options(text: str, options: List[str]) -> str:
65
70
 
66
71
  result = options[int(index)]
67
72
  return result
73
+
74
+
75
+ def is_valid_project_name(name: str) -> bool:
76
+ """Check if the given string is a valid Python module name.
77
+
78
+ A valid module name must start with a letter or an underscore, and can only contain
79
+ letters, digits, and underscores.
80
+ """
81
+ if not name:
82
+ return False
83
+
84
+ # Check if the first character is a letter or underscore
85
+ if not (name[0].isalpha() or name[0] == "_"):
86
+ return False
87
+
88
+ # Check if the rest of the characters are valid (letter, digit, or underscore)
89
+ for char in name[1:]:
90
+ if not (char.isalnum() or char == "_"):
91
+ return False
92
+
93
+ return True
94
+
95
+
96
+ def sanitize_project_name(name: str) -> str:
97
+ """Sanitize the given string to make it a valid Python module name.
98
+
99
+ This version replaces hyphens with underscores, removes any characters not allowed
100
+ in Python module names, makes the string lowercase, and ensures it starts with a
101
+ valid character.
102
+ """
103
+ # Replace '-' with '_'
104
+ name_with_underscores = name.replace("-", "_").replace(" ", "_")
105
+
106
+ # Allowed characters in a module name: letters, digits, underscore
107
+ allowed_chars = set(
108
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
109
+ )
110
+
111
+ # Make the string lowercase
112
+ sanitized_name = name_with_underscores.lower()
113
+
114
+ # Remove any characters not allowed in Python module names
115
+ sanitized_name = "".join(c for c in sanitized_name if c in allowed_chars)
116
+
117
+ # Ensure the first character is a letter or underscore
118
+ if sanitized_name and (
119
+ sanitized_name[0].isdigit() or sanitized_name[0] not in allowed_chars
120
+ ):
121
+ sanitized_name = "_" + sanitized_name
122
+
123
+ return sanitized_name
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flwr-nightly
3
- Version: 1.9.0.dev20240410
3
+ Version: 1.9.0.dev20240411
4
4
  Summary: Flower: A Friendly Federated Learning Framework
5
5
  Home-page: https://flower.ai
6
6
  License: Apache-2.0
@@ -4,7 +4,7 @@ flwr/cli/app.py,sha256=38thPnMydBmNAxNE9mz4By-KdRUhJfoUgeDuAxMYF_U,1095
4
4
  flwr/cli/example.py,sha256=1bGDYll3BXQY2kRqSN-oICqS5n1b9m0g0RvXTopXHl4,2215
5
5
  flwr/cli/flower_toml.py,sha256=gypY4zOe6Mx_Xzz5vsSzGRppWBaCnipiksBTrox_r3k,4675
6
6
  flwr/cli/new/__init__.py,sha256=cQzK1WH4JP2awef1t2UQ2xjl1agVEz9rwutV18SWV1k,789
7
- flwr/cli/new/new.py,sha256=FqQoFATat1O9UGEUdWrAFCOUOEtnIRn3USr-Lv8osi0,5016
7
+ flwr/cli/new/new.py,sha256=zsal2Cahc99lpHhHO1UUyGVvTH5mxeuBVt44zCLvQwM,5387
8
8
  flwr/cli/new/templates/__init__.py,sha256=4luU8RL-CK8JJCstQ_ON809W9bNTkY1l9zSaPKBkgwY,725
9
9
  flwr/cli/new/templates/app/README.md.tpl,sha256=AvM6QCfQd1acUV3fkXOwgypZ5_52L3kKu53owXsjgcc,714
10
10
  flwr/cli/new/templates/app/__init__.py,sha256=DU7QMY7IhMQyuwm_tja66xU0KXTWQFqzfTqwg-_NJdE,729
@@ -26,7 +26,7 @@ flwr/cli/new/templates/app/requirements.pytorch.txt.tpl,sha256=3dvhiFgiOw3HAHCDm
26
26
  flwr/cli/new/templates/app/requirements.tensorflow.txt.tpl,sha256=MsiO0GbUe35h5giVMaE2YykKMAhtC5ccAc_4EcmJUNs,209
27
27
  flwr/cli/run/__init__.py,sha256=oCd6HmQDx-sqver1gecgx-uMA38BLTSiiKpl7RGNceg,789
28
28
  flwr/cli/run/run.py,sha256=C7Yh-Y0f64PEabb9733jBKIhhOUFpcRmCZJIDtv-NG8,2329
29
- flwr/cli/utils.py,sha256=_V2BlFVNNG2naZrq227fZ8o4TxBN_hB-4fQsen9uQoo,2300
29
+ flwr/cli/utils.py,sha256=33m5ELefA43VhJwtBHW5ntWkP7X5Tk_5A2s1OcaSBYg,4153
30
30
  flwr/client/__init__.py,sha256=futk_IdY_N1h8BTve4Iru51bxm7H1gv58ZPIXWi5XUA,1187
31
31
  flwr/client/app.py,sha256=B48cQa-kb_0WzdtufTXuaoEyrynGWMQCqxdUz_sAKek,26193
32
32
  flwr/client/client.py,sha256=Vp9UkOkoHdNfn6iMYZsj_5m_GICiFfUlKEVaLad-YhM,8183
@@ -206,8 +206,8 @@ flwr/simulation/ray_transport/ray_actor.py,sha256=_wv2eP7qxkCZ-6rMyYWnjLrGPBZRxj
206
206
  flwr/simulation/ray_transport/ray_client_proxy.py,sha256=oDu4sEPIOu39vrNi-fqDAe10xtNUXMO49bM2RWfRcyw,6738
207
207
  flwr/simulation/ray_transport/utils.py,sha256=TYdtfg1P9VfTdLMOJlifInGpxWHYs9UfUqIv2wfkRLA,2392
208
208
  flwr/simulation/run_simulation.py,sha256=HiIH6aa_v56NfKQN5ZBd94NyVfaZNyFs43_kItYsQXU,15685
209
- flwr_nightly-1.9.0.dev20240410.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
210
- flwr_nightly-1.9.0.dev20240410.dist-info/METADATA,sha256=OW93pYK505VyF_-9xkLce_c6DOWTwte0ySOevzM9EPk,15257
211
- flwr_nightly-1.9.0.dev20240410.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
212
- flwr_nightly-1.9.0.dev20240410.dist-info/entry_points.txt,sha256=utu2wybGyYJSTtsB2ktY_gmy-XtMFo9EFZdishX0zR4,320
213
- flwr_nightly-1.9.0.dev20240410.dist-info/RECORD,,
209
+ flwr_nightly-1.9.0.dev20240411.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
210
+ flwr_nightly-1.9.0.dev20240411.dist-info/METADATA,sha256=O2ZbB-wm4FY4UjCCPjSxZyyB9KmVSMIVgBiTfrZ-Iu8,15257
211
+ flwr_nightly-1.9.0.dev20240411.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
212
+ flwr_nightly-1.9.0.dev20240411.dist-info/entry_points.txt,sha256=utu2wybGyYJSTtsB2ktY_gmy-XtMFo9EFZdishX0zR4,320
213
+ flwr_nightly-1.9.0.dev20240411.dist-info/RECORD,,