pyhabitat 1.0.30__tar.gz → 1.0.35__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.
Potentially problematic release.
This version of pyhabitat might be problematic. Click here for more details.
- {pyhabitat-1.0.30/pyhabitat.egg-info → pyhabitat-1.0.35}/PKG-INFO +6 -2
- {pyhabitat-1.0.30/pyhabitat-build → pyhabitat-1.0.35}/pyhabitat/__init__.py +4 -0
- {pyhabitat-1.0.30/pyhabitat-build → pyhabitat-1.0.35}/pyhabitat/environment.py +104 -15
- pyhabitat-1.0.35/pyhabitat/report.py +0 -0
- {pyhabitat-1.0.30 → pyhabitat-1.0.35/pyhabitat-build}/pyhabitat/environment.py +88 -13
- {pyhabitat-1.0.30 → pyhabitat-1.0.35/pyhabitat.egg-info}/PKG-INFO +6 -2
- {pyhabitat-1.0.30 → pyhabitat-1.0.35}/pyhabitat.egg-info/SOURCES.txt +1 -0
- {pyhabitat-1.0.30 → pyhabitat-1.0.35}/pyproject.toml +10 -5
- {pyhabitat-1.0.30 → pyhabitat-1.0.35}/LICENSE +0 -0
- {pyhabitat-1.0.30 → pyhabitat-1.0.35}/README.md +0 -0
- {pyhabitat-1.0.30 → pyhabitat-1.0.35}/pyhabitat/cli.py +0 -0
- /pyhabitat-1.0.30/pyhabitat/report.py → /pyhabitat-1.0.35/pyhabitat/demo.py +0 -0
- {pyhabitat-1.0.30 → pyhabitat-1.0.35}/pyhabitat/utils.py +0 -0
- {pyhabitat-1.0.30 → pyhabitat-1.0.35}/pyhabitat-build/__main__.py +0 -0
- {pyhabitat-1.0.30 → pyhabitat-1.0.35/pyhabitat-build}/pyhabitat/__init__.py +0 -0
- {pyhabitat-1.0.30 → pyhabitat-1.0.35}/pyhabitat-build/pyhabitat/cli.py +0 -0
- {pyhabitat-1.0.30 → pyhabitat-1.0.35}/pyhabitat-build/pyhabitat/utils.py +0 -0
- {pyhabitat-1.0.30 → pyhabitat-1.0.35}/pyhabitat.egg-info/dependency_links.txt +0 -0
- {pyhabitat-1.0.30 → pyhabitat-1.0.35}/pyhabitat.egg-info/entry_points.txt +0 -0
- {pyhabitat-1.0.30 → pyhabitat-1.0.35}/pyhabitat.egg-info/top_level.txt +0 -0
- {pyhabitat-1.0.30 → pyhabitat-1.0.35}/setup.cfg +0 -0
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyhabitat
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.35
|
|
4
4
|
Summary: A lightweight library for detecting system environment, GUI, and build properties.
|
|
5
5
|
Author-email: George Clayton Bennett <george.bennett@memphistn.gov>
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Keywords: environment,os-detection,gui,build-system
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: Operating System :: OS Independent
|
|
10
|
-
Classifier:
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
13
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
14
|
+
Classifier: Topic :: Utilities
|
|
11
15
|
Requires-Python: >=3.7
|
|
12
16
|
Description-Content-Type: text/markdown
|
|
13
17
|
License-File: LICENSE
|
|
@@ -30,6 +30,8 @@ from .environment import (
|
|
|
30
30
|
user_darrin_deyoung,
|
|
31
31
|
can_read_input,
|
|
32
32
|
can_spawn_shell,
|
|
33
|
+
is_ascii,
|
|
34
|
+
is_binary,
|
|
33
35
|
)
|
|
34
36
|
|
|
35
37
|
# Optional: Set __all__ for explicit documentation and cleaner imports
|
|
@@ -63,6 +65,8 @@ __all__ = [
|
|
|
63
65
|
'user_darrin_deyoung',
|
|
64
66
|
'can_read_input',
|
|
65
67
|
'can_spawn_shell',
|
|
68
|
+
'is_ascii',
|
|
69
|
+
'is_binary',
|
|
66
70
|
]
|
|
67
71
|
|
|
68
72
|
__version__ = get_version()
|
|
@@ -17,6 +17,12 @@ import logging
|
|
|
17
17
|
import getpass
|
|
18
18
|
import select
|
|
19
19
|
|
|
20
|
+
# On Windows, we need the msvcrt module for non-blocking I/O
|
|
21
|
+
try:
|
|
22
|
+
import msvcrt
|
|
23
|
+
except ImportError:
|
|
24
|
+
msvcrt = None
|
|
25
|
+
|
|
20
26
|
__all__ = [
|
|
21
27
|
'matplotlib_is_available_for_gui_plotting',
|
|
22
28
|
'matplotlib_is_available_for_headless_image_export',
|
|
@@ -512,6 +518,19 @@ def is_python_script(path: Path | str | None = None, debug: bool = False, suppre
|
|
|
512
518
|
return False
|
|
513
519
|
return exec_path.suffix.lower() == '.py'
|
|
514
520
|
|
|
521
|
+
# --- File encoding check ---
|
|
522
|
+
def is_binary(path:str|Path|None=None)->bool:
|
|
523
|
+
"""
|
|
524
|
+
Target file is encoded as binary.
|
|
525
|
+
"""
|
|
526
|
+
pass
|
|
527
|
+
|
|
528
|
+
def is_ascii(path:str|Path|None=None)->bool:
|
|
529
|
+
"""
|
|
530
|
+
Target file is encoded as ascii, plaintext.
|
|
531
|
+
"""
|
|
532
|
+
pass
|
|
533
|
+
|
|
515
534
|
# --- Interpreter Check ---
|
|
516
535
|
|
|
517
536
|
def interp_path(debug: bool = False) -> str:
|
|
@@ -543,21 +562,46 @@ def interactive_terminal_is_available():
|
|
|
543
562
|
then typer.prompt() or input() will work reliably,
|
|
544
563
|
without getting lost in a log or lost entirely.
|
|
545
564
|
|
|
565
|
+
Solution correctly identifies that true interactivity requires:
|
|
566
|
+
(1) a TTY (potential) connection
|
|
567
|
+
(2) the ability to execute
|
|
568
|
+
(3) the ability to read I/O
|
|
569
|
+
(4) ignores known limitatons in restrictive environments
|
|
570
|
+
|
|
571
|
+
Jargon:
|
|
572
|
+
A TTY, short for Teletypewriter or TeleTYpe,
|
|
573
|
+
is a conceptual or physical device that serves
|
|
574
|
+
as the interface for a user to interact with
|
|
575
|
+
a computer system.
|
|
546
576
|
"""
|
|
547
577
|
# Address walmart demo unit edge case, fast check, though this might hamstring othwrwise successful processes
|
|
548
|
-
if
|
|
578
|
+
if user_darrin_deyoung():
|
|
549
579
|
return False
|
|
550
|
-
|
|
580
|
+
|
|
581
|
+
# Check if a tty is attached to stdin,
|
|
582
|
+
# quick failure here if not before testing spwaning and reading
|
|
583
|
+
if not (sys.stdin.isatty() and sys.stdout.isatty()):
|
|
584
|
+
return False
|
|
585
|
+
|
|
586
|
+
# Check of a new shell can be launched to print stuff
|
|
551
587
|
if not can_spawn_shell():
|
|
552
588
|
return False
|
|
589
|
+
|
|
553
590
|
# A user can interact with a console, providing input
|
|
554
591
|
#if not can_read_input():
|
|
555
592
|
# return False
|
|
556
|
-
|
|
593
|
+
|
|
557
594
|
return sys.stdin.isatty() and sys.stdout.isatty()
|
|
558
595
|
|
|
559
596
|
def user_darrin_deyoung():
|
|
560
597
|
"""Common demo unit undicator, edge case that is unable to launch terminal"""
|
|
598
|
+
# Enable teating on non-Windows, non-demo systems
|
|
599
|
+
# where this function would otherwise return False.
|
|
600
|
+
# Linux: `export USER_DARRIN_DEYOUNG=True`
|
|
601
|
+
if os.getenv('USER_DARRIN_DEYOUNG','').lower() == "true":
|
|
602
|
+
print("env var USER_DARRIN_DEYOUNG is set to True.")
|
|
603
|
+
return True
|
|
604
|
+
# Darrin Deyoung is the typical username on demo-mode Windows systems
|
|
561
605
|
if not on_windows():
|
|
562
606
|
return False
|
|
563
607
|
username = getpass.getuser()
|
|
@@ -568,25 +612,33 @@ def can_spawn_shell(override_known:bool=False)->bool:
|
|
|
568
612
|
global _CAN_SPAWN_SHELL
|
|
569
613
|
if _CAN_SPAWN_SHELL is not None and override_known is False:
|
|
570
614
|
return _CAN_SPAWN_SHELL
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
615
|
+
|
|
616
|
+
try:
|
|
617
|
+
# Use a simple, universally applicable command with shell=True
|
|
618
|
+
# 'true' on Linux/macOS, or a basic command on Windows via cmd.exe
|
|
619
|
+
# A simple 'echo' or 'exit 0' would also work
|
|
620
|
+
result = subprocess.run(
|
|
621
|
+
'exit 0', # A shell-internal command that succeeds on most shells
|
|
622
|
+
stdout=subprocess.PIPE,
|
|
623
|
+
stderr=subprocess.PIPE,
|
|
624
|
+
timeout=2,
|
|
625
|
+
shell=True # <--- ESSENTIAL for cross-platform reliability
|
|
626
|
+
)
|
|
577
627
|
|
|
578
|
-
|
|
628
|
+
_CAN_SPAWN_SHELL = result.returncode == 0
|
|
629
|
+
return _CAN_SPAWN_SHELL
|
|
630
|
+
|
|
579
631
|
except subprocess.TimeoutExpired:
|
|
580
|
-
|
|
632
|
+
print("Shell spawn failed: TimeoutExpired")
|
|
581
633
|
_CAN_SPAWN_SHELL = result.returncode == 0
|
|
582
634
|
return _CAN_SPAWN_SHELL
|
|
583
635
|
except subprocess.SubprocessError:
|
|
584
|
-
|
|
636
|
+
print("Shell spawn failed: SubprocessError")
|
|
585
637
|
_CAN_SPAWN_SHELL = False
|
|
586
638
|
return False
|
|
587
639
|
except OSError:
|
|
588
640
|
_CAN_SPAWN_SHELL = False
|
|
589
|
-
|
|
641
|
+
print("Shell spawn failed: OSError (likely permission or missing binary)")
|
|
590
642
|
return False
|
|
591
643
|
|
|
592
644
|
def can_read_input(override_known:bool=False)-> bool:
|
|
@@ -594,10 +646,43 @@ def can_read_input(override_known:bool=False)-> bool:
|
|
|
594
646
|
global _CAN_READ_INPUT
|
|
595
647
|
if _CAN_READ_INPUT is not None and override_known is False:
|
|
596
648
|
return _CAN_READ_INPUT
|
|
649
|
+
|
|
650
|
+
# --- 1. Windows Specific Check (msvcrt) ---
|
|
651
|
+
if msvcrt is not None and sys.stdin.isatty():
|
|
652
|
+
try:
|
|
653
|
+
# msvcrt.kbhit() checks if a keyboard hit is present
|
|
654
|
+
# We don't read the input yet, just check if it's there
|
|
655
|
+
_CAN_READ_INPUT = msvcrt.kbhit()
|
|
656
|
+
# If kbhit returns True, it means a key press is waiting.
|
|
657
|
+
# We assume if the terminal *is* a TTY, it *can* read input.
|
|
658
|
+
# We can't actually call input() without blocking, so we check TTY instead.
|
|
659
|
+
if _CAN_READ_INPUT:
|
|
660
|
+
return True
|
|
661
|
+
|
|
662
|
+
# Since we are checking if a *user can* interact, if we are in a TTY,
|
|
663
|
+
# we assume the capability exists, even if nothing is currently buffered.
|
|
664
|
+
# This prevents the false negative when no key is pressed.
|
|
665
|
+
_CAN_READ_INPUT = True
|
|
666
|
+
return True
|
|
667
|
+
|
|
668
|
+
except Exception as e:
|
|
669
|
+
# Catch errors in the kbhit check itself
|
|
670
|
+
logging.debug(f"msvcrt check failed: {e}")
|
|
671
|
+
pass # Fall through to the select check
|
|
672
|
+
|
|
673
|
+
# --- 2. POSIX/General Check (select) ---
|
|
674
|
+
# This block is reliable on Linux/macOS and other POSIX systems.
|
|
597
675
|
try:
|
|
598
|
-
#
|
|
676
|
+
# _CAN_READ_INPUT is assigned the read-ready list ([] or [sys.stdin])
|
|
677
|
+
# The return value is then the boolean conversion of that list's truthiness.
|
|
678
|
+
# 1. select.select(...) returns a 3-element tuple.
|
|
679
|
+
# 2. [0] gets the read-ready list (rlist).
|
|
680
|
+
# 3. Wrapping the result in bool() converts the list's truth value:
|
|
681
|
+
# - [] becomes False
|
|
682
|
+
# - [sys.stdin] becomes True
|
|
599
683
|
_CAN_READ_INPUT = select.select([sys.stdin], [], [], 0.1)[0]
|
|
600
|
-
|
|
684
|
+
# Return the boolean value of the list: True if [sys.stdin], False if []
|
|
685
|
+
return bool(_CAN_READ_INPUT) # <--- Requied to convert list to boolean
|
|
601
686
|
except ValueError:
|
|
602
687
|
logging.debug("Input check failed: ValueError (invalid file descriptor)")
|
|
603
688
|
_CAN_READ_INPUT = False
|
|
@@ -606,6 +691,9 @@ def can_read_input(override_known:bool=False)-> bool:
|
|
|
606
691
|
logging.debug("Input check failed: OSError (likely I/O issue)")
|
|
607
692
|
_CAN_READ_INPUT = False
|
|
608
693
|
return False
|
|
694
|
+
|
|
695
|
+
# Final fallback: if nothing worked, assume False
|
|
696
|
+
return False
|
|
609
697
|
|
|
610
698
|
# --- Browser Check ---
|
|
611
699
|
def web_browser_is_available() -> bool:
|
|
@@ -623,6 +711,7 @@ def web_browser_is_available() -> bool:
|
|
|
623
711
|
if shutil.which("xdg-open"):
|
|
624
712
|
return True
|
|
625
713
|
return False
|
|
714
|
+
|
|
626
715
|
|
|
627
716
|
# --- LAUNCH MECHANISMS BASED ON ENVIRONMENT ---
|
|
628
717
|
def edit_textfile(path: Path | str | None = None) -> None:
|
|
File without changes
|
|
@@ -17,6 +17,12 @@ import logging
|
|
|
17
17
|
import getpass
|
|
18
18
|
import select
|
|
19
19
|
|
|
20
|
+
# On Windows, we need the msvcrt module for non-blocking I/O
|
|
21
|
+
try:
|
|
22
|
+
import msvcrt
|
|
23
|
+
except ImportError:
|
|
24
|
+
msvcrt = None
|
|
25
|
+
|
|
20
26
|
__all__ = [
|
|
21
27
|
'matplotlib_is_available_for_gui_plotting',
|
|
22
28
|
'matplotlib_is_available_for_headless_image_export',
|
|
@@ -556,21 +562,46 @@ def interactive_terminal_is_available():
|
|
|
556
562
|
then typer.prompt() or input() will work reliably,
|
|
557
563
|
without getting lost in a log or lost entirely.
|
|
558
564
|
|
|
565
|
+
Solution correctly identifies that true interactivity requires:
|
|
566
|
+
(1) a TTY (potential) connection
|
|
567
|
+
(2) the ability to execute
|
|
568
|
+
(3) the ability to read I/O
|
|
569
|
+
(4) ignores known limitatons in restrictive environments
|
|
570
|
+
|
|
571
|
+
Jargon:
|
|
572
|
+
A TTY, short for Teletypewriter or TeleTYpe,
|
|
573
|
+
is a conceptual or physical device that serves
|
|
574
|
+
as the interface for a user to interact with
|
|
575
|
+
a computer system.
|
|
559
576
|
"""
|
|
560
577
|
# Address walmart demo unit edge case, fast check, though this might hamstring othwrwise successful processes
|
|
561
578
|
if user_darrin_deyoung():
|
|
562
579
|
return False
|
|
580
|
+
|
|
581
|
+
# Check if a tty is attached to stdin,
|
|
582
|
+
# quick failure here if not before testing spwaning and reading
|
|
583
|
+
if not (sys.stdin.isatty() and sys.stdout.isatty()):
|
|
584
|
+
return False
|
|
585
|
+
|
|
563
586
|
# Check of a new shell can be launched to print stuff
|
|
564
587
|
if not can_spawn_shell():
|
|
565
588
|
return False
|
|
589
|
+
|
|
566
590
|
# A user can interact with a console, providing input
|
|
567
591
|
#if not can_read_input():
|
|
568
592
|
# return False
|
|
569
|
-
|
|
593
|
+
|
|
570
594
|
return sys.stdin.isatty() and sys.stdout.isatty()
|
|
571
595
|
|
|
572
596
|
def user_darrin_deyoung():
|
|
573
597
|
"""Common demo unit undicator, edge case that is unable to launch terminal"""
|
|
598
|
+
# Enable teating on non-Windows, non-demo systems
|
|
599
|
+
# where this function would otherwise return False.
|
|
600
|
+
# Linux: `export USER_DARRIN_DEYOUNG=True`
|
|
601
|
+
if os.getenv('USER_DARRIN_DEYOUNG','').lower() == "true":
|
|
602
|
+
print("env var USER_DARRIN_DEYOUNG is set to True.")
|
|
603
|
+
return True
|
|
604
|
+
# Darrin Deyoung is the typical username on demo-mode Windows systems
|
|
574
605
|
if not on_windows():
|
|
575
606
|
return False
|
|
576
607
|
username = getpass.getuser()
|
|
@@ -581,25 +612,33 @@ def can_spawn_shell(override_known:bool=False)->bool:
|
|
|
581
612
|
global _CAN_SPAWN_SHELL
|
|
582
613
|
if _CAN_SPAWN_SHELL is not None and override_known is False:
|
|
583
614
|
return _CAN_SPAWN_SHELL
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
615
|
+
|
|
616
|
+
try:
|
|
617
|
+
# Use a simple, universally applicable command with shell=True
|
|
618
|
+
# 'true' on Linux/macOS, or a basic command on Windows via cmd.exe
|
|
619
|
+
# A simple 'echo' or 'exit 0' would also work
|
|
620
|
+
result = subprocess.run(
|
|
621
|
+
'exit 0', # A shell-internal command that succeeds on most shells
|
|
622
|
+
stdout=subprocess.PIPE,
|
|
623
|
+
stderr=subprocess.PIPE,
|
|
624
|
+
timeout=2,
|
|
625
|
+
shell=True # <--- ESSENTIAL for cross-platform reliability
|
|
626
|
+
)
|
|
590
627
|
|
|
591
|
-
|
|
628
|
+
_CAN_SPAWN_SHELL = result.returncode == 0
|
|
629
|
+
return _CAN_SPAWN_SHELL
|
|
630
|
+
|
|
592
631
|
except subprocess.TimeoutExpired:
|
|
593
|
-
|
|
632
|
+
print("Shell spawn failed: TimeoutExpired")
|
|
594
633
|
_CAN_SPAWN_SHELL = result.returncode == 0
|
|
595
634
|
return _CAN_SPAWN_SHELL
|
|
596
635
|
except subprocess.SubprocessError:
|
|
597
|
-
|
|
636
|
+
print("Shell spawn failed: SubprocessError")
|
|
598
637
|
_CAN_SPAWN_SHELL = False
|
|
599
638
|
return False
|
|
600
639
|
except OSError:
|
|
601
640
|
_CAN_SPAWN_SHELL = False
|
|
602
|
-
|
|
641
|
+
print("Shell spawn failed: OSError (likely permission or missing binary)")
|
|
603
642
|
return False
|
|
604
643
|
|
|
605
644
|
def can_read_input(override_known:bool=False)-> bool:
|
|
@@ -607,10 +646,43 @@ def can_read_input(override_known:bool=False)-> bool:
|
|
|
607
646
|
global _CAN_READ_INPUT
|
|
608
647
|
if _CAN_READ_INPUT is not None and override_known is False:
|
|
609
648
|
return _CAN_READ_INPUT
|
|
649
|
+
|
|
650
|
+
# --- 1. Windows Specific Check (msvcrt) ---
|
|
651
|
+
if msvcrt is not None and sys.stdin.isatty():
|
|
652
|
+
try:
|
|
653
|
+
# msvcrt.kbhit() checks if a keyboard hit is present
|
|
654
|
+
# We don't read the input yet, just check if it's there
|
|
655
|
+
_CAN_READ_INPUT = msvcrt.kbhit()
|
|
656
|
+
# If kbhit returns True, it means a key press is waiting.
|
|
657
|
+
# We assume if the terminal *is* a TTY, it *can* read input.
|
|
658
|
+
# We can't actually call input() without blocking, so we check TTY instead.
|
|
659
|
+
if _CAN_READ_INPUT:
|
|
660
|
+
return True
|
|
661
|
+
|
|
662
|
+
# Since we are checking if a *user can* interact, if we are in a TTY,
|
|
663
|
+
# we assume the capability exists, even if nothing is currently buffered.
|
|
664
|
+
# This prevents the false negative when no key is pressed.
|
|
665
|
+
_CAN_READ_INPUT = True
|
|
666
|
+
return True
|
|
667
|
+
|
|
668
|
+
except Exception as e:
|
|
669
|
+
# Catch errors in the kbhit check itself
|
|
670
|
+
logging.debug(f"msvcrt check failed: {e}")
|
|
671
|
+
pass # Fall through to the select check
|
|
672
|
+
|
|
673
|
+
# --- 2. POSIX/General Check (select) ---
|
|
674
|
+
# This block is reliable on Linux/macOS and other POSIX systems.
|
|
610
675
|
try:
|
|
611
|
-
#
|
|
676
|
+
# _CAN_READ_INPUT is assigned the read-ready list ([] or [sys.stdin])
|
|
677
|
+
# The return value is then the boolean conversion of that list's truthiness.
|
|
678
|
+
# 1. select.select(...) returns a 3-element tuple.
|
|
679
|
+
# 2. [0] gets the read-ready list (rlist).
|
|
680
|
+
# 3. Wrapping the result in bool() converts the list's truth value:
|
|
681
|
+
# - [] becomes False
|
|
682
|
+
# - [sys.stdin] becomes True
|
|
612
683
|
_CAN_READ_INPUT = select.select([sys.stdin], [], [], 0.1)[0]
|
|
613
|
-
|
|
684
|
+
# Return the boolean value of the list: True if [sys.stdin], False if []
|
|
685
|
+
return bool(_CAN_READ_INPUT) # <--- Requied to convert list to boolean
|
|
614
686
|
except ValueError:
|
|
615
687
|
logging.debug("Input check failed: ValueError (invalid file descriptor)")
|
|
616
688
|
_CAN_READ_INPUT = False
|
|
@@ -619,6 +691,9 @@ def can_read_input(override_known:bool=False)-> bool:
|
|
|
619
691
|
logging.debug("Input check failed: OSError (likely I/O issue)")
|
|
620
692
|
_CAN_READ_INPUT = False
|
|
621
693
|
return False
|
|
694
|
+
|
|
695
|
+
# Final fallback: if nothing worked, assume False
|
|
696
|
+
return False
|
|
622
697
|
|
|
623
698
|
# --- Browser Check ---
|
|
624
699
|
def web_browser_is_available() -> bool:
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyhabitat
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.35
|
|
4
4
|
Summary: A lightweight library for detecting system environment, GUI, and build properties.
|
|
5
5
|
Author-email: George Clayton Bennett <george.bennett@memphistn.gov>
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Keywords: environment,os-detection,gui,build-system
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: Operating System :: OS Independent
|
|
10
|
-
Classifier:
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
13
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
14
|
+
Classifier: Topic :: Utilities
|
|
11
15
|
Requires-Python: >=3.7
|
|
12
16
|
Description-Content-Type: text/markdown
|
|
13
17
|
License-File: LICENSE
|
|
@@ -6,21 +6,26 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "pyhabitat"
|
|
9
|
-
version = "1.0.
|
|
10
|
-
#dynamic = ["version"]
|
|
9
|
+
version = "1.0.35"
|
|
10
|
+
#dynamic = ["version"]
|
|
11
11
|
authors = [
|
|
12
12
|
{ name="George Clayton Bennett", email="george.bennett@memphistn.gov" },
|
|
13
13
|
]
|
|
14
14
|
description = "A lightweight library for detecting system environment, GUI, and build properties."
|
|
15
15
|
readme = "README.md"
|
|
16
16
|
requires-python = ">=3.7"
|
|
17
|
-
license = "MIT"
|
|
17
|
+
license = "MIT"
|
|
18
18
|
keywords = ["environment", "os-detection", "gui", "build-system"]
|
|
19
|
-
classifiers
|
|
19
|
+
classifiers=[
|
|
20
20
|
"Programming Language :: Python :: 3",
|
|
21
21
|
"Operating System :: OS Independent",
|
|
22
|
-
"
|
|
22
|
+
"Intended Audience :: Developers",
|
|
23
|
+
"Environment :: Console",
|
|
24
|
+
"Topic :: Software Development :: Build Tools",
|
|
25
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
26
|
+
"Topic :: Utilities",
|
|
23
27
|
]
|
|
28
|
+
|
|
24
29
|
dependencies = []
|
|
25
30
|
|
|
26
31
|
[project.scripts]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|