pyhabitat 1.0.7__py3-none-any.whl → 1.0.9__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.
Potentially problematic release.
This version of pyhabitat might be problematic. Click here for more details.
- pyhabitat/environment.py +5 -3
- {pyhabitat-1.0.7.dist-info → pyhabitat-1.0.9.dist-info}/METADATA +43 -19
- pyhabitat-1.0.9.dist-info/RECORD +7 -0
- pyhabitat-1.0.7.dist-info/RECORD +0 -7
- {pyhabitat-1.0.7.dist-info → pyhabitat-1.0.9.dist-info}/WHEEL +0 -0
- {pyhabitat-1.0.7.dist-info → pyhabitat-1.0.9.dist-info}/licenses/LICENSE +0 -0
- {pyhabitat-1.0.7.dist-info → pyhabitat-1.0.9.dist-info}/top_level.txt +0 -0
pyhabitat/environment.py
CHANGED
|
@@ -418,12 +418,14 @@ def is_pipx(debug=False) -> bool:
|
|
|
418
418
|
|
|
419
419
|
|
|
420
420
|
# --- TTY CHECK ---
|
|
421
|
-
def
|
|
421
|
+
def interactive_terminal_is_available():
|
|
422
422
|
"""
|
|
423
423
|
Check if the script is running in an interactive terminal.
|
|
424
424
|
Assumpton:
|
|
425
|
-
If
|
|
426
|
-
then typer.prompt() will work reliably
|
|
425
|
+
If interactive_terminal_is_available() returns True,
|
|
426
|
+
then typer.prompt() or input() will work reliably,
|
|
427
|
+
without getting lost in a log or lost entirely.
|
|
428
|
+
|
|
427
429
|
"""
|
|
428
430
|
# Check if a tty is attached to stdin
|
|
429
431
|
return sys.stdin.isatty() and sys.stdout.isatty()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyhabitat
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.9
|
|
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
|
|
@@ -25,37 +25,51 @@ Dynamic: license-file
|
|
|
25
25
|
|
|
26
26
|
Stop writing verbose `sys.platform` and environment variable checks. Use **`pyhabitat`** to implement clean, **architectural logic** based on the execution habitat.
|
|
27
27
|
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
Read the code on [github](https://github.com/City-of-Memphis-Wastewater/pyhabitat/blob/main/pyhabitat/environment.py).
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 📦 Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install pyhabitat
|
|
38
|
+
```
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
<details>
|
|
42
|
+
<summary> Motivation </summary>
|
|
28
43
|
This library is especially useful for **leveraging Python in mobile environments** (`Termux` on Android and `iSH` on iOS), which often have particular limitations and require special handling. For example, it helps automate work-arounds like using **localhost plotting** when `matplotlib` is unavailable or **web-based interfaces** when `tkinter` is missing.
|
|
29
44
|
|
|
30
45
|
Our team is fundamentally driven by enabling mobile computing for true utility applications, leveraging environments like Termux (Android) and iSH (iOS). This includes highly practical solutions, such as deploying a lightweight Python web server (e.g., Flask, http.server, FastAPI) directly on a handset, or orchestrating full-stack, utility-grade applications that allow technicians to manage data and systems right from their mobile device in a way that is cross-platform and not overly catered to the App Store.
|
|
31
46
|
|
|
32
|
-
Another key goal of this project is to facilitate the orchestration of wider system installation for **`pipx` CLI tools** for additional touch points, like
|
|
47
|
+
Another key goal of this project is to facilitate the orchestration of wider system installation for **`pipx` CLI tools** for additional touch points, like context menus and widgets.
|
|
33
48
|
|
|
34
49
|
Ultimately, [City-of-Memphis-Wastewater](https://github.com/City-of-Memphis-Wastewater) aims to produce **reference-quality code** for the documented proper approach. We recognize that many people (and bots) are searching for ideal solutions, and our functions are built upon extensive research and testing to go **beyond simple `platform.system()` checks**.
|
|
35
50
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
Read the code on [github](https://github.com/City-of-Memphis-Wastewater/pyhabitat/blob/main/pyhabitat/environment.py).
|
|
51
|
+
</details>
|
|
39
52
|
|
|
40
53
|
---
|
|
41
54
|
|
|
42
|
-
|
|
55
|
+
<details>
|
|
56
|
+
<summary> 🚀 Features </summary>
|
|
43
57
|
|
|
44
58
|
* **Definitive Environment Checks:** Rigorous checks catered to Termux and iSH (iOS Alpine). Accurate, typical modern detection for Windows, macOS (Apple), Linux, FreeBSD, Android.
|
|
45
59
|
* **GUI Availability:** Rigorous, cached checks to determine if the environment supports a graphical popup window (Tkinter/Matplotlib TkAgg) or just headless image export (Matplotlib Agg).
|
|
46
60
|
* **Build/Packaging Detection:** Reliable detection of standalone executables built by tools like PyInstaller, and, crucially, correct identification and exclusion of pipx-managed virtual environments, which also user binaries that could conflate the check.
|
|
47
61
|
* **Executable Type Inspection:** Uses file magic numbers (ELF and MZ) to confirm if the running script is a monolithic, frozen binary (non-pipx).
|
|
48
62
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
pip install pyhabitat
|
|
53
|
-
```
|
|
63
|
+
</details>
|
|
64
|
+
|
|
54
65
|
---
|
|
55
66
|
|
|
56
|
-
|
|
67
|
+
<details>
|
|
68
|
+
<summary> 📚 Function Reference </summary>
|
|
57
69
|
|
|
58
|
-
### OS and Environment
|
|
70
|
+
### OS and Environment Checking
|
|
71
|
+
|
|
72
|
+
Key question: "What is this running on?"
|
|
59
73
|
|
|
60
74
|
| Function | Description |
|
|
61
75
|
| :--- | :--- |
|
|
@@ -66,7 +80,9 @@ pip install pyhabitat
|
|
|
66
80
|
| `is_ish_alpine()` | Returns `True` if running in the iSH Alpine Linux iOS emulator. |
|
|
67
81
|
| `is_android()` | Returns `True` on any Android-based Linux environment. |
|
|
68
82
|
|
|
69
|
-
###
|
|
83
|
+
### Packaging and Build Checking
|
|
84
|
+
|
|
85
|
+
Key question: "What is the character of my executable?"
|
|
70
86
|
|
|
71
87
|
| Function | Description |
|
|
72
88
|
| :--- | :--- |
|
|
@@ -76,24 +92,30 @@ pip install pyhabitat
|
|
|
76
92
|
| `is_windows_portable_executable()` | Checks if the executable is a Windows PE binary (MZ header), excluding pipx. |
|
|
77
93
|
| `is_macos_executable()` | Checks if the executable is a macOS/Darwin Mach-O binary, excluding pipx. |
|
|
78
94
|
|
|
79
|
-
###
|
|
95
|
+
### Capability Checking
|
|
96
|
+
|
|
97
|
+
Key Question: "What could I do next?"
|
|
80
98
|
|
|
81
99
|
| Function | Description |
|
|
82
100
|
| :--- | :--- |
|
|
83
101
|
| `tkinter_is_available()` | Checks if Tkinter is imported and can successfully create a window. |
|
|
84
102
|
| `matplotlib_is_available_for_gui_plotting(termux_has_gui=False)` | Checks for Matplotlib and its TkAgg backend, required for interactive plotting. |
|
|
85
103
|
| `matplotlib_is_available_for_headless_image_export()` | Checks for Matplotlib and its Agg backend, required for saving images without a GUI. |
|
|
86
|
-
| `
|
|
104
|
+
| `interactive_terminal_is_available()` | Checks if standard input and output streams are connected to a TTY (allows safe use of interactive prompts). |
|
|
87
105
|
| `web_browser_is_available()` | Check if a web browser can be launched in the current environment (allows safe use of web-based prompts and localhost plotting). |
|
|
88
106
|
|
|
89
107
|
### Actions
|
|
108
|
+
|
|
90
109
|
| Function | Description |
|
|
91
110
|
| :--- | :--- |
|
|
92
111
|
| `open_text_file_in_default_app()` | Smoothly opens a text file for editing (for configuration editing prompted by a CLI flag). |
|
|
93
112
|
|
|
113
|
+
</details>
|
|
114
|
+
|
|
94
115
|
---
|
|
95
116
|
|
|
96
|
-
|
|
117
|
+
<details>
|
|
118
|
+
<summary> 💻 Usage Examples </summary>
|
|
97
119
|
|
|
98
120
|
The module exposes all detection functions directly for easy access.
|
|
99
121
|
|
|
@@ -111,7 +133,7 @@ elif is_frozen():
|
|
|
111
133
|
elif is_termux():
|
|
112
134
|
# Expected cases:
|
|
113
135
|
#- pkg install python-numpy python-cryptography
|
|
114
|
-
|
|
136
|
+
#- Avoiding matplotlib unless the user explicitly confirms that termux_has_gui=False in matplotlib_is_available_for_gui_plotting(termux_has_gui=False).
|
|
115
137
|
#- Auto-selection of 'termux-open-url' and 'xdg-open' in logic.
|
|
116
138
|
#- Installation on the system, like orchestrating the construction of Termux Widget entries in ~/.shortcuts.
|
|
117
139
|
print("Running in the Termux environment on Android.")
|
|
@@ -125,7 +147,7 @@ elif is_windows():
|
|
|
125
147
|
Use these functions to determine if you can show an interactive plot or if you must save an image file.
|
|
126
148
|
|
|
127
149
|
```python
|
|
128
|
-
from pyhabitat import matplotlib_is_available_for_gui_plotting, matplotlib_is_available_for_headless_image_export
|
|
150
|
+
from pyhabitat import matplotlib_is_available_for_gui_plotting, matplotlib_is_available_for_headless_image_export,
|
|
129
151
|
|
|
130
152
|
if matplotlib_is_available_for_gui_plotting():
|
|
131
153
|
# We can safely call plt.show()
|
|
@@ -151,6 +173,8 @@ Ideal use case: Edit a configuration file, if prompted by a CLI command like 'co
|
|
|
151
173
|
```python
|
|
152
174
|
open_text_file_in_default_app(filepath=Path('./config.json'))
|
|
153
175
|
```
|
|
176
|
+
</details>
|
|
177
|
+
|
|
154
178
|
---
|
|
155
179
|
|
|
156
180
|
## 🤝 Contributing
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
pyhabitat/__init__.py,sha256=fy1SRFXok05bCprjGMCXS5afw27iKBJCLeSQTuBjlRI,1101
|
|
2
|
+
pyhabitat/environment.py,sha256=rteFLXko5VaxwgfQYRR7SBQaRygKqrNr0YjRYQ5mybo,18206
|
|
3
|
+
pyhabitat-1.0.9.dist-info/licenses/LICENSE,sha256=D4fg30ctUGnCJlWu3ONv5-V8JE1v3ctakoJTcVjsJlg,1072
|
|
4
|
+
pyhabitat-1.0.9.dist-info/METADATA,sha256=Th1AvU7Fvpy7WSaesAi1BMVoRcECPlWsmcWV2RGKgNA,8478
|
|
5
|
+
pyhabitat-1.0.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
6
|
+
pyhabitat-1.0.9.dist-info/top_level.txt,sha256=zXYK44Qu8EqxUETREvd2diMUaB5JiGRErkwFaoLQnnI,10
|
|
7
|
+
pyhabitat-1.0.9.dist-info/RECORD,,
|
pyhabitat-1.0.7.dist-info/RECORD
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
pyhabitat/__init__.py,sha256=fy1SRFXok05bCprjGMCXS5afw27iKBJCLeSQTuBjlRI,1101
|
|
2
|
-
pyhabitat/environment.py,sha256=eGF6BSTNEnbit6RNVhG6JPqckhhnGlYE3vukq_GRPSk,18114
|
|
3
|
-
pyhabitat-1.0.7.dist-info/licenses/LICENSE,sha256=D4fg30ctUGnCJlWu3ONv5-V8JE1v3ctakoJTcVjsJlg,1072
|
|
4
|
-
pyhabitat-1.0.7.dist-info/METADATA,sha256=7dPMUZ9mC9AzJbmcCkgat3l3Jdmr56s9ZxCun6R5aqg,8126
|
|
5
|
-
pyhabitat-1.0.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
6
|
-
pyhabitat-1.0.7.dist-info/top_level.txt,sha256=zXYK44Qu8EqxUETREvd2diMUaB5JiGRErkwFaoLQnnI,10
|
|
7
|
-
pyhabitat-1.0.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|