namecheap-python 1.0.0__py3-none-any.whl → 1.0.1__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.
namecheap_cli/__main__.py CHANGED
@@ -24,7 +24,24 @@ from .completion import get_completion_script
24
24
  console = Console()
25
25
 
26
26
  # Configuration
27
- CONFIG_DIR = Path.home() / ".namecheap"
27
+ def get_config_dir() -> Path:
28
+ """Get config directory, using XDG on Unix-like systems."""
29
+ import sys
30
+ import os
31
+
32
+ if sys.platform == "win32":
33
+ # Windows: use platformdirs for proper Windows paths
34
+ from platformdirs import user_config_dir
35
+ return Path(user_config_dir("namecheap"))
36
+ else:
37
+ # Linux/macOS: use XDG
38
+ xdg_config = os.environ.get("XDG_CONFIG_HOME")
39
+ if xdg_config:
40
+ return Path(xdg_config) / "namecheap"
41
+ else:
42
+ return Path.home() / ".config" / "namecheap"
43
+
44
+ CONFIG_DIR = get_config_dir()
28
45
  CONFIG_FILE = CONFIG_DIR / "config.yaml"
29
46
 
30
47
 
@@ -54,9 +71,23 @@ class Config:
54
71
  if self.client:
55
72
  return self.client
56
73
 
74
+ # Check if config file exists
75
+ if not CONFIG_FILE.exists():
76
+ console.print("[red]❌ Configuration not found![/red]")
77
+ console.print(f"\nPlease run [bold cyan]namecheap-cli config init[/bold cyan] to set up your configuration.")
78
+ console.print(f"\nThis will create a config file at: [dim]{CONFIG_FILE}[/dim]")
79
+ sys.exit(1)
80
+
57
81
  config = self.load_config()
58
82
  profile_config = config.get("profiles", {}).get(self.profile, {})
59
83
 
84
+ # Check if profile exists
85
+ if not profile_config:
86
+ console.print(f"[red]❌ Profile '{self.profile}' not found in configuration![/red]")
87
+ console.print(f"\nAvailable profiles: {', '.join(config.get('profiles', {}).keys()) or 'none'}")
88
+ console.print(f"\nRun [bold cyan]namecheap-cli config init[/bold cyan] to create a new profile.")
89
+ sys.exit(1)
90
+
60
91
  # Override sandbox if specified
61
92
  if self.sandbox is not None:
62
93
  profile_config["sandbox"] = self.sandbox
@@ -65,7 +96,14 @@ class Config:
65
96
  self.client = Namecheap(**profile_config)
66
97
  return self.client
67
98
  except Exception as e:
68
- console.print(f"[red]❌ Error initializing client: {e}[/red]")
99
+ # Check for common configuration errors
100
+ error_msg = str(e)
101
+ if "Parameter APIUser is missing" in error_msg or "Parameter APIKey is missing" in error_msg:
102
+ console.print("[red]❌ Invalid or incomplete configuration![/red]")
103
+ console.print(f"\nYour configuration appears to be missing required fields.")
104
+ console.print(f"Please run [bold cyan]namecheap-cli config init[/bold cyan] to reconfigure.")
105
+ else:
106
+ console.print(f"[red]❌ Error initializing client: {e}[/red]")
69
107
  sys.exit(1)
70
108
 
71
109
 
@@ -213,9 +251,8 @@ def domain_list(config: Config, status: str | None, sort: str, expiring_in: int
213
251
  @domain_group.command("check")
214
252
  @click.argument("domains", nargs=-1, required=False)
215
253
  @click.option("--file", "-f", type=click.File("r"), help="File with domains to check")
216
- @click.option("--pricing", "-p", is_flag=True, help="Include pricing information")
217
254
  @pass_config
218
- def domain_check(config: Config, domains: tuple[str, ...], file, pricing: bool) -> None:
255
+ def domain_check(config: Config, domains: tuple[str, ...], file) -> None:
219
256
  """Check domain availability."""
220
257
  nc = config.init_client()
221
258
 
@@ -235,39 +272,30 @@ def domain_check(config: Config, domains: tuple[str, ...], file, pricing: bool)
235
272
  transient=True,
236
273
  ) as progress:
237
274
  progress.add_task(f"Checking {len(domain_list)} domains...", total=None)
238
- results = nc.domains.check(*domain_list, include_pricing=pricing)
275
+ results = nc.domains.check(*domain_list, include_pricing=True)
239
276
 
240
277
  # Output
241
278
  if config.output_format == "table":
242
279
  table = Table(title="Domain Availability")
243
280
  table.add_column("Domain", style="cyan")
244
281
  table.add_column("Available", style="green")
245
- if pricing:
246
- table.add_column("Price", style="yellow")
247
- table.add_column("Total", style="yellow")
282
+ table.add_column("Price (USD/year)", style="yellow")
248
283
 
249
284
  for result in results:
250
285
  available_text = "✅ Available" if result.available else "❌ Taken"
251
286
  available_style = "green" if result.available else "red"
252
287
 
288
+ if result.available and result.price:
289
+ price_text = f"${result.price:.2f}"
290
+ else:
291
+ price_text = "-"
292
+
253
293
  row = [
254
294
  result.domain,
255
295
  f"[{available_style}]{available_text}[/{available_style}]",
296
+ price_text
256
297
  ]
257
298
 
258
- if pricing and result.available:
259
- if result.price:
260
- price_text = f"${result.price:.2f}"
261
- total_text = (
262
- f"${result.total_price:.2f}" if result.total_price else price_text
263
- )
264
- else:
265
- price_text = "N/A"
266
- total_text = "N/A"
267
- row.extend([price_text, total_text])
268
- elif pricing:
269
- row.extend(["-", "-"])
270
-
271
299
  table.add_row(*row)
272
300
 
273
301
  console.print(table)
@@ -293,16 +321,11 @@ def domain_check(config: Config, domains: tuple[str, ...], file, pricing: bool)
293
321
  "domain": result.domain,
294
322
  "available": result.available,
295
323
  }
296
- if pricing and result.available and result.price:
324
+ if result.available and result.price:
297
325
  item["price"] = float(result.price)
298
- item["total_price"] = (
299
- float(result.total_price) if result.total_price else float(result.price)
300
- )
301
326
  data.append(item)
302
327
 
303
- headers = ["domain", "available"]
304
- if pricing:
305
- headers.extend(["price", "total_price"])
328
+ headers = ["domain", "available", "price"]
306
329
  output_formatter(data, config.output_format, headers)
307
330
 
308
331
  except NamecheapError as e:
@@ -747,6 +770,12 @@ def config_init() -> None:
747
770
  return
748
771
 
749
772
  console.print("\n[bold cyan]Namecheap CLI Configuration Wizard[/bold cyan]\n")
773
+
774
+ console.print("[dim]To get your API key:[/dim]")
775
+ console.print("1. Go to [link=https://ap.www.namecheap.com/settings/tools/apiaccess/]https://ap.www.namecheap.com/settings/tools/apiaccess/[/link]")
776
+ console.print("2. Enable API access")
777
+ console.print("3. Whitelist your IP address")
778
+ console.print("4. Generate your API key\n")
750
779
 
751
780
  # Get configuration values
752
781
  api_key = Prompt.ask("API Key", password=True)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: namecheap-python
3
- Version: 1.0.0
3
+ Version: 1.0.1
4
4
  Summary: A friendly Python SDK for Namecheap API
5
5
  Project-URL: Homepage, https://github.com/adriangalilea/namecheap-python
6
6
  Project-URL: Repository, https://github.com/adriangalilea/namecheap-python
@@ -26,11 +26,13 @@ Requires-Dist: tldextract>=5.0.0
26
26
  Requires-Dist: xmltodict>=0.13.0
27
27
  Provides-Extra: all
28
28
  Requires-Dist: click>=8.1.0; extra == 'all'
29
+ Requires-Dist: platformdirs>=4.0.0; extra == 'all'
29
30
  Requires-Dist: pyyaml>=6.0.0; extra == 'all'
30
31
  Requires-Dist: rich>=13.0.0; extra == 'all'
31
32
  Requires-Dist: textual>=0.47.0; extra == 'all'
32
33
  Provides-Extra: cli
33
34
  Requires-Dist: click>=8.1.0; extra == 'cli'
35
+ Requires-Dist: platformdirs>=4.0.0; extra == 'cli'
34
36
  Requires-Dist: pyyaml>=6.0.0; extra == 'cli'
35
37
  Requires-Dist: rich>=13.0.0; extra == 'cli'
36
38
  Provides-Extra: dev
@@ -60,26 +62,17 @@ A modern, friendly Python SDK for the Namecheap API with comprehensive CLI and T
60
62
  - **Comprehensive logging** with beautiful colored output
61
63
  - **Sandbox support** for safe testing
62
64
 
63
- ## 📦 Installation
64
-
65
- ```bash
66
- # Core SDK only
67
- pip install namecheap-python
65
+ ## 🎯 Quick Start
68
66
 
69
- # With CLI tool
70
- pip install namecheap-python[cli]
67
+ **Requires Python 3.12 or higher**
71
68
 
72
- # With TUI tool
73
- pip install namecheap-python[tui]
69
+ ### `namecheap-python`: Core Python SDK Library
74
70
 
75
- # Everything
76
- pip install namecheap-python[all]
71
+ ```bash
72
+ # Add as a dependency to your project
73
+ uv add namecheap-python
77
74
  ```
78
75
 
79
- ## 🎯 Quick Start
80
-
81
- ### SDK Usage
82
-
83
76
  ```python
84
77
  from namecheap import Namecheap
85
78
 
@@ -107,18 +100,22 @@ nc.dns.set("example.com",
107
100
  )
108
101
  ```
109
102
 
110
- ### CLI Usage
103
+ ### `namecheap-cli`: CLI tool
111
104
 
112
- ```bash
113
- # Configure CLI
114
- uv run namecheap-cli config init
105
+ It was meant as a proof of concept to showcase `namecheap-python`, but it is a tool that I use
115
106
 
107
+ ```bash
116
108
  # List domains with beautiful table output
117
- uv run namecheap-cli domain list
118
- ```
119
109
 
120
- Output:
121
- ```
110
+ # Run it without install with:
111
+ uvx --from 'namecheap-python[cli]' namecheap-cli domain list
112
+
113
+ # Or install it permanently with:
114
+ uv tool install --python 3.12 'namecheap-python[cli]'
115
+
116
+ # Then run
117
+ namecheap-cli domain list
118
+
122
119
  Domains (4 total)
123
120
  ┏━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━┓
124
121
  ┃ Domain ┃ Status ┃ Expires ┃ Auto-Renew ┃ Locked ┃
@@ -130,22 +127,42 @@ Output:
130
127
  └───────────────────┴────────┴────────────┴────────────┴────────┘
131
128
  ```
132
129
 
130
+ Configure it before first use:
131
+
132
+ ```bash
133
+ # Interactive setup
134
+ namecheap-cli config init
135
+
136
+ # Creates config file at:
137
+ # - Linux/macOS: $XDG_CONFIG_HOME/namecheap/config.yaml (or ~/.config/namecheap/config.yaml)
138
+ # - Windows: %APPDATA%\namecheap\config.yaml
139
+ ```
140
+ Check domain availability and pricing:
141
+
133
142
  ```bash
134
143
  # Check domain availability
135
- uv run namecheap-cli domain check myawesome.com coolstartup.io
144
+ namecheap-cli domain check myawesome.com coolstartup.io
145
+ Domain Availability
146
+ ┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓
147
+ ┃ Domain ┃ Available ┃ Price (USD/year) ┃
148
+ ┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩
149
+ │ myawesome.com │ ❌ Taken │ - │
150
+ │ coolstartup.io │ ✅ Available │ $34.98 │
151
+ └────────────────┴──────────────┴──────────────────┘
152
+
153
+ 💡 Suggestions for taken domains:
154
+ • myawesome.com → myawesome.net, myawesome.io, getmyawesome.com
155
+ ```
156
+
157
+ Manage DNS records:
136
158
 
137
- # Manage DNS records
138
- uv run namecheap-cli dns list example.com
139
- uv run namecheap-cli dns add example.com A www 192.0.2.1
140
- uv run namecheap-cli dns export example.com --format yaml
159
+ In this example I'll set up GitHub Pages for my domain `tdo.garden`
141
160
 
142
- # Setup GitHub Pages (example: tdo.garden)
161
+ ```bash
143
162
  # First, check current DNS records (before setup)
144
- uv run namecheap-cli dns list tdo.garden
145
- ```
163
+ namecheap-cli dns list tdo.garden
146
164
 
147
- Initial state (Namecheap default parking page):
148
- ```
165
+ # Initial state (Namecheap default parking page):
149
166
  DNS Records for tdo.garden (2 total)
150
167
  ┏━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┓
151
168
  ┃ Type ┃ Name ┃ Value ┃ TTL ┃ Priority ┃
@@ -153,40 +170,34 @@ Initial state (Namecheap default parking page):
153
170
  │ CNAME │ www │ parkingpage.namecheap.com. │ 1800 │ 10 │
154
171
  │ URL │ @ │ http://www.tdo.garden/ │ 1800 │ 10 │
155
172
  └──────────┴──────────────────────┴────────────────────────────┴──────────┴──────────┘
156
- ```
157
173
 
158
- ```bash
159
174
  # Add GitHub Pages A records for apex domain
160
- uv run namecheap-cli dns add tdo.garden A @ 185.199.108.153
161
- Built namecheap-python @ file:///Users/adrian/Developer/namecheap-python
162
- Uninstalled 1 package in 0.77ms
163
- Installed 1 package in 1ms
175
+ ❯ namecheap-cli dns add tdo.garden A @ 185.199.108.153
164
176
  Adding A record to tdo.garden...
165
177
  ✅ Added A record successfully!
166
178
 
167
- uv run namecheap-cli dns add tdo.garden A @ 185.199.109.153
179
+ ❯ namecheap-cli dns add tdo.garden A @ 185.199.109.153
168
180
  Adding A record to tdo.garden...
169
181
  ✅ Added A record successfully!
170
182
 
171
- uv run namecheap-cli dns add tdo.garden A @ 185.199.110.153
183
+ ❯ namecheap-cli dns add tdo.garden A @ 185.199.110.153
172
184
  Adding A record to tdo.garden...
173
185
  ✅ Added A record successfully!
174
186
 
175
- uv run namecheap-cli dns add tdo.garden A @ 185.199.111.153
187
+ ❯ namecheap-cli dns add tdo.garden A @ 185.199.111.153
176
188
  Adding A record to tdo.garden...
177
189
  ✅ Added A record successfully!
178
190
 
179
191
  # Add CNAME for www subdomain
180
- uv run namecheap-cli dns add tdo.garden CNAME www adriangalilea.github.io
192
+ ❯ namecheap-cli dns add tdo.garden CNAME www adriangalilea.github.io
181
193
  Adding CNAME record to tdo.garden...
182
194
  ✅ Added CNAME record successfully!
183
195
 
184
196
  # Verify the setup
185
- uv run namecheap-cli dns list tdo.garden
186
- ```
197
+ ❯ namecheap-cli dns list tdo.garden
187
198
 
188
- Final state (with GitHub Pages + old records still present):
189
- ```
199
+ # Final state with GitHub Pages + old records still present that you may want to remove:
200
+ ```bash
190
201
  DNS Records for tdo.garden (7 total)
191
202
  ┏━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┓
192
203
  ┃ Type ┃ Name ┃ Value ┃ TTL ┃ Priority ┃
@@ -201,18 +212,27 @@ Final state (with GitHub Pages + old records still present):
201
212
  └──────────┴──────────────────────┴────────────────────────────┴──────────┴──────────┘
202
213
  ```
203
214
 
204
- Note: You may want to remove the old parking page records after confirming GitHub Pages works.
205
- ```
206
215
 
207
- ### TUI Usage
216
+ You can also export DNS records:
217
+
218
+ ```bash
219
+ namecheap-cli dns export example.com --format yaml
220
+ ```
221
+ ### `namecheap-dns-tui`: TUI for DNS management
208
222
 
209
223
  ```bash
210
224
  # Launch interactive DNS manager
211
- uv run namecheap-dns-tui
225
+ namecheap-dns-tui
212
226
  ```
213
227
 
214
228
  ![DNS Manager TUI](src/namecheap_dns_tui/assets/screenshot2.png)
215
229
 
230
+ ## Install both the CLI and TUI
231
+
232
+ ```bash
233
+ uv tool install --python 3.12 'namecheap-python[all]'
234
+ ```
235
+
216
236
  ## 📖 Documentation
217
237
 
218
238
  - **[Examples Overview](examples/README.md)** - Quick examples for all tools
@@ -251,15 +271,6 @@ nc = Namecheap(
251
271
  )
252
272
  ```
253
273
 
254
- ### CLI Configuration
255
-
256
- ```bash
257
- # Interactive setup
258
- uv run namecheap-cli config init
259
-
260
- # Creates ~/.namecheap/config.yaml with profiles
261
- ```
262
-
263
274
  ## 🔧 Advanced SDK Usage
264
275
 
265
276
  ### DNS Builder Pattern
@@ -376,4 +387,4 @@ MIT License - see [LICENSE](LICENSE) file for details.
376
387
 
377
388
  ## 🤝 Contributing
378
389
 
379
- Contributions are welcome! Please feel free to submit a Pull Request. See the [Development Guide](docs/dev/README.md) for setup instructions and guidelines.
390
+ Contributions are welcome! Please feel free to submit a Pull Request. See the [Development Guide](docs/dev/README.md) for setup instructions and guidelines.
@@ -9,7 +9,7 @@ namecheap/_api/dns.py,sha256=Yvx91QIWrDx3ZxxmH_NLo_M9MP55aL71CJ6mXyJZUT0,10813
9
9
  namecheap/_api/domains.py,sha256=EUXV7R5wQyPHQHfDITe2IWRlPF7V-df-K0q2XnrvshI,16113
10
10
  namecheap_cli/README.md,sha256=liduIiGr8DHXGTht5swrYnvtAlcdCMQOnSdCD61g4Vw,7337
11
11
  namecheap_cli/__init__.py,sha256=nGRHc_CkO4xKhSQdAVG-koEffP8VS0TvbfbZkg7Jg4k,108
12
- namecheap_cli/__main__.py,sha256=OyE_oKtBXxWzxF-yGJQy9IbQL5FJ-5rP5ElrKS4Yu8E,28733
12
+ namecheap_cli/__main__.py,sha256=l-9egf6_9Gitocq10f2agcyjubd-1KFC76K4kAFGiNQ,30154
13
13
  namecheap_cli/completion.py,sha256=JTEMnceQli7TombjZkHh-IcZKW4RFRI8Yk5VynxPsEA,2777
14
14
  namecheap_dns_tui/README.md,sha256=It16ZiZh0haEeaENfF5HX0Ec4dBawdTYiAi-TiG9wi0,1690
15
15
  namecheap_dns_tui/__init__.py,sha256=-yL_1Ha41FlQcmjG-raUrZP9CjTJD3d0w2BW2X-twJg,106
@@ -18,8 +18,8 @@ namecheap_dns_tui/assets/screenshot1.png,sha256=OXO2P80ll5WRzLYgaakcNnzos8svlJoX
18
18
  namecheap_dns_tui/assets/screenshot2.png,sha256=5VN_qDMNhWEyrOqKw7vxl1h-TgmZQ_V9aph3Xmf_AFg,279194
19
19
  namecheap_dns_tui/assets/screenshot3.png,sha256=h39wSKxx1JCkgeAB7Q3_JlBcAtX1vsRFKtWtOwbBVso,220625
20
20
  namecheap_dns_tui/assets/screenshot4.png,sha256=J4nCOW16z3vaRiPbcMiiIRgV7q3XFbi_1N1ivD1Pa4Y,238068
21
- namecheap_python-1.0.0.dist-info/METADATA,sha256=wq_qAcQp7Tv5YuqypDFVpomVr1djHhfCc_FRBXR3RpM,13101
22
- namecheap_python-1.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
- namecheap_python-1.0.0.dist-info/entry_points.txt,sha256=AyhiXroLUpM0Vdo_-RvH0S8o4XDPsDlsEl_65vm6DEk,96
24
- namecheap_python-1.0.0.dist-info/licenses/LICENSE,sha256=pemTblFP6BBje3bBv_yL_sr2iAqB2H0-LdWMvVIR42o,1062
25
- namecheap_python-1.0.0.dist-info/RECORD,,
21
+ namecheap_python-1.0.1.dist-info/METADATA,sha256=BUpPd6I_zUAB0oy3aJ9iwG0iI6T88dHxx2sY1W-BtJI,14130
22
+ namecheap_python-1.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ namecheap_python-1.0.1.dist-info/entry_points.txt,sha256=AyhiXroLUpM0Vdo_-RvH0S8o4XDPsDlsEl_65vm6DEk,96
24
+ namecheap_python-1.0.1.dist-info/licenses/LICENSE,sha256=pemTblFP6BBje3bBv_yL_sr2iAqB2H0-LdWMvVIR42o,1062
25
+ namecheap_python-1.0.1.dist-info/RECORD,,