nestifypy 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.
Files changed (65) hide show
  1. nestifypy/__init__.py +9 -0
  2. nestifypy/cli.py +510 -0
  3. nestifypy/collections/__init__.py +21 -0
  4. nestifypy/collections/array_list.py +270 -0
  5. nestifypy/collections/hash_map.py +285 -0
  6. nestifypy/collections/linked_list.py +222 -0
  7. nestifypy/collections/ordered_set.py +183 -0
  8. nestifypy/collections/queue.py +147 -0
  9. nestifypy/collections/stack.py +148 -0
  10. nestifypy/console/__init__.py +329 -0
  11. nestifypy/core/__init__.py +287 -0
  12. nestifypy/decorators/__init__.py +675 -0
  13. nestifypy/env/__init__.py +189 -0
  14. nestifypy/flow/__init__.py +319 -0
  15. nestifypy/json/__init__.py +18 -0
  16. nestifypy/json/engine.py +88 -0
  17. nestifypy/json/exceptions.py +19 -0
  18. nestifypy/json/models.py +13 -0
  19. nestifypy/json/parser.py +45 -0
  20. nestifypy/json/serializer.py +39 -0
  21. nestifypy/json/utils.py +25 -0
  22. nestifypy/json/validator.py +45 -0
  23. nestifypy/os/__init__.py +13 -0
  24. nestifypy/os/dirs.py +61 -0
  25. nestifypy/os/files.py +80 -0
  26. nestifypy/os/paths.py +43 -0
  27. nestifypy/os/process.py +56 -0
  28. nestifypy/os/system.py +50 -0
  29. nestifypy/py.typed +1 -0
  30. nestifypy/pyunix/__init__.py +55 -0
  31. nestifypy/pyunix/app.py +404 -0
  32. nestifypy/pyunix/assets.py +241 -0
  33. nestifypy/pyunix/audio.py +128 -0
  34. nestifypy/pyunix/camera.py +135 -0
  35. nestifypy/pyunix/events.py +108 -0
  36. nestifypy/pyunix/exceptions.py +35 -0
  37. nestifypy/pyunix/fonts.py +71 -0
  38. nestifypy/pyunix/input.py +271 -0
  39. nestifypy/pyunix/physics.py +363 -0
  40. nestifypy/pyunix/scene.py +277 -0
  41. nestifypy/pyunix/sprite.py +350 -0
  42. nestifypy/pyunix/text.py +148 -0
  43. nestifypy/pyunix/timer.py +149 -0
  44. nestifypy/pyunix/window.py +136 -0
  45. nestifypy/types/__init__.py +239 -0
  46. nestifypy/utils/__init__.py +206 -0
  47. nestifypy/version.py +1 -0
  48. nestifypy/yaml/__init__.py +91 -0
  49. nestifypy/yaml/bootstrap.py +28 -0
  50. nestifypy/yaml/cache.py +36 -0
  51. nestifypy/yaml/engine.py +239 -0
  52. nestifypy/yaml/exceptions.py +11 -0
  53. nestifypy/yaml/metadata.py +88 -0
  54. nestifypy/yaml/models.py +79 -0
  55. nestifypy/yaml/proxy.py +50 -0
  56. nestifypy/yaml/registry.py +84 -0
  57. nestifypy/yaml/runtime.py +92 -0
  58. nestifypy/yaml/scanner.py +107 -0
  59. nestifypy/yaml/watcher.py +117 -0
  60. nestifypy-0.1.0.dist-info/METADATA +208 -0
  61. nestifypy-0.1.0.dist-info/RECORD +65 -0
  62. nestifypy-0.1.0.dist-info/WHEEL +5 -0
  63. nestifypy-0.1.0.dist-info/entry_points.txt +2 -0
  64. nestifypy-0.1.0.dist-info/licenses/LICENSE +21 -0
  65. nestifypy-0.1.0.dist-info/top_level.txt +1 -0
nestifypy/__init__.py ADDED
@@ -0,0 +1,9 @@
1
+ """
2
+ nestifypy
3
+ ======
4
+ Modern utility and game framework for Python.
5
+ """
6
+
7
+ from nestifypy.version import __version__
8
+
9
+ __all__ = ["__version__"]
nestifypy/cli.py ADDED
@@ -0,0 +1,510 @@
1
+ """
2
+ nestifypy.cli
3
+ ----------
4
+ CLI entry point for the Nestifypy ecosystem.
5
+ Registered via pyproject.toml: nestifypy = "nestifypy.cli:main"
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import re
11
+ import sys
12
+ from pathlib import Path
13
+ from typing import Optional
14
+
15
+ import typer
16
+
17
+ app = typer.Typer(
18
+ name="nestifypy",
19
+ help="Nestifypy — Modern utility and game framework for Python",
20
+ no_args_is_help=True,
21
+ rich_markup_mode="rich",
22
+ )
23
+
24
+ # ─────────────────────────────────────────────────────────────────────────────
25
+ # Default project.yml template
26
+ # ─────────────────────────────────────────────────────────────────────────────
27
+
28
+ _DEFAULT_PROJECT_YML = """\
29
+ project:
30
+ name: "{name}"
31
+ version: "0.1.0"
32
+ description: ""
33
+
34
+ python:
35
+ version: "{python_version}"
36
+
37
+ build:
38
+ backend: "uv"
39
+
40
+ docker:
41
+ image: "{name}:latest"
42
+ """
43
+
44
+ _DEFAULT_PYPROJECT = """\
45
+ [build-system]
46
+ requires = ["setuptools>=69", "wheel"]
47
+ build-backend = "setuptools.build_meta"
48
+
49
+ [project]
50
+ name = "{name}"
51
+ version = "0.1.0"
52
+ description = ""
53
+ requires-python = ">={python_version}"
54
+ dependencies = [
55
+ "nestifypy>=0.1.0"
56
+ ]
57
+
58
+ [project.optional-dependencies]
59
+ dev = [
60
+ "ruff>=0.4",
61
+ "pytest>=8.0",
62
+ "mypy>=1.10"
63
+ ]
64
+
65
+ [project.scripts]
66
+ {name} = "{name}.cli:main"
67
+
68
+ [tool.ruff]
69
+ line-length = 88
70
+ target-version = "py310"
71
+
72
+ [tool.ruff.lint]
73
+ select = ["E", "F", "I", "N", "W", "UP"]
74
+
75
+ [tool.pytest.ini_options]
76
+ testpaths = ["tests"]
77
+ python_files = ["test_*.py"]
78
+ addopts = "-v"
79
+ """
80
+
81
+ _DEFAULT_GITIGNORE = """\
82
+ # Byte-compiled / optimized / DLL files
83
+ __pycache__/
84
+ *.py[cod]
85
+ *$py.class
86
+
87
+ # C extensions
88
+ *.so
89
+
90
+ # Distribution / packaging
91
+ .Python
92
+ build/
93
+ develop-eggs/
94
+ dist/
95
+ downloads/
96
+ eggs/
97
+ .eggs/
98
+ lib/
99
+ lib64/
100
+ parts/
101
+ sdist/
102
+ var/
103
+ wheels/
104
+ share/python-wheels/
105
+ *.egg-info/
106
+ .installed.cfg
107
+ *.egg
108
+ MANIFEST
109
+
110
+ # PyInstaller
111
+ # Usually these files are written by a python script from a template
112
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
113
+ *.manifest
114
+ *.spec
115
+
116
+ # Installer logs
117
+ pip-log.txt
118
+ pip-delete-this-directory.txt
119
+
120
+ # Unit test / coverage reports
121
+ htmlcov/
122
+ .tox/
123
+ .nox/
124
+ .coverage
125
+ .coverage.*
126
+ .cache
127
+ nosetests.xml
128
+ coverage.xml
129
+ *.cover
130
+ *.py,cover
131
+ .hypothesis/
132
+ .pytest_cache/
133
+ cover/
134
+
135
+ # Translations
136
+ *.mo
137
+ *.pot
138
+
139
+ # Django stuff:
140
+ *.log
141
+ local_settings.py
142
+ db.sqlite3
143
+ db.sqlite3-journal
144
+
145
+ # Flask stuff:
146
+ instance/
147
+ .webassets-cache
148
+
149
+ # Scrapy stuff:
150
+ .scrapy
151
+
152
+ # Sphinx documentation
153
+ docs/_build/
154
+
155
+ # PyBuilder
156
+ .pybuilder/
157
+ target/
158
+
159
+ # Jupyter Notebook
160
+ .ipynb_checkpoints
161
+
162
+ # IPython
163
+ profile_default/
164
+ ipython_config.py
165
+
166
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
167
+ __pypackages__/
168
+
169
+ # Celery stuff
170
+ celerybeat-schedule
171
+ celerybeat.pid
172
+
173
+ # SageMath parsed files
174
+ *.sage.py
175
+
176
+ # Environments
177
+ .env
178
+ .venv
179
+ env/
180
+ venv/
181
+ ENV/
182
+ env.bak/
183
+ venv.bak/
184
+
185
+ # Spyder project settings
186
+ .spyderproject
187
+ .spyproject
188
+
189
+ # Rope project settings
190
+ .ropeproject
191
+
192
+ # mkdocs documentation
193
+ /site
194
+
195
+ # mypy
196
+ .mypy_cache/
197
+ .dmypy.json
198
+ dmypy.json
199
+
200
+ # Pyre type checker
201
+ .pyre/
202
+
203
+ # pytype static type analyzer
204
+ .pytype/
205
+
206
+ # Cython debug symbols
207
+ cython_debug/
208
+
209
+ # IDEs / Editors
210
+ .idea/
211
+ .vscode/
212
+ *.swp
213
+ *.swo
214
+ *~
215
+ .DS_Store
216
+
217
+ # PyNest specific / local files
218
+ .nestifypy/
219
+ """
220
+
221
+ _DEFAULT_MAIN = """\
222
+ from nestifypy.core import Logger
223
+ from nestifypy.env import Env
224
+
225
+ def main() -> None:
226
+ Env.load()
227
+ Logger.info("Hello from {name}! Environment loaded successfully.")
228
+
229
+ if __name__ == "__main__":
230
+ main()
231
+ """
232
+
233
+
234
+ # ─────────────────────────────────────────────────────────────────────────────
235
+ # init
236
+ # ─────────────────────────────────────────────────────────────────────────────
237
+
238
+ @app.command()
239
+ def init(
240
+ name: Optional[str] = typer.Option(
241
+ None, "--name", "-n", help="Project name"
242
+ ),
243
+ python: str = typer.Option(
244
+ "3.11", "--python", "-p", help="Python version"
245
+ ),
246
+ force: bool = typer.Option(
247
+ False, "--force", "-f", help="Overwrite existing files"
248
+ ),
249
+ ) -> None:
250
+ """Initialize a new Nestifypy project in the current directory."""
251
+
252
+ # Resolve project name
253
+ if name is None:
254
+ name = Path.cwd().name
255
+
256
+ typer.echo(f"\n🪺 Initializing Nestifypy project: [bold]{name}[/bold]\n", color=True)
257
+
258
+ files = {
259
+ "project.yml": _DEFAULT_PROJECT_YML.format(name=name, python_version=python),
260
+ "pyproject.toml": _DEFAULT_PYPROJECT.format(name=name, python_version=python),
261
+ ".gitignore": _DEFAULT_GITIGNORE,
262
+ ".python-version": python,
263
+ f"src/{name}/__init__.py": "",
264
+ f"src/{name}/main.py": _DEFAULT_MAIN.format(name=name),
265
+ "tests/__init__.py": "",
266
+ }
267
+
268
+ created = []
269
+ skipped = []
270
+
271
+ for filepath, content in files.items():
272
+ p = Path(filepath)
273
+ if p.exists() and not force:
274
+ skipped.append(filepath)
275
+ continue
276
+ p.parent.mkdir(parents=True, exist_ok=True)
277
+ p.write_text(content, encoding="utf-8")
278
+ created.append(filepath)
279
+
280
+ for f in created:
281
+ typer.echo(f" ✓ created {f}")
282
+ for f in skipped:
283
+ typer.echo(f" – skipped {f} (use --force to overwrite)")
284
+
285
+ typer.echo(f"\n✅ Project [bold]{name}[/bold] ready!\n")
286
+ typer.echo(" Next steps:")
287
+ typer.echo(" uv sync")
288
+ typer.echo(" nestifypy run\n")
289
+
290
+
291
+ # ─────────────────────────────────────────────────────────────────────────────
292
+ # sync
293
+ # ─────────────────────────────────────────────────────────────────────────────
294
+
295
+ @app.command()
296
+ def sync(
297
+ config: str = typer.Option("project.yml", "--config", "-c", help="Config file"),
298
+ ) -> None:
299
+ """Sync pyproject.toml, .python-version, and Docker files from project.yml."""
300
+
301
+ try:
302
+ import yaml
303
+ except ImportError:
304
+ typer.echo("❌ pyyaml not installed. Run: pip install pyyaml")
305
+ raise typer.Exit(1)
306
+
307
+ cfg_path = Path(config)
308
+ if not cfg_path.exists():
309
+ typer.echo(f"❌ Config file not found: {config}")
310
+ raise typer.Exit(1)
311
+
312
+ with open(cfg_path, "r") as f:
313
+ cfg = yaml.safe_load(f)
314
+
315
+ python_version: str = str(cfg.get("python", {}).get("version", "3.11"))
316
+ project_name: str = cfg.get("project", {}).get("name", "project")
317
+ project_version: str = cfg.get("project", {}).get("version", "0.1.0")
318
+
319
+ typer.echo(f"\n🔄 Syncing from {config}…\n")
320
+
321
+ # .python-version
322
+ pv_path = Path(".python-version")
323
+ pv_path.write_text(python_version)
324
+ typer.echo(f" ✓ .python-version → {python_version}")
325
+
326
+ # pyproject.toml
327
+ pp_path = Path("pyproject.toml")
328
+ if pp_path.exists():
329
+ content = pp_path.read_text(encoding="utf-8")
330
+ content = re.sub(
331
+ r'requires-python\s*=\s*"[^"]+"',
332
+ f'requires-python = ">={python_version}"',
333
+ content,
334
+ )
335
+ content = re.sub(
336
+ r'^version\s*=\s*"[^"]+"',
337
+ f'version = "{project_version}"',
338
+ content,
339
+ flags=re.MULTILINE,
340
+ )
341
+ pp_path.write_text(content, encoding="utf-8")
342
+ typer.echo(f" ✓ pyproject.toml → version={project_version}, python>={python_version}")
343
+
344
+ typer.echo(f"\n✅ Sync complete.\n")
345
+
346
+
347
+ # ─────────────────────────────────────────────────────────────────────────────
348
+ # run
349
+ # ─────────────────────────────────────────────────────────────────────────────
350
+
351
+ @app.command()
352
+ def run(
353
+ entry: str = typer.Option("main.py", "--entry", "-e", help="Entry file to run"),
354
+ module: Optional[str] = typer.Option(None, "--module", "-m", help="Module to run"),
355
+ ) -> None:
356
+ """Run the project entry point."""
357
+ import subprocess
358
+
359
+ if module:
360
+ typer.echo(f"\n▶ Running module: {module}\n")
361
+ subprocess.run([sys.executable, "-m", module], check=False)
362
+ else:
363
+ entry_path = Path(entry)
364
+ if not entry_path.exists():
365
+ # Try src/<name>/main.py
366
+ candidates = list(Path("src").rglob("main.py")) if Path("src").exists() else []
367
+ if candidates:
368
+ entry_path = candidates[0]
369
+ else:
370
+ typer.echo(f"❌ Entry file not found: {entry}")
371
+ raise typer.Exit(1)
372
+ typer.echo(f"\n▶ Running: {entry_path}\n")
373
+ subprocess.run([sys.executable, str(entry_path)], check=False)
374
+
375
+
376
+ # ─────────────────────────────────────────────────────────────────────────────
377
+ # build
378
+ # ─────────────────────────────────────────────────────────────────────────────
379
+
380
+ @app.command()
381
+ def build(
382
+ output: str = typer.Option("dist/", "--output", "-o", help="Output directory"),
383
+ ) -> None:
384
+ """Build the project distribution."""
385
+ import subprocess
386
+
387
+ typer.echo(f"\n📦 Building project…\n")
388
+ result = subprocess.run(
389
+ [sys.executable, "-m", "build", "--outdir", output],
390
+ capture_output=False,
391
+ )
392
+ if result.returncode == 0:
393
+ typer.echo(f"\n✅ Build complete → {output}\n")
394
+ else:
395
+ typer.echo("\n❌ Build failed.\n")
396
+ raise typer.Exit(result.returncode)
397
+
398
+
399
+ # ─────────────────────────────────────────────────────────────────────────────
400
+ # doctor
401
+ # ─────────────────────────────────────────────────────────────────────────────
402
+
403
+ @app.command()
404
+ def doctor() -> None:
405
+ """Check environment health and installed dependencies."""
406
+ import importlib
407
+ import platform
408
+
409
+ typer.echo("\n🩺 Nestifypy Doctor\n")
410
+
411
+ typer.echo(f" Python : {platform.python_version()}")
412
+ typer.echo(f" Platform : {platform.system()} {platform.machine()}")
413
+ typer.echo(f" Executable : {sys.executable}\n")
414
+
415
+ deps = [
416
+ ("pyyaml", "yaml"),
417
+ ("python-dotenv","dotenv"),
418
+ ("typer", "typer"),
419
+ ("watchdog", "watchdog"),
420
+ ("pygame", "pygame"),
421
+ ("ruff", "ruff"),
422
+ ("pytest", "pytest"),
423
+ ("mypy", "mypy"),
424
+ ]
425
+
426
+ for display_name, import_name in deps:
427
+ try:
428
+ mod = importlib.import_module(import_name)
429
+ version = getattr(mod, "__version__", "?")
430
+ typer.echo(f" ✓ {display_name:<20} {version}")
431
+ except ImportError:
432
+ typer.echo(f" – {display_name:<20} not installed")
433
+
434
+ # Check project.yml
435
+ typer.echo()
436
+ if Path("project.yml").exists():
437
+ typer.echo(" ✓ project.yml found")
438
+ else:
439
+ typer.echo(" – project.yml not found (run: nestifypy init)")
440
+
441
+ typer.echo()
442
+
443
+
444
+ # ─────────────────────────────────────────────────────────────────────────────
445
+ # clean
446
+ # ─────────────────────────────────────────────────────────────────────────────
447
+
448
+ @app.command()
449
+ def clean() -> None:
450
+ """Remove build artifacts and caches."""
451
+ import shutil
452
+
453
+ targets = [
454
+ "dist", "build", ".nestifypy",
455
+ "__pycache__", ".mypy_cache", ".ruff_cache",
456
+ ]
457
+ removed = []
458
+ for target in targets:
459
+ for p in Path(".").rglob(target):
460
+ if p.is_dir():
461
+ shutil.rmtree(p)
462
+ removed.append(str(p))
463
+
464
+ if removed:
465
+ for r in removed:
466
+ typer.echo(f" 🗑 removed {r}")
467
+ typer.echo(f"\n✅ Cleaned {len(removed)} items.\n")
468
+ else:
469
+ typer.echo(" Nothing to clean.")
470
+
471
+
472
+ # ─────────────────────────────────────────────────────────────────────────────
473
+ # info
474
+ # ─────────────────────────────────────────────────────────────────────────────
475
+
476
+ @app.command()
477
+ def info() -> None:
478
+ """Show project info from project.yml."""
479
+ try:
480
+ import yaml
481
+ cfg_path = Path("project.yml")
482
+ if not cfg_path.exists():
483
+ typer.echo("❌ project.yml not found. Run: nestifypy init")
484
+ raise typer.Exit(1)
485
+ with open(cfg_path) as f:
486
+ cfg = yaml.safe_load(f)
487
+
488
+ typer.echo("\n🪺 Nestifypy Project Info\n")
489
+ proj = cfg.get("project", {})
490
+ typer.echo(f" Name : {proj.get('name', '-')}")
491
+ typer.echo(f" Version : {proj.get('version', '-')}")
492
+ typer.echo(f" Description : {proj.get('description', '-')}")
493
+ typer.echo(f" Python : {cfg.get('python', {}).get('version', '-')}")
494
+ typer.echo(f" Build : {cfg.get('build', {}).get('backend', '-')}")
495
+ typer.echo()
496
+ except ImportError:
497
+ typer.echo("❌ pyyaml required: pip install pyyaml")
498
+ raise typer.Exit(1)
499
+
500
+
501
+ # ─────────────────────────────────────────────────────────────────────────────
502
+ # Entry
503
+ # ─────────────────────────────────────────────────────────────────────────────
504
+
505
+ def main() -> None:
506
+ app()
507
+
508
+
509
+ if __name__ == "__main__":
510
+ main()
@@ -0,0 +1,21 @@
1
+ """
2
+ nestifypy.collections
3
+ ------------------
4
+ Fluent, Java-inspired data structures.
5
+ """
6
+
7
+ from nestifypy.collections.array_list import ArrayList
8
+ from nestifypy.collections.linked_list import LinkedList
9
+ from nestifypy.collections.stack import Stack
10
+ from nestifypy.collections.queue import Queue
11
+ from nestifypy.collections.ordered_set import OrderedSet
12
+ from nestifypy.collections.hash_map import HashMap
13
+
14
+ __all__ = [
15
+ "ArrayList",
16
+ "LinkedList",
17
+ "Stack",
18
+ "Queue",
19
+ "OrderedSet",
20
+ "HashMap",
21
+ ]