mflux-web 0.0.1a1__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.
- mflux_web-0.0.1a1/PKG-INFO +106 -0
- mflux_web-0.0.1a1/README.md +92 -0
- mflux_web-0.0.1a1/pyproject.toml +72 -0
- mflux_web-0.0.1a1/pyproject.toml.orig +56 -0
- mflux_web-0.0.1a1/src/mflux/web/__init__.py +13 -0
- mflux_web-0.0.1a1/src/mflux_web/__init__.py +9 -0
- mflux_web-0.0.1a1/tests/test_packaging.py +131 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: mflux-web
|
|
3
|
+
Version: 0.0.1a1
|
|
4
|
+
Summary: Web integration for mflux with a standalone Python API
|
|
5
|
+
Author: Anthony Wu
|
|
6
|
+
Author-email: Anthony Wu <462072+anthonywu@users.noreply.github.com>
|
|
7
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
12
|
+
Requires-Python: >=3.11
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# mflux-web
|
|
16
|
+
|
|
17
|
+
Install (once published):
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
pip install mflux-web
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Both entry points resolve to the same module object:
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
import mflux.web
|
|
27
|
+
import mflux_web
|
|
28
|
+
|
|
29
|
+
assert mflux.web is mflux_web
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`mflux_web` owns the implementation and works without installing or importing
|
|
33
|
+
`mflux`. Importing `mflux.web` registers it as an alias of `mflux_web`, sharing
|
|
34
|
+
all public symbols and module state. Either import order works, and the greeting
|
|
35
|
+
prints once per process. Submodules are not automatically aliased; use
|
|
36
|
+
`mflux.web.<plugin>` for third-party plugins. This initial scaffold has no web
|
|
37
|
+
server or application API yet.
|
|
38
|
+
|
|
39
|
+
## Namespace ownership
|
|
40
|
+
|
|
41
|
+
This distribution owns `mflux/web/__init__.py` and `mflux_web/`. It deliberately
|
|
42
|
+
does **not** ship `mflux/__init__.py` or require the inference distribution.
|
|
43
|
+
The `mflux.web` alias adds plugin directories discovered by `pkgutil.extend_path`
|
|
44
|
+
to the shared package path, so other distributions can contribute subpackages
|
|
45
|
+
even from separate import paths.
|
|
46
|
+
|
|
47
|
+
A plugin distribution can ship:
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
src/
|
|
51
|
+
└── mflux/
|
|
52
|
+
└── web/
|
|
53
|
+
└── anythingelse/
|
|
54
|
+
└── __init__.py
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
With this uv build configuration:
|
|
58
|
+
|
|
59
|
+
```toml
|
|
60
|
+
[project]
|
|
61
|
+
name = "mflux-web-anythingelse"
|
|
62
|
+
version = "0.1.0"
|
|
63
|
+
dependencies = ["mflux-web>=0.0.1a1"]
|
|
64
|
+
|
|
65
|
+
[build-system]
|
|
66
|
+
requires = ["uv_build>=0.12.15,<0.13.0"]
|
|
67
|
+
build-backend = "uv_build"
|
|
68
|
+
|
|
69
|
+
[tool.uv.build-backend]
|
|
70
|
+
module-name = "mflux.web.anythingelse"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Consumers can then use `import mflux.web.anythingelse`. Plugins must not ship
|
|
74
|
+
`mflux/__init__.py` or `mflux/web/__init__.py`; each owns a unique child name.
|
|
75
|
+
|
|
76
|
+
## Integration with the mflux parent
|
|
77
|
+
|
|
78
|
+
The existing mflux project has a regular `mflux/__init__.py`. Normal wheel
|
|
79
|
+
installations into the same site-packages directory coexist with this package.
|
|
80
|
+
For separate editable installs or other split-path layouts, add this to the
|
|
81
|
+
**mflux project's** existing `src/mflux/__init__.py`, retaining its current setup:
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from pkgutil import extend_path
|
|
85
|
+
|
|
86
|
+
__path__ = extend_path(__path__, __name__)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Without that parent change, an installed regular mflux package can hide an
|
|
90
|
+
editable mflux-web checkout. Setting `namespace = true` in build configuration
|
|
91
|
+
does not change Python's runtime import behavior. This repository does not
|
|
92
|
+
modify or replace the parent initializer.
|
|
93
|
+
|
|
94
|
+
## Development
|
|
95
|
+
|
|
96
|
+
Use uv-managed Python 3.14 for development; the library supports Python 3.11–3.15.
|
|
97
|
+
|
|
98
|
+
```sh
|
|
99
|
+
uv sync
|
|
100
|
+
uv build
|
|
101
|
+
uv run python -m unittest discover -s tests -v
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The tests build the distributions in a temporary directory and check their
|
|
105
|
+
contents and imports in isolated subprocesses, including third-party namespace
|
|
106
|
+
contributions and regular-parent coexistence.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# mflux-web
|
|
2
|
+
|
|
3
|
+
Install (once published):
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
pip install mflux-web
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Both entry points resolve to the same module object:
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
import mflux.web
|
|
13
|
+
import mflux_web
|
|
14
|
+
|
|
15
|
+
assert mflux.web is mflux_web
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`mflux_web` owns the implementation and works without installing or importing
|
|
19
|
+
`mflux`. Importing `mflux.web` registers it as an alias of `mflux_web`, sharing
|
|
20
|
+
all public symbols and module state. Either import order works, and the greeting
|
|
21
|
+
prints once per process. Submodules are not automatically aliased; use
|
|
22
|
+
`mflux.web.<plugin>` for third-party plugins. This initial scaffold has no web
|
|
23
|
+
server or application API yet.
|
|
24
|
+
|
|
25
|
+
## Namespace ownership
|
|
26
|
+
|
|
27
|
+
This distribution owns `mflux/web/__init__.py` and `mflux_web/`. It deliberately
|
|
28
|
+
does **not** ship `mflux/__init__.py` or require the inference distribution.
|
|
29
|
+
The `mflux.web` alias adds plugin directories discovered by `pkgutil.extend_path`
|
|
30
|
+
to the shared package path, so other distributions can contribute subpackages
|
|
31
|
+
even from separate import paths.
|
|
32
|
+
|
|
33
|
+
A plugin distribution can ship:
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
src/
|
|
37
|
+
└── mflux/
|
|
38
|
+
└── web/
|
|
39
|
+
└── anythingelse/
|
|
40
|
+
└── __init__.py
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
With this uv build configuration:
|
|
44
|
+
|
|
45
|
+
```toml
|
|
46
|
+
[project]
|
|
47
|
+
name = "mflux-web-anythingelse"
|
|
48
|
+
version = "0.1.0"
|
|
49
|
+
dependencies = ["mflux-web>=0.0.1a1"]
|
|
50
|
+
|
|
51
|
+
[build-system]
|
|
52
|
+
requires = ["uv_build>=0.12.15,<0.13.0"]
|
|
53
|
+
build-backend = "uv_build"
|
|
54
|
+
|
|
55
|
+
[tool.uv.build-backend]
|
|
56
|
+
module-name = "mflux.web.anythingelse"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Consumers can then use `import mflux.web.anythingelse`. Plugins must not ship
|
|
60
|
+
`mflux/__init__.py` or `mflux/web/__init__.py`; each owns a unique child name.
|
|
61
|
+
|
|
62
|
+
## Integration with the mflux parent
|
|
63
|
+
|
|
64
|
+
The existing mflux project has a regular `mflux/__init__.py`. Normal wheel
|
|
65
|
+
installations into the same site-packages directory coexist with this package.
|
|
66
|
+
For separate editable installs or other split-path layouts, add this to the
|
|
67
|
+
**mflux project's** existing `src/mflux/__init__.py`, retaining its current setup:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from pkgutil import extend_path
|
|
71
|
+
|
|
72
|
+
__path__ = extend_path(__path__, __name__)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Without that parent change, an installed regular mflux package can hide an
|
|
76
|
+
editable mflux-web checkout. Setting `namespace = true` in build configuration
|
|
77
|
+
does not change Python's runtime import behavior. This repository does not
|
|
78
|
+
modify or replace the parent initializer.
|
|
79
|
+
|
|
80
|
+
## Development
|
|
81
|
+
|
|
82
|
+
Use uv-managed Python 3.14 for development; the library supports Python 3.11–3.15.
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
uv sync
|
|
86
|
+
uv build
|
|
87
|
+
uv run python -m unittest discover -s tests -v
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The tests build the distributions in a temporary directory and check their
|
|
91
|
+
contents and imports in isolated subprocesses, including third-party namespace
|
|
92
|
+
contributions and regular-parent coexistence.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "mflux-web"
|
|
3
|
+
version = "0.0.1a1"
|
|
4
|
+
description = "Web integration for mflux with a standalone Python API"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
classifiers = [
|
|
8
|
+
"Programming Language :: Python :: 3.11",
|
|
9
|
+
"Programming Language :: Python :: 3.12",
|
|
10
|
+
"Programming Language :: Python :: 3.13",
|
|
11
|
+
"Programming Language :: Python :: 3.14",
|
|
12
|
+
"Programming Language :: Python :: 3.15",
|
|
13
|
+
]
|
|
14
|
+
dependencies = []
|
|
15
|
+
|
|
16
|
+
[[project.authors]]
|
|
17
|
+
name = "Anthony Wu"
|
|
18
|
+
email = "462072+anthonywu@users.noreply.github.com"
|
|
19
|
+
|
|
20
|
+
[build-system]
|
|
21
|
+
requires = ["uv_build>=0.12.15,<0.13.0"]
|
|
22
|
+
build-backend = "uv_build"
|
|
23
|
+
|
|
24
|
+
[tool.uv.build-backend]
|
|
25
|
+
module-name = [
|
|
26
|
+
"mflux_web",
|
|
27
|
+
"mflux.web",
|
|
28
|
+
]
|
|
29
|
+
source-include = ["tests/**"]
|
|
30
|
+
|
|
31
|
+
[tool.ruff]
|
|
32
|
+
target-version = "py311"
|
|
33
|
+
line-length = 88
|
|
34
|
+
src = ["src"]
|
|
35
|
+
|
|
36
|
+
[tool.ruff.lint]
|
|
37
|
+
select = [
|
|
38
|
+
"E4",
|
|
39
|
+
"E7",
|
|
40
|
+
"E9",
|
|
41
|
+
"F",
|
|
42
|
+
"I",
|
|
43
|
+
"UP",
|
|
44
|
+
"B",
|
|
45
|
+
"SIM",
|
|
46
|
+
"RUF",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
[tool.ruff.format]
|
|
50
|
+
quote-style = "double"
|
|
51
|
+
indent-style = "space"
|
|
52
|
+
|
|
53
|
+
[tool.ty.environment]
|
|
54
|
+
python-version = "3.11"
|
|
55
|
+
|
|
56
|
+
[tool.ty.src]
|
|
57
|
+
include = [
|
|
58
|
+
"src",
|
|
59
|
+
"tests",
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
[tool.ty.rules]
|
|
63
|
+
unused-ignore-comment = "warn"
|
|
64
|
+
|
|
65
|
+
[tool.ty.terminal]
|
|
66
|
+
error-on-warning = true
|
|
67
|
+
|
|
68
|
+
[dependency-groups]
|
|
69
|
+
dev = [
|
|
70
|
+
"ruff>=0.16.9",
|
|
71
|
+
"ty>=0.0.84",
|
|
72
|
+
]
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "mflux-web"
|
|
3
|
+
version = "0.0.1a1"
|
|
4
|
+
description = "Web integration for mflux with a standalone Python API"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "Anthony Wu", email = "462072+anthonywu@users.noreply.github.com" }
|
|
8
|
+
]
|
|
9
|
+
requires-python = ">=3.11"
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Programming Language :: Python :: 3.11",
|
|
12
|
+
"Programming Language :: Python :: 3.12",
|
|
13
|
+
"Programming Language :: Python :: 3.13",
|
|
14
|
+
"Programming Language :: Python :: 3.14",
|
|
15
|
+
"Programming Language :: Python :: 3.15",
|
|
16
|
+
]
|
|
17
|
+
dependencies = []
|
|
18
|
+
|
|
19
|
+
[build-system]
|
|
20
|
+
requires = ["uv_build>=0.12.15,<0.13.0"]
|
|
21
|
+
build-backend = "uv_build"
|
|
22
|
+
|
|
23
|
+
[tool.uv.build-backend]
|
|
24
|
+
module-name = ["mflux_web", "mflux.web"]
|
|
25
|
+
source-include = ["tests/**"]
|
|
26
|
+
|
|
27
|
+
[tool.ruff]
|
|
28
|
+
target-version = "py311"
|
|
29
|
+
line-length = 88
|
|
30
|
+
src = ["src"]
|
|
31
|
+
|
|
32
|
+
[tool.ruff.lint]
|
|
33
|
+
# Core errors, import sorting, upgrades, bug risks, and simple cleanup.
|
|
34
|
+
select = ["E4", "E7", "E9", "F", "I", "UP", "B", "SIM", "RUF"]
|
|
35
|
+
|
|
36
|
+
[tool.ruff.format]
|
|
37
|
+
quote-style = "double"
|
|
38
|
+
indent-style = "space"
|
|
39
|
+
|
|
40
|
+
[tool.ty.environment]
|
|
41
|
+
python-version = "3.11"
|
|
42
|
+
|
|
43
|
+
[tool.ty.src]
|
|
44
|
+
include = ["src", "tests"]
|
|
45
|
+
|
|
46
|
+
[tool.ty.rules]
|
|
47
|
+
unused-ignore-comment = "warn"
|
|
48
|
+
|
|
49
|
+
[tool.ty.terminal]
|
|
50
|
+
error-on-warning = true
|
|
51
|
+
|
|
52
|
+
[dependency-groups]
|
|
53
|
+
dev = [
|
|
54
|
+
"ruff>=0.16.9",
|
|
55
|
+
"ty>=0.0.84",
|
|
56
|
+
]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Alias mflux.web to the standalone mflux_web package."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from pkgutil import extend_path
|
|
5
|
+
|
|
6
|
+
import mflux_web
|
|
7
|
+
|
|
8
|
+
# Keep plugin directories discoverable after replacing this module with the alias.
|
|
9
|
+
for path in extend_path(__path__, __name__):
|
|
10
|
+
if path not in mflux_web.__path__:
|
|
11
|
+
mflux_web.__path__.append(path)
|
|
12
|
+
|
|
13
|
+
sys.modules[__name__] = mflux_web
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"""Exercise built artifacts without relying on the editable source checkout."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
import tempfile
|
|
7
|
+
import unittest
|
|
8
|
+
import zipfile
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PackagingTests(unittest.TestCase):
|
|
15
|
+
@classmethod
|
|
16
|
+
def setUpClass(cls):
|
|
17
|
+
cls.temp = tempfile.TemporaryDirectory()
|
|
18
|
+
cls.addClassCleanup(cls.temp.cleanup)
|
|
19
|
+
cls.root = Path(cls.temp.name)
|
|
20
|
+
dist = cls.root / "dist"
|
|
21
|
+
subprocess.run(
|
|
22
|
+
["uv", "build", "--out-dir", str(dist)],
|
|
23
|
+
cwd=ROOT,
|
|
24
|
+
check=True,
|
|
25
|
+
capture_output=True,
|
|
26
|
+
text=True,
|
|
27
|
+
)
|
|
28
|
+
cls.site = cls.root / "site"
|
|
29
|
+
with zipfile.ZipFile(next(dist.glob("*.whl"))) as wheel:
|
|
30
|
+
cls.members = wheel.namelist()
|
|
31
|
+
wheel.extractall(cls.site)
|
|
32
|
+
|
|
33
|
+
def run_imports(self, code, *paths):
|
|
34
|
+
# -I -S prevents the project's editable install and user site from leaking in.
|
|
35
|
+
setup = f"import sys; sys.path[:0] = {[str(p) for p in paths]!r}\n"
|
|
36
|
+
result = subprocess.run(
|
|
37
|
+
[sys.executable, "-I", "-S", "-c", setup + code],
|
|
38
|
+
check=False,
|
|
39
|
+
cwd=self.root,
|
|
40
|
+
capture_output=True,
|
|
41
|
+
text=True,
|
|
42
|
+
env={k: v for k, v in os.environ.items() if k != "PYTHONPATH"},
|
|
43
|
+
)
|
|
44
|
+
self.assertEqual(result.returncode, 0, result.stderr)
|
|
45
|
+
return result.stdout
|
|
46
|
+
|
|
47
|
+
def test_wheel_ownership(self):
|
|
48
|
+
self.assertIn("mflux/web/__init__.py", self.members)
|
|
49
|
+
self.assertIn("mflux_web/__init__.py", self.members)
|
|
50
|
+
self.assertNotIn("mflux/__init__.py", self.members)
|
|
51
|
+
self.assertFalse(any("mflux_web_pypi" in name for name in self.members))
|
|
52
|
+
|
|
53
|
+
def test_standalone_does_not_import_parent(self):
|
|
54
|
+
self.run_imports(
|
|
55
|
+
'import mflux_web\nassert "mflux" not in sys.modules\n'
|
|
56
|
+
'assert mflux_web.__version__ == "0.0.1a1"',
|
|
57
|
+
self.site,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
def test_both_entry_points(self):
|
|
61
|
+
for imports in (
|
|
62
|
+
"import mflux.web\nimport mflux_web",
|
|
63
|
+
"import mflux_web\nimport mflux.web",
|
|
64
|
+
"from mflux import web\nimport mflux.web\nimport mflux_web",
|
|
65
|
+
):
|
|
66
|
+
with self.subTest(imports=imports):
|
|
67
|
+
output = self.run_imports(
|
|
68
|
+
imports + "\n"
|
|
69
|
+
"assert mflux.web is mflux_web\n"
|
|
70
|
+
'assert sys.modules["mflux.web"] is mflux_web\n'
|
|
71
|
+
"mflux.web.shared_value = 42\n"
|
|
72
|
+
"assert mflux_web.shared_value == 42",
|
|
73
|
+
self.site,
|
|
74
|
+
)
|
|
75
|
+
self.assertEqual(output, "Hello from mflux-web library\n")
|
|
76
|
+
|
|
77
|
+
def test_plugin_on_separate_path(self):
|
|
78
|
+
plugin_root = self.root / "plugin"
|
|
79
|
+
plugin = plugin_root / "mflux/web/anythingelse"
|
|
80
|
+
plugin.mkdir(parents=True)
|
|
81
|
+
(plugin / "__init__.py").write_text("VALUE = 42\n")
|
|
82
|
+
self.run_imports(
|
|
83
|
+
"import mflux.web.anythingelse, mflux_web\n"
|
|
84
|
+
"assert mflux.web is mflux_web\n"
|
|
85
|
+
"assert mflux.web.anythingelse.VALUE == 42\n"
|
|
86
|
+
"assert mflux_web.anythingelse is mflux.web.anythingelse",
|
|
87
|
+
self.site,
|
|
88
|
+
plugin_root,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
def test_regular_parent_in_same_site(self):
|
|
92
|
+
import shutil
|
|
93
|
+
|
|
94
|
+
site = self.root / "coinstalled"
|
|
95
|
+
shutil.copytree(self.site, site)
|
|
96
|
+
(site / "mflux/__init__.py").write_text("PARENT = True\n")
|
|
97
|
+
self.run_imports(
|
|
98
|
+
"import mflux.web\nassert mflux.PARENT",
|
|
99
|
+
site,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
def test_split_parent_with_extend_path(self):
|
|
103
|
+
parent_root = self.root / "parent"
|
|
104
|
+
parent = parent_root / "mflux"
|
|
105
|
+
parent.mkdir(parents=True)
|
|
106
|
+
(parent / "__init__.py").write_text(
|
|
107
|
+
"from pkgutil import extend_path\n"
|
|
108
|
+
"__path__ = extend_path(__path__, __name__)\n"
|
|
109
|
+
"PARENT = True\n"
|
|
110
|
+
)
|
|
111
|
+
self.run_imports(
|
|
112
|
+
"import mflux.web\nassert mflux.PARENT",
|
|
113
|
+
parent_root,
|
|
114
|
+
self.site,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
def test_unmodified_split_parent_hides_web(self):
|
|
118
|
+
parent_root = self.root / "unmodified"
|
|
119
|
+
parent = parent_root / "mflux"
|
|
120
|
+
parent.mkdir(parents=True)
|
|
121
|
+
(parent / "__init__.py").write_text("PARENT = True\n")
|
|
122
|
+
self.run_imports(
|
|
123
|
+
"import importlib.util, mflux_web\n"
|
|
124
|
+
'assert importlib.util.find_spec("mflux.web") is None',
|
|
125
|
+
parent_root,
|
|
126
|
+
self.site,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
if __name__ == "__main__":
|
|
131
|
+
unittest.main()
|