devdash-mac 0.1.0__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.
@@ -0,0 +1,119 @@
1
+ """UUID v4/v7 and ULID generator."""
2
+
3
+ import re
4
+ import secrets
5
+ import sys
6
+ import time
7
+ import uuid
8
+
9
+ from devdash.tools.base import DevTool
10
+
11
+ _UUID_PATTERN = re.compile(
12
+ r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", re.IGNORECASE
13
+ )
14
+
15
+ # ULID encoding alphabet (Crockford's Base32)
16
+ _ULID_ALPHABET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
17
+
18
+
19
+ def _generate_uuid_v7() -> str:
20
+ """Generate UUID v7 (timestamp-based)."""
21
+ if sys.version_info >= (3, 12):
22
+ # Not available in stdlib until hypothetical future; use manual
23
+ pass
24
+ # Manual UUID v7 implementation
25
+ timestamp_ms = int(time.time() * 1000)
26
+ rand_bytes = secrets.token_bytes(10)
27
+
28
+ # Build 16 bytes: 6 bytes timestamp + 2 bytes ver/rand + 8 bytes rand
29
+ ts_bytes = timestamp_ms.to_bytes(6, "big")
30
+ uuid_bytes = bytearray(16)
31
+ uuid_bytes[0:6] = ts_bytes
32
+ uuid_bytes[6:16] = rand_bytes
33
+
34
+ # Set version (0111 = 7) in bits 48-51
35
+ uuid_bytes[6] = (uuid_bytes[6] & 0x0F) | 0x70
36
+ # Set variant (10xx) in bits 64-65
37
+ uuid_bytes[8] = (uuid_bytes[8] & 0x3F) | 0x80
38
+
39
+ hex_str = uuid_bytes.hex()
40
+ return f"{hex_str[:8]}-{hex_str[8:12]}-{hex_str[12:16]}-{hex_str[16:20]}-{hex_str[20:]}"
41
+
42
+
43
+ def _generate_ulid() -> str:
44
+ """Generate a ULID (Universally Unique Lexicographically Sortable Identifier)."""
45
+ timestamp_ms = int(time.time() * 1000)
46
+ rand_bytes = secrets.token_bytes(10)
47
+
48
+ # Encode timestamp (48 bits) as 10 Crockford Base32 chars
49
+ chars: list[str] = []
50
+ t = timestamp_ms
51
+ for _ in range(10):
52
+ chars.append(_ULID_ALPHABET[t & 0x1F])
53
+ t >>= 5
54
+ time_part = "".join(reversed(chars))
55
+
56
+ # Encode randomness (80 bits) as 16 Crockford Base32 chars
57
+ rand_int = int.from_bytes(rand_bytes, "big")
58
+ chars = []
59
+ for _ in range(16):
60
+ chars.append(_ULID_ALPHABET[rand_int & 0x1F])
61
+ rand_int >>= 5
62
+ rand_part = "".join(reversed(chars))
63
+
64
+ return time_part + rand_part
65
+
66
+
67
+ class UuidTool(DevTool):
68
+ @property
69
+ def name(self) -> str:
70
+ return "UUID / ULID Generator"
71
+
72
+ @property
73
+ def keyword(self) -> str:
74
+ return "uuid"
75
+
76
+ @property
77
+ def category(self) -> str:
78
+ return "Generators"
79
+
80
+ @property
81
+ def description(self) -> str:
82
+ return "Generate UUID v4, v7, or ULID; validate UUIDs"
83
+
84
+ def process(self, input_text: str, **kwargs: object) -> str:
85
+ text = input_text.strip()
86
+
87
+ # If input looks like a UUID, validate it
88
+ if text and _UUID_PATTERN.match(text):
89
+ try:
90
+ parsed = uuid.UUID(text)
91
+ return f"Valid UUID (version {parsed.version}): {parsed}"
92
+ except ValueError:
93
+ return "Invalid UUID format"
94
+
95
+ version = str(kwargs.get("version", "v4"))
96
+ count = int(kwargs.get("count", 1))
97
+ uppercase = bool(kwargs.get("uppercase", False))
98
+ count = max(1, min(count, 100))
99
+
100
+ results: list[str] = []
101
+ for _ in range(count):
102
+ if version == "v7":
103
+ val = _generate_uuid_v7()
104
+ elif version == "ulid":
105
+ val = _generate_ulid()
106
+ else:
107
+ val = str(uuid.uuid4())
108
+
109
+ if uppercase:
110
+ val = val.upper()
111
+ else:
112
+ val = val.lower()
113
+ results.append(val)
114
+
115
+ return "\n".join(results)
116
+
117
+
118
+ def register() -> DevTool:
119
+ return UuidTool()
devdash/ui/__init__.py ADDED
@@ -0,0 +1 @@
1
+ """DevDash UI components."""
@@ -0,0 +1,22 @@
1
+ """macOS native notifications helper."""
2
+
3
+ import rumps
4
+
5
+
6
+ def notify(title: str, message: str, subtitle: str = "") -> None:
7
+ """Show a macOS notification with consistent DevDash styling."""
8
+ rumps.notification(
9
+ title=title,
10
+ subtitle=subtitle,
11
+ message=message,
12
+ )
13
+
14
+
15
+ def notify_copied() -> None:
16
+ """Show 'Copied to clipboard' notification."""
17
+ notify("DevDash", "Copied to clipboard!")
18
+
19
+
20
+ def notify_error(message: str) -> None:
21
+ """Show an error notification."""
22
+ notify("DevDash - Error", message)
devdash/ui/windows.py ADDED
@@ -0,0 +1,84 @@
1
+ """Custom rumps.Window wrappers for consistent tool UI."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING
6
+
7
+ import rumps
8
+
9
+ from devdash import clipboard
10
+ from devdash.ui.notifications import notify_copied, notify_error
11
+
12
+ if TYPE_CHECKING:
13
+ from devdash.tools.base import DevTool
14
+
15
+
16
+ def show_tool_dialog(tool: DevTool, input_text: str = "") -> None:
17
+ """Show input window, process with tool, show output, offer clipboard copy."""
18
+ window = rumps.Window(
19
+ message=tool.description or f"Enter input for {tool.name}",
20
+ title=tool.name,
21
+ default_text=input_text,
22
+ ok="Process",
23
+ cancel="Cancel",
24
+ dimensions=(320, 200),
25
+ )
26
+ response = window.run()
27
+ if not response.clicked:
28
+ return
29
+
30
+ text = response.text
31
+ error = tool.validate(text)
32
+ if error:
33
+ notify_error(error)
34
+ return
35
+
36
+ try:
37
+ result = tool.process(text)
38
+ except Exception as e:
39
+ notify_error(f"Error: {e}")
40
+ return
41
+
42
+ # Show output window
43
+ output_window = rumps.Window(
44
+ message="Result (click OK to copy to clipboard):",
45
+ title=f"{tool.name} - Output",
46
+ default_text=result,
47
+ ok="Copy to Clipboard",
48
+ cancel="Close",
49
+ dimensions=(320, 200),
50
+ )
51
+ out_response = output_window.run()
52
+ if out_response.clicked:
53
+ clipboard.write(result)
54
+ notify_copied()
55
+
56
+
57
+ def show_multi_input_dialog(
58
+ tool: DevTool,
59
+ fields: list[tuple[str, str]],
60
+ ) -> list[str] | None:
61
+ """Show sequential input dialogs for tools needing multiple inputs.
62
+
63
+ Args:
64
+ tool: The tool instance.
65
+ fields: List of (label, default_value) tuples.
66
+
67
+ Returns:
68
+ List of input values, or None if cancelled.
69
+ """
70
+ values: list[str] = []
71
+ for label, default in fields:
72
+ window = rumps.Window(
73
+ message=label,
74
+ title=tool.name,
75
+ default_text=default,
76
+ ok="Next" if len(values) < len(fields) - 1 else "Process",
77
+ cancel="Cancel",
78
+ dimensions=(320, 150),
79
+ )
80
+ response = window.run()
81
+ if not response.clicked:
82
+ return None
83
+ values.append(response.text)
84
+ return values
@@ -0,0 +1,194 @@
1
+ Metadata-Version: 2.4
2
+ Name: devdash-mac
3
+ Version: 0.1.0
4
+ Summary: Open-source macOS menubar developer utilities
5
+ Author: DevDash Contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/devdash/devdash
8
+ Project-URL: Repository, https://github.com/devdash/devdash
9
+ Project-URL: Issues, https://github.com/devdash/devdash/issues
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: MacOS X
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: MacOS
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Topic :: Utilities
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: rumps>=0.4.0
26
+ Requires-Dist: pyperclip>=1.8.0
27
+ Requires-Dist: PyJWT>=2.8.0
28
+ Requires-Dist: pyyaml>=6.0
29
+ Requires-Dist: croniter>=1.3.0
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest>=7.0; extra == "dev"
32
+ Requires-Dist: pytest-cov; extra == "dev"
33
+ Requires-Dist: ruff; extra == "dev"
34
+ Requires-Dist: mypy; extra == "dev"
35
+ Requires-Dist: pre-commit; extra == "dev"
36
+ Requires-Dist: build; extra == "dev"
37
+ Requires-Dist: twine; extra == "dev"
38
+ Dynamic: license-file
39
+
40
+ # DevDash
41
+
42
+ Open-source macOS menubar developer utilities at your fingertips.
43
+
44
+ [![PyPI](https://img.shields.io/pypi/v/devdash.svg)](https://pypi.org/project/devdash)
45
+ [![Python 3.10+](https://img.shields.io/badge/Python-3.10+-blue.svg)](https://www.python.org/downloads/)
46
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
47
+
48
+ [GIF PLACEHOLDER - menubar app with tools opening in macOS]
49
+
50
+ ## Why DevDash?
51
+
52
+ - **Free & Open Source** — MIT licensed, no ads, no tracking, community-driven
53
+ - **Offline First** — All processing happens locally. Nothing is ever sent to external services
54
+ - **Pip Installable** — Single command installation. Works with Python 3.10+
55
+
56
+ ## Quick Start
57
+
58
+ ```bash
59
+ pip install devdash
60
+ devdash
61
+ ```
62
+
63
+ Click the wrench icon (🔧) in your macOS menubar to access all tools.
64
+
65
+ ## Tools
66
+
67
+ DevDash includes 12 essential developer utilities:
68
+
69
+ | Tool | What it does |
70
+ |------|-------------|
71
+ | 📝 **JSON Formatter** | Format, validate, and minify JSON |
72
+ | 🔐 **JWT Decoder** | Decode and inspect JSON Web Tokens |
73
+ | 🆔 **UUID / ULID Generator** | Generate UUID v4, v7, or ULID identifiers |
74
+ | 📄 **Base64 Encode/Decode** | Encode text to Base64 or decode back |
75
+ | #️⃣ **Hash Generator** | Generate MD5, SHA256, SHA512 hashes |
76
+ | ⏰ **Timestamp Converter** | Convert between Unix timestamps and readable dates |
77
+ | 🔗 **URL Encode/Decode** | Encode and decode URL-safe strings |
78
+ | 🔍 **Regex Tester** | Test regular expressions with live matches |
79
+ | 🎨 **Color Converter** | Convert between hex, RGB, and HSL colors |
80
+ | 📚 **Lorem Ipsum Generator** | Generate placeholder text and paragraphs |
81
+ | 🔑 **Password Generator** | Create secure random passwords |
82
+ | ⏱️ **Cron Parser** | Parse and explain cron expressions |
83
+
84
+ ## Smart Clipboard
85
+
86
+ DevDash auto-detects your clipboard content and opens the right tool automatically.
87
+
88
+ **How it works:**
89
+ 1. Copy anything to your clipboard (JSON, UUID, JWT, URL, etc.)
90
+ 2. Click "Clipboard: Auto-detect" in the DevDash menu
91
+ 3. The matching tool opens with your content pre-filled
92
+
93
+ Supports auto-detection for: JSON, JWT, UUID, Base64, URL-encoded text, timestamps, hex colors, and cron expressions.
94
+
95
+ ## Configuration
96
+
97
+ DevDash stores user preferences in `~/.config/devdash/config.yaml`. Edit this file to customize:
98
+
99
+ ```yaml
100
+ # Default hash algorithm: md5, sha256, sha512
101
+ default_hash_algorithm: sha256
102
+
103
+ # Timestamp format (Python strftime)
104
+ timestamp_format: "%Y-%m-%d %H:%M:%S"
105
+
106
+ # Password generator length
107
+ password_length: 16
108
+
109
+ # UUID version: v4, v7
110
+ uuid_version: v4
111
+
112
+ # Enable clipboard auto-detection
113
+ auto_clipboard_detection: true
114
+
115
+ # Watch clipboard for changes (experimental)
116
+ clipboard_watcher: false
117
+ ```
118
+
119
+ The config file is created automatically on first run with sensible defaults.
120
+
121
+ ## Installation
122
+
123
+ ### From PyPI (Recommended)
124
+
125
+ ```bash
126
+ pip install devdash
127
+ devdash
128
+ ```
129
+
130
+ ### From Source
131
+
132
+ ```bash
133
+ git clone https://github.com/devdash/devdash.git
134
+ cd devdash
135
+ pip install -e .
136
+ devdash
137
+ ```
138
+
139
+ For development setup, see [CONTRIBUTING.md](CONTRIBUTING.md).
140
+
141
+ ## macOS Permissions
142
+
143
+ DevDash needs clipboard access to work. On first run, macOS will ask for permission:
144
+
145
+ > "DevDash" would like to access your clipboard.
146
+
147
+ Click **Allow** to enable clipboard auto-detection. You can revoke this later in System Preferences → Security & Privacy → Accessibility.
148
+
149
+ ## Troubleshooting
150
+
151
+ **"command not found: devdash"**
152
+ - Ensure Python 3.10+ is installed: `python3 --version`
153
+ - Reinstall: `pip install --upgrade devdash`
154
+
155
+ **Menubar icon doesn't appear**
156
+ - Restart the app: press Ctrl+C to quit, then run `devdash` again
157
+ - Check that you have a menubar (not in fullscreen)
158
+
159
+ **Clipboard detection not working**
160
+ - Grant clipboard permission: System Preferences → Security & Privacy → Accessibility
161
+ - Enable in config: `auto_clipboard_detection: true`
162
+
163
+ ## Contributing
164
+
165
+ Found a bug? Want a new tool? Head to [CONTRIBUTING.md](CONTRIBUTING.md) to get started.
166
+
167
+ Quick links:
168
+ - [Reporting bugs](CONTRIBUTING.md#reporting-bugs)
169
+ - [Suggesting features](CONTRIBUTING.md#suggesting-features)
170
+ - [Adding a new tool](docs/adding-tools.md)
171
+ - [Architecture overview](docs/architecture.md)
172
+
173
+ ## Built With
174
+
175
+ - [rumps](https://github.com/jmorey/rumps) — Ridiculously Uncomplicated macOS Python Statusbar applications
176
+ - [pyperclip](https://github.com/asweigart/pyperclip) — Cross-platform clipboard support
177
+ - [PyJWT](https://pyjwt.readthedocs.io/) — JWT encoding and decoding
178
+ - [pyyaml](https://pyyaml.org/) — YAML configuration parsing
179
+ - [croniter](https://github.com/taichino/croniter) — Cron expression parsing
180
+
181
+ ## Security
182
+
183
+ All data processing happens locally on your machine:
184
+ - Input is never sent to external services
185
+ - Clipboard content is not logged or stored
186
+ - No telemetry or analytics
187
+
188
+ See [LICENSE](LICENSE) for full details.
189
+
190
+ ## License
191
+
192
+ MIT License © 2024 DevDash Contributors
193
+
194
+ See [LICENSE](LICENSE) for details.
@@ -0,0 +1,30 @@
1
+ devdash/__init__.py,sha256=gtDTOlI0x-HJdB2DQHYS8Tnkt5Nt1t6hUdGHKW8GT-I,111
2
+ devdash/__main__.py,sha256=FFZVLUrCty8o-YTs7ENbkw60HmVwOPOvTBBlHtoFBCo,112
3
+ devdash/app.py,sha256=NAhifbj-vRi7tW0awNpyYDqz6TZlgqzDILXcLEmfBYM,5411
4
+ devdash/clipboard.py,sha256=fGrocv24_75r5Ys3nhIhmF3LJa1x4q6cCHsTADH5muA,2808
5
+ devdash/config.py,sha256=rXz1_1GN9Znvqc3-FSSIuN0IMuTa-4uxCxsqMo1tfAU,1435
6
+ devdash/plugin_loader.py,sha256=LjW9RBM2rYyosmQJBl5L_3O6yHoPAmQJxmaAYMu10Zk,1327
7
+ devdash/storage.py,sha256=kbgqI1QuPH7BhU0t0H9f15UvFso2CqyJn7f_JQtdZ7I,7840
8
+ devdash/tools/__init__.py,sha256=Ht3dBoH29xzzg6988NSJENd63P4uMIRbYszSBCEDO6Y,30
9
+ devdash/tools/base.py,sha256=NPQM6nYTS7ykwcPxRmZj-whUAk74H243Stutvlna20c,928
10
+ devdash/tools/base64_tool.py,sha256=Wx3Lfm-XQZONz9VaiR1rOXmnaQ0PlBuV3KrRKEUs5tE,2640
11
+ devdash/tools/color_tool.py,sha256=vV9tvj-G-7afvq472njgI3KKVf0cBp-M3NqRyHhdCBg,3832
12
+ devdash/tools/cron_tool.py,sha256=7zPhZ9xduiOXtdg116PsQJKRIAecOwxIpzlfypdS2H0,4278
13
+ devdash/tools/hash_tool.py,sha256=DRBRZCbH52Etk4GIDxsFeYF8xnUUt8tO6UaaMYpeL6w,2037
14
+ devdash/tools/json_tool.py,sha256=aRWnSP_zB-ro3W6-Gfemt0ql-zuUHAQXyuXchcke5Wc,1753
15
+ devdash/tools/jwt_tool.py,sha256=r7hpULBiYpVbp7FNyXE9FnUVgPqps2TKYGhXjIjbplE,2831
16
+ devdash/tools/lorem_tool.py,sha256=DIt06y5cqF_wzSDnHUeQy2I48eSpaKerUwSbuFr3nUI,3703
17
+ devdash/tools/password_tool.py,sha256=XZPRQ58tZu9cyJ6-NbsjcyYD4TblheyUoZTyomyN21M,6559
18
+ devdash/tools/regex_tool.py,sha256=h4rJ7ringDUhceg7LePxhQ7AjibySXn6gV13ERbjYZM,2706
19
+ devdash/tools/timestamp_tool.py,sha256=jAMGNQ0_wyapk1Kjz0oSeEZaYurgo6V8w1hZoHlAj9s,4181
20
+ devdash/tools/url_tool.py,sha256=sqi7K1hBgrufPW_iHGBamwWsIYwI3CkuIm5zV8ySXew,2103
21
+ devdash/tools/uuid_tool.py,sha256=xNFj6x_OnMR97acxVSYKMsd-OEKArLauysvR0KpSURg,3404
22
+ devdash/ui/__init__.py,sha256=jiMWDarEwz6tc2z1Yd1sTt3xeoYFBCPkfJM6N0Ayv2g,29
23
+ devdash/ui/notifications.py,sha256=87IAuQIVOsYEqkueSJ7j4I-CAJNnVXBoVH88iXm1MHk,542
24
+ devdash/ui/windows.py,sha256=7HfAETkfeTXS9d1hwb3fLicDvAT37BzXIwPrHUaEOnU,2229
25
+ devdash_mac-0.1.0.dist-info/licenses/LICENSE,sha256=sjP20vbIrJHhrjfJ-FoI9vrktuxBhd9MjV1ddfNIdGU,1077
26
+ devdash_mac-0.1.0.dist-info/METADATA,sha256=Wlo-tw443fJQ2ofJXKjJz9zckaYcI2iYs7A-FbTkdG4,6353
27
+ devdash_mac-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
28
+ devdash_mac-0.1.0.dist-info/entry_points.txt,sha256=LIj0XyHuL5S6xW_uFwx5PCViD4s5UNTlsWlKtIc6VI0,50
29
+ devdash_mac-0.1.0.dist-info/top_level.txt,sha256=5d0fXhQcW9hREl625T3slXusJxOgWejd9Pm3VAtHDr4,8
30
+ devdash_mac-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ devdash = devdash.__main__:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 DevDash Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ devdash