chipfoundry-cli 1.2.4__tar.gz → 1.2.6__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: chipfoundry-cli
3
- Version: 1.2.4
3
+ Version: 1.2.6
4
4
  Summary: CLI tool to automate ChipFoundry project submission to SFTP server
5
5
  Home-page: https://chipfoundry.io
6
6
  License: Apache-2.0
@@ -138,15 +138,28 @@ def get_project_json_from_cwd():
138
138
  return str(Path(os.getcwd())), project_name
139
139
  return None, None
140
140
 
141
- def check_project_initialized(project_root_path: Path, command_name: str):
141
+ def check_project_initialized(project_root_path: Path, command_name: str, dry_run: bool = False, allow_graceful: bool = False):
142
142
  """
143
143
  Check if project is initialized (has .cf/project.json).
144
144
  Raises click.Abort with helpful message if not initialized.
145
+
146
+ Args:
147
+ project_root_path: Path to project root
148
+ command_name: Name of the command (for error messages)
149
+ dry_run: If True, allows dry-run mode to proceed without initialization
150
+ allow_graceful: If True, returns False instead of raising Abort (for commands that should return 0 on error)
145
151
  """
146
152
  project_json_path = project_root_path / '.cf' / 'project.json'
147
153
  if not project_json_path.exists():
154
+ if allow_graceful:
155
+ return False
156
+ if dry_run:
157
+ # In dry-run mode, allow to proceed but warn
158
+ console.print(f"[yellow]⚠ Project not initialized. Run 'cf init' first for full functionality.[/yellow]")
159
+ return True
148
160
  console.print(f"[red]✗ Project not initialized. Please run 'cf init' first.[/red]")
149
161
  raise click.Abort()
162
+ return True
150
163
 
151
164
  @click.group(help="ChipFoundry CLI: Automate project submission and management.")
152
165
  @click.version_option(importlib.metadata.version("chipfoundry-cli"), "-v", "--version", message="%(version)s")
@@ -337,11 +350,47 @@ def gpio_config(project_root):
337
350
 
338
351
  project_root = Path(project_root)
339
352
 
340
- # Check if project is initialized
341
- check_project_initialized(project_root, 'gpio-config')
342
-
343
353
  project_json_path = project_root / '.cf' / 'project.json'
344
354
 
355
+ # Auto-initialize if project.json doesn't exist
356
+ if not project_json_path.exists():
357
+ console.print("[yellow]Project not initialized. Auto-initializing...[/yellow]")
358
+ cf_dir = project_root / '.cf'
359
+ cf_dir.mkdir(parents=True, exist_ok=True)
360
+
361
+ # Get username from user config
362
+ config = load_user_config()
363
+ username = config.get("sftp_username", "unknown")
364
+
365
+ # Auto-detect project type from GDS file name
366
+ gds_dir = project_root / 'gds'
367
+ gds_type = None
368
+ for gds_name, gtype in GDS_TYPE_MAP.items():
369
+ if (gds_dir / gds_name).exists():
370
+ gds_type = gtype
371
+ break
372
+
373
+ # Default project name to directory name
374
+ default_name = Path(project_root).name
375
+
376
+ # Default project type
377
+ project_type = gds_type if gds_type else 'digital'
378
+
379
+ # Create minimal project.json
380
+ data = {
381
+ "project": {
382
+ "name": default_name,
383
+ "type": project_type,
384
+ "user": username,
385
+ "version": "1",
386
+ "user_project_wrapper_hash": "",
387
+ "submission_state": "Draft"
388
+ }
389
+ }
390
+ with open(project_json_path, 'w') as f:
391
+ json.dump(data, f, indent=2)
392
+ console.print(f"[green]Auto-initialized project at {project_json_path}[/green]")
393
+
345
394
  # Load project type from project.json
346
395
  with open(project_json_path, 'r') as f:
347
396
  project_data = json.load(f)
@@ -1259,8 +1308,8 @@ def setup(project_root, repo_owner, repo_name, branch, pdk, caravel_lite,
1259
1308
 
1260
1309
  project_root_path = Path(project_root)
1261
1310
 
1262
- # Check if project is initialized
1263
- check_project_initialized(project_root_path, 'setup')
1311
+ # Check if project is initialized (allow dry-run to proceed)
1312
+ check_project_initialized(project_root_path, 'setup', dry_run=dry_run)
1264
1313
 
1265
1314
  had_errors = False
1266
1315
 
@@ -1871,9 +1920,12 @@ def harden(macro, project_root, list_designs, tag, pdk, use_nix, use_docker, dry
1871
1920
 
1872
1921
  project_root_path = Path(project_root)
1873
1922
 
1874
- # Check if project is initialized (skip check for --list)
1923
+ # Check if project is initialized (skip check for --list, allow graceful return)
1875
1924
  if not list_designs:
1876
- check_project_initialized(project_root_path, 'harden')
1925
+ if not check_project_initialized(project_root_path, 'harden', dry_run=dry_run, allow_graceful=True):
1926
+ console.print(f"[red]✗[/red] Project not initialized. Please run 'cf init' first.")
1927
+ console.print("[yellow]Run 'cf setup' first to install OpenLane[/yellow]")
1928
+ return
1877
1929
 
1878
1930
  openlane_dir = project_root_path / 'openlane'
1879
1931
 
@@ -1932,7 +1984,7 @@ def harden(macro, project_root, list_designs, tag, pdk, use_nix, use_docker, dry
1932
1984
  if not librelane_venv.exists():
1933
1985
  console.print("[red]✗[/red] LibreLane not installed")
1934
1986
  console.print("[yellow]Run 'cf setup --only-openlane' to install LibreLane[/yellow]")
1935
- sys.exit(1)
1987
+ raise click.Abort()
1936
1988
 
1937
1989
  # Fetch versions from upstream
1938
1990
  console.print("[dim]Fetching version information from cf-cli repository...[/dim]")
@@ -1976,7 +2028,7 @@ def harden(macro, project_root, list_designs, tag, pdk, use_nix, use_docker, dry
1976
2028
  if force_nix_flag and not use_nix:
1977
2029
  console.print("[red]✗[/red] Nix not available or cannot access LibreLane flake")
1978
2030
  console.print("[yellow]Install Nix from: https://librelane.readthedocs.io[/yellow]")
1979
- sys.exit(1)
2031
+ raise click.Abort()
1980
2032
 
1981
2033
  # Check if Docker is available
1982
2034
  if not use_nix and (force_docker_flag or not force_nix_flag):
@@ -1993,7 +2045,7 @@ def harden(macro, project_root, list_designs, tag, pdk, use_nix, use_docker, dry
1993
2045
  if force_docker_flag and not use_docker:
1994
2046
  console.print("[red]✗[/red] Docker not available")
1995
2047
  console.print("[yellow]Install Docker from: https://docker.com[/yellow]")
1996
- sys.exit(1)
2048
+ raise click.Abort()
1997
2049
 
1998
2050
  # Error if neither is available
1999
2051
  if not use_nix and not use_docker:
@@ -2002,7 +2054,7 @@ def harden(macro, project_root, list_designs, tag, pdk, use_nix, use_docker, dry
2002
2054
  console.print(" 1. [cyan]Nix[/cyan] - Install from: https://librelane.readthedocs.io")
2003
2055
  console.print(" 2. [cyan]Docker[/cyan] - Install from: https://docker.com")
2004
2056
  console.print("\nAfter installing either one, try again.")
2005
- sys.exit(1)
2057
+ raise click.Abort()
2006
2058
 
2007
2059
  execution_method = "Nix" if use_nix else "Docker"
2008
2060
 
@@ -2104,7 +2156,6 @@ def harden(macro, project_root, list_designs, tag, pdk, use_nix, use_docker, dry
2104
2156
 
2105
2157
  # Add --docker-no-tty if not running in a TTY (e.g., CI environments)
2106
2158
  try:
2107
- import sys
2108
2159
  if not sys.stdin.isatty():
2109
2160
  cmd.append('--docker-no-tty')
2110
2161
  except:
@@ -2258,8 +2309,11 @@ def precheck(project_root, disable_lvs, checks, dry_run):
2258
2309
 
2259
2310
  project_root_path = Path(project_root)
2260
2311
 
2261
- # Check if project is initialized
2262
- check_project_initialized(project_root_path, 'precheck')
2312
+ # Check if project is initialized (allow graceful return)
2313
+ if not check_project_initialized(project_root_path, 'precheck', dry_run=dry_run, allow_graceful=True):
2314
+ console.print(f"[red]✗[/red] Project not initialized. Please run 'cf init' first.")
2315
+ console.print("[yellow]Dependencies are required before running precheck.[/yellow]")
2316
+ return
2263
2317
 
2264
2318
  project_json_path = project_root_path / '.cf' / 'project.json'
2265
2319
 
@@ -2450,9 +2504,12 @@ def verify(test, project_root, sim, list_tests, run_all, tag, dry_run):
2450
2504
 
2451
2505
  project_root_path = Path(project_root)
2452
2506
 
2453
- # Check if project is initialized (skip check if just listing tests)
2507
+ # Check if project is initialized (skip check if just listing tests, allow graceful return)
2454
2508
  if not list_tests:
2455
- check_project_initialized(project_root_path, 'verify')
2509
+ if not check_project_initialized(project_root_path, 'verify', dry_run=dry_run, allow_graceful=True):
2510
+ console.print(f"[red]✗[/red] Project not initialized. Please run 'cf init' first.")
2511
+ console.print("[yellow]Cocotb tests require project initialization.[/yellow]")
2512
+ return
2456
2513
 
2457
2514
  project_json_path = project_root_path / '.cf' / 'project.json'
2458
2515
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "chipfoundry-cli"
3
- version = "1.2.4"
3
+ version = "1.2.6"
4
4
  description = "CLI tool to automate ChipFoundry project submission to SFTP server"
5
5
  authors = ["ChipFoundry <marwan.abbas@chipfoundry.io>"]
6
6
  readme = "README.md"
File without changes