python-mscl 67.0.0__tar.gz → 67.1.0.1__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.
@@ -1,4 +1,4 @@
1
- name: Build wheels
1
+ name: Download, extract, build, and test wheels
2
2
 
3
3
  on:
4
4
  pull_request:
@@ -10,19 +10,14 @@ on:
10
10
 
11
11
  jobs:
12
12
  build-wheels:
13
- name: Build wheels
13
+ name: Download, extract, build, and wheels
14
14
  runs-on: ${{ matrix.os }}
15
15
  timeout-minutes: 5
16
16
  strategy:
17
17
  fail-fast: false
18
18
  matrix:
19
- os: [ubuntu-latest, windows-latest]
20
- python-version: [3.9, 3.11, 3.13]
21
- exclude:
22
- - os: windows-latest
23
- python-version: 3.9
24
- - os: windows-latest
25
- python-version: 3.13
19
+ os: [ubuntu-latest, windows-latest, ubuntu-24.04-arm]
20
+ python-version: [3.13]
26
21
 
27
22
  steps:
28
23
  - uses: actions/checkout@v4
@@ -39,15 +34,21 @@ jobs:
39
34
 
40
35
  - name: Install the project
41
36
  run: uv sync
37
+
38
+ - name: Download and extract the mscl assets
39
+ run: |
40
+ uv run download_and_extract_assets.py
42
41
 
43
- - name: Build the wheel
44
- run: uv build --wheel
42
+ - name: Build the wheels
43
+ run: |
44
+ uv run run_build.py
45
45
 
46
- - name: Initialize test environment
46
+ # There should be only one wheel so it should work:
47
+ - name: Initialize test environment and install wheel
47
48
  run: |
48
49
  uv init --no-workspace test
49
50
  cd test
50
- uv add ../dist/*.whl
51
+ uv add "$(python -c 'import glob; print(glob.glob("../dist/*.whl")[0])')"
51
52
 
52
53
  - name: Verify installation
53
54
  run: uv run -- python -c "from python_mscl import mscl"
@@ -15,10 +15,12 @@ wheels/
15
15
  # Exclude local .deb and .zip files from mscl:
16
16
  mscl_release_assets/*.zip
17
17
  mscl_release_assets/*.deb
18
+ mscl_release_assets/
18
19
 
19
20
  # VSCode:
20
21
  .vscode/
21
22
 
22
23
  # Exclude build downloaded mscl files:
23
- src/mscl/mscl.py
24
- src/mscl/_mscl.so
24
+ src/python_mscl/mscl.py
25
+ src/python_mscl/_mscl.so
26
+ src/python_mscl/_mscl.pyd
@@ -0,0 +1 @@
1
+ 3.14+gil
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: python-mscl
3
- Version: 67.0.0
3
+ Version: 67.1.0.1
4
4
  Summary: Easy to install python wrapper for the MSCL library.
5
5
  Author-email: Harshil <37377066+harshil21@users.noreply.github.com>
6
6
  License-File: LICENSE
@@ -8,23 +8,25 @@ Classifier: Development Status :: 4 - Beta
8
8
  Classifier: Intended Audience :: Developers
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.9
12
- Classifier: Programming Language :: Python :: 3.10
13
11
  Classifier: Programming Language :: Python :: 3.11
14
12
  Classifier: Programming Language :: Python :: 3.12
15
13
  Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
16
15
  Classifier: Topic :: Scientific/Engineering
17
- Requires-Python: >=3.9
16
+ Requires-Python: >=3.11
18
17
  Description-Content-Type: text/markdown
19
18
 
20
19
  # python-mscl
21
20
 
21
+ # ARCHIVED: There is now an official mscl library: [`pymscl`](https://pypi.org/project/pymscl). Please use that library instead.
22
+
23
+ [![PyPI Downloads](https://static.pepy.tech/badge/python-mscl/week)](https://pepy.tech/projects/python-mscl)
24
+
22
25
  Unofficial Python package for the [Microstrain Communication Library](https://github.com/LORD-MicroStrain/MSCL/tree/master).
23
26
 
24
- This library just makes it so that we can install the MSCL library using pip. Wheels are not provided. This will fetch the necessary files for your architecture and python
25
- version, and then build the wheel for you.
27
+ This library just makes it so that we can install the MSCL library using pip, and directly provides the wheels!
26
28
 
27
- It is therefore recommended to use a cache for your CI or package manager, unless you're okay with the ~20MB download every time you run your CI.
29
+ Only Python 3.x wheels are provided. If you need Python 2.x wheels, please open an issue.
28
30
 
29
31
  ### Installation
30
32
 
@@ -40,11 +42,6 @@ from python_mscl import mscl
40
42
  # ... use the MSCL library as you normally would
41
43
  ```
42
44
 
43
- ### Windows support:
44
-
45
- The latest mscl version (v67.0.0) only has a .zip for python 3.11. It has been confirmed that it does not work on other python versions (You would get an import error). However the build itself would still go through.
46
-
47
-
48
45
  ### Versioning system:
49
46
 
50
47
  This repository follows the same versioning system as the MSCL library. This is reflected in the tags of this repository.
@@ -63,13 +60,18 @@ The below steps assume you have [`uv`](https://docs.astral.sh/uv/) installed.
63
60
 
64
61
  1. Clone the repo and `cd` into it.
65
62
  2. Optional: Create a .env file and insert your GITHUB_TOKEN= to make requests to the GitHub API.
66
- 3. Edit & run `uv run main.py` to fetch the latest tagged MSCL releases and extract them.
67
- 4. Run `uv build`, which will build the source distribution and wheel for your python
68
- version and architecture.
63
+ 3. Edit & run `uv run download_and_extract_assets.py` to fetch the latest tagged MSCL releases and extract them.
64
+ 4. Run `uv run run_build.py`, which will build the source distribution and wheel for your python
65
+ version and architecture. The wheels will be placed in the `dist/` directory.
69
66
 
70
67
  Notes for me, the maintainer:
71
- 5. Optional: Run `uv publish` to publish the package to PyPI. To upload to TestPyPI, uncomment lines in `pyproject.toml`, and run `uv publish --index testpypi dist/*.tar.gz`.
72
- 6. Optional: To check if the package worked correctly: `uv add --index https://test.pypi.org/simple/ --index-strategy unsafe-best-match python-mscl` in a new uv project directory.
68
+
69
+ 5. Make sure that the constants in `constants.py` are updated, and that the MSCL repo still follows their
70
+ versioning system. If not, update rest of the files accordingly.
71
+
72
+ 6. Optional: Run `uv publish` to publish the package to PyPI. To upload to TestPyPI, uncomment lines in `pyproject.toml`, and run `uv publish --index testpypi dist/*.whl`.
73
+
74
+ 7. Optional: To check if the package worked correctly: `uv add --index https://test.pypi.org/simple/ --index-strategy unsafe-best-match python-mscl` in a new uv project directory.
73
75
 
74
76
 
75
77
  ## Issues:
@@ -1,11 +1,14 @@
1
1
  # python-mscl
2
2
 
3
+ # ARCHIVED: There is now an official mscl library: [`pymscl`](https://pypi.org/project/pymscl). Please use that library instead.
4
+
5
+ [![PyPI Downloads](https://static.pepy.tech/badge/python-mscl/week)](https://pepy.tech/projects/python-mscl)
6
+
3
7
  Unofficial Python package for the [Microstrain Communication Library](https://github.com/LORD-MicroStrain/MSCL/tree/master).
4
8
 
5
- This library just makes it so that we can install the MSCL library using pip. Wheels are not provided. This will fetch the necessary files for your architecture and python
6
- version, and then build the wheel for you.
9
+ This library just makes it so that we can install the MSCL library using pip, and directly provides the wheels!
7
10
 
8
- It is therefore recommended to use a cache for your CI or package manager, unless you're okay with the ~20MB download every time you run your CI.
11
+ Only Python 3.x wheels are provided. If you need Python 2.x wheels, please open an issue.
9
12
 
10
13
  ### Installation
11
14
 
@@ -21,11 +24,6 @@ from python_mscl import mscl
21
24
  # ... use the MSCL library as you normally would
22
25
  ```
23
26
 
24
- ### Windows support:
25
-
26
- The latest mscl version (v67.0.0) only has a .zip for python 3.11. It has been confirmed that it does not work on other python versions (You would get an import error). However the build itself would still go through.
27
-
28
-
29
27
  ### Versioning system:
30
28
 
31
29
  This repository follows the same versioning system as the MSCL library. This is reflected in the tags of this repository.
@@ -44,13 +42,18 @@ The below steps assume you have [`uv`](https://docs.astral.sh/uv/) installed.
44
42
 
45
43
  1. Clone the repo and `cd` into it.
46
44
  2. Optional: Create a .env file and insert your GITHUB_TOKEN= to make requests to the GitHub API.
47
- 3. Edit & run `uv run main.py` to fetch the latest tagged MSCL releases and extract them.
48
- 4. Run `uv build`, which will build the source distribution and wheel for your python
49
- version and architecture.
45
+ 3. Edit & run `uv run download_and_extract_assets.py` to fetch the latest tagged MSCL releases and extract them.
46
+ 4. Run `uv run run_build.py`, which will build the source distribution and wheel for your python
47
+ version and architecture. The wheels will be placed in the `dist/` directory.
50
48
 
51
49
  Notes for me, the maintainer:
52
- 5. Optional: Run `uv publish` to publish the package to PyPI. To upload to TestPyPI, uncomment lines in `pyproject.toml`, and run `uv publish --index testpypi dist/*.tar.gz`.
53
- 6. Optional: To check if the package worked correctly: `uv add --index https://test.pypi.org/simple/ --index-strategy unsafe-best-match python-mscl` in a new uv project directory.
50
+
51
+ 5. Make sure that the constants in `constants.py` are updated, and that the MSCL repo still follows their
52
+ versioning system. If not, update rest of the files accordingly.
53
+
54
+ 6. Optional: Run `uv publish` to publish the package to PyPI. To upload to TestPyPI, uncomment lines in `pyproject.toml`, and run `uv publish --index testpypi dist/*.whl`.
55
+
56
+ 7. Optional: To check if the package worked correctly: `uv add --index https://test.pypi.org/simple/ --index-strategy unsafe-best-match python-mscl` in a new uv project directory.
54
57
 
55
58
 
56
59
  ## Issues:
@@ -8,6 +8,8 @@ from github import Github
8
8
  from github.GitRelease import GitRelease
9
9
  from github.GitReleaseAsset import GitReleaseAsset
10
10
 
11
+ from constants import ASSET_DIRECTORY, ReleaseAsset
12
+
11
13
 
12
14
  class GithubDownloader:
13
15
  """Manages downloading the Github release assets for the mscl library, along with the
@@ -18,6 +20,7 @@ class GithubDownloader:
18
20
  self.mscl_repo = "LORD-MicroStrain/MSCL"
19
21
  self.python_mscl_repo = "harshil21/python-mscl"
20
22
  self.latest_release = None
23
+ self.asset_dir = Path(ASSET_DIRECTORY)
21
24
 
22
25
  def get_latest_release(self) -> GitRelease:
23
26
  """Returns the latest stable release for the given repo."""
@@ -33,13 +36,19 @@ class GithubDownloader:
33
36
  break
34
37
  return self.latest_release
35
38
 
36
- def download_release_assets(self, output_dir: str):
37
- """Downloads the release assets for the given repo and tag."""
39
+ def download_release_assets(self, only_release: ReleaseAsset | None = None) -> None:
40
+ """Downloads the release assets from the MSCL repository.
41
+
42
+ Args:
43
+ only_release: If set, only download the release asset for the given Python version and
44
+ architecture. If not set, download all the release assets.
45
+ """
38
46
  release = self.get_latest_release()
39
- output_path = Path(output_dir)
47
+ output_path = Path(self.asset_dir)
40
48
  output_path.mkdir(parents=True, exist_ok=True)
41
49
 
42
50
  asset: GitReleaseAsset
51
+ print(f"Downloading release assets for {only_release=}")
43
52
  for asset in release.get_assets():
44
53
  # Don't download the "Documentation" or "Examples"
45
54
  if "Documentation" in asset.name or "Examples" in asset.name:
@@ -51,22 +60,17 @@ class GithubDownloader:
51
60
  if "3" not in asset.name:
52
61
  continue
53
62
 
63
+ # Extract the python version, arch, and platform from the only_release, if set:
64
+ if only_release:
65
+ if only_release.python_version not in asset.name:
66
+ continue
67
+ if only_release.arch not in asset.name:
68
+ continue
69
+
54
70
  self.download_asset(output_path, asset)
71
+ print(f"Downloaded {asset.name}")
55
72
 
56
73
  def download_asset(self, output_path: Path, asset: GitReleaseAsset) -> None:
57
74
  response = requests.get(asset.browser_download_url, timeout=15)
58
75
  asset_path = output_path / asset.name
59
76
  asset_path.write_bytes(response.content)
60
-
61
- def download_assets_from_folder(self, tag: str, folder_name: str) -> None:
62
- """Downloads all the files under the `folder_name` for the given tag, from the
63
- root of the repository."""
64
-
65
- repo = self.github.get_repo(self.python_mscl_repo)
66
- contents = repo.get_contents(folder_name, ref=tag)
67
-
68
- for content in contents:
69
- if content.type == "file":
70
- response = requests.get(content.download_url, timeout=15)
71
- file_path = Path(content.name)
72
- file_path.write_bytes(response.content)
@@ -1,17 +1,19 @@
1
1
  """Extracts the .deb and .zip releases for the mscl library."""
2
2
 
3
3
  import os
4
+ import shutil
4
5
  import subprocess
5
6
  from pathlib import Path
7
+ from zipfile import ZipFile
8
+
9
+ from constants import ASSET_DIRECTORY, MSCL_VERSION
6
10
 
7
- MSCL_VERSION = "v67.0.0"
8
- """The mscl version to extract."""
9
11
 
10
12
  class ReleaseExtractor:
11
13
  """Will extract the .deb and .zip releases for the mscl library."""
12
14
 
13
15
  def __init__(self):
14
- self.asset_dir = Path("mscl_release_assets")
16
+ self.asset_dir = Path(ASSET_DIRECTORY)
15
17
 
16
18
  def extract_assets(self):
17
19
  """Extracts the .deb and .zip releases into the same directory."""
@@ -77,18 +79,19 @@ class ReleaseExtractor:
77
79
  # Create a directory to extract the .zip file. Syntax: mscl-<arch>-<python-ver>-<mscl-ver>
78
80
  parts = file.stem.split("_")
79
81
  arch, py_ver = parts[2], parts[3]
80
- mscl_versioned_name = f"mscl-Windows-{arch}-{py_ver}-{MSCL_VERSION}"
82
+ mscl_versioned_name = f"mscl-Windows_{arch}-{py_ver}-{MSCL_VERSION}"
81
83
  mscl_versioned_dir = cwd / self.asset_dir / mscl_versioned_name
82
84
 
83
85
  # If output directory exists, remove it:
84
86
  if mscl_versioned_dir.exists():
85
- os.system(f"rm -rf {mscl_versioned_dir}")
87
+ shutil.rmtree(mscl_versioned_dir)
86
88
 
87
89
  mscl_versioned_dir.mkdir(parents=True, exist_ok=True)
88
- file_relative = file.absolute().relative_to(mscl_versioned_dir, walk_up=True)
89
90
 
90
91
  # Extract the .zip file
91
- subprocess.run(["unzip", str(file_relative)], cwd=mscl_versioned_dir, check=True) # noqa: S603, S607
92
+ with ZipFile(file, "r") as zip_ref:
93
+ zip_ref.extractall(mscl_versioned_dir)
94
+ print("Extracted the zip file.")
92
95
 
93
96
  found_mscl_py = list(mscl_versioned_dir.rglob("mscl.py"))
94
97
  found_mscl_pyd = list(mscl_versioned_dir.rglob("_mscl.pyd"))
@@ -106,8 +109,18 @@ class ReleaseExtractor:
106
109
  # Delete the remaining files in mscl_versioned_dir:
107
110
  for f in mscl_versioned_dir.iterdir():
108
111
  if f.stem in (mscl_py.stem, mscl_pyd.stem):
112
+ print(f"Skipping deletion of {f}")
109
113
  continue
110
114
  if f.is_dir():
111
- os.system(f"rm -rf {f}")
115
+ print(f"Deleting the directory {f}")
116
+ shutil.rmtree(f)
112
117
  else:
118
+ print(f"Deleting {f}")
113
119
  f.unlink()
120
+
121
+ # Confirm that the files still exist after deleting the rest:
122
+ found_mscl_py = list(mscl_versioned_dir.rglob("mscl.py"))
123
+ found_mscl_pyd = list(mscl_versioned_dir.rglob("_mscl.pyd"))
124
+
125
+ if not found_mscl_py or not found_mscl_pyd:
126
+ raise FileNotFoundError(f"Deleted mscl.py or _mscl.pyd in {mscl_versioned_dir}!")
@@ -0,0 +1,38 @@
1
+ """File to store common constants used in the project."""
2
+
3
+ from pathlib import Path
4
+ from typing import NamedTuple
5
+
6
+
7
+ # Named tuple to store the release asset information:
8
+ class ReleaseAsset(NamedTuple):
9
+ """Named tuple to store the release asset information.
10
+
11
+ Args:
12
+ python_version: The Python version of the release asset. E.g. "Python3.9".
13
+ arch: The architecture of the release asset. E.g. "amd64".
14
+ """
15
+
16
+ python_version: str
17
+ arch: str
18
+
19
+
20
+ ASSET_DIRECTORY = Path("mscl_release_assets")
21
+ """The directory to store the downloaded release assets."""
22
+
23
+
24
+ # Keep this the same as the one in `hatch_build.py`!
25
+ MSCL_VERSION = "v67.1.0"
26
+ """The mscl version to extract from the `ASSET_DIRECTORY`. The
27
+ downloader will download the latest version despite this version number."""
28
+
29
+
30
+ MACHINE_MAPPING_TO_ARCH = {
31
+ # Linux:
32
+ "x86_64": "amd64",
33
+ "aarch64": "arm64",
34
+ "armv7l": "armhf",
35
+ # Windows:
36
+ "AMD64": "Windows_x64",
37
+ "x86": "Windows_x86",
38
+ }
@@ -0,0 +1,41 @@
1
+ """Entry point for downloading and extracting mscl release assets."""
2
+
3
+ import os
4
+ import platform
5
+ import sys
6
+
7
+ from build_helpers.release_downloader import GithubDownloader, ReleaseAsset
8
+ from build_helpers.release_extractor import ReleaseExtractor
9
+ from constants import MACHINE_MAPPING_TO_ARCH
10
+
11
+
12
+ def main(github_actions: bool = False) -> None:
13
+ """Entry point to fetch the latest release assets from the Github repository & extract them.
14
+
15
+ :param github_actions: If the script is running in a Github Actions environment. If true,
16
+ the script will download and extract the release asset of only the python version and
17
+ architecture and OS type detected.
18
+ """
19
+ gh = GithubDownloader()
20
+ if github_actions:
21
+ print(f"Downloading on {sys.version_info=}, {platform.machine()=}")
22
+ gh.download_release_assets(
23
+ ReleaseAsset(
24
+ python_version=f"Python{sys.version_info.major}.{sys.version_info.minor}",
25
+ arch=MACHINE_MAPPING_TO_ARCH.get(platform.machine()),
26
+ )
27
+ )
28
+ else:
29
+ gh.download_release_assets()
30
+
31
+ re = ReleaseExtractor()
32
+ re.extract_assets()
33
+
34
+
35
+ if __name__ == "__main__":
36
+ if os.getenv("GITHUB_ACTIONS", "false") == "true":
37
+ print("Running in Github Actions environment.")
38
+ main(github_actions=True)
39
+ else:
40
+ print("Running locally")
41
+ main()
@@ -0,0 +1,112 @@
1
+ """Specifies a hatch build hook to create the wheel for mscl."""
2
+
3
+ import os
4
+ import shutil
5
+ from pathlib import Path
6
+ from typing import ClassVar
7
+
8
+ from hatchling.builders.hooks.plugin.interface import BuildHookInterface
9
+
10
+ # This is specified here instead of in the constants since we get import errors:
11
+ MSCL_VERSION = "v67.1.0"
12
+ """The mscl version to build the wheels from."""
13
+
14
+ BUILD_ARCH = os.getenv("BUILD_ARCH", "false")
15
+ """The build architecture to use for the wheels. This determines the tag for the wheel.
16
+
17
+ This will be the arch in folder name (e.g., amd64, arm64, armhf, Windows-x64, Windows-x86).
18
+ """
19
+
20
+ PYTHON_BUILD_VERSION = os.getenv("PYTHON_BUILD_VERSION", "false")
21
+ """The Python build version to use for the wheels. This determines the tag for the wheel.
22
+
23
+ This will be the python version in folder name (e.g., Python3.9, Python3.11, etc).
24
+ """
25
+
26
+
27
+ class CustomBuildHook(BuildHookInterface):
28
+ """Build hook to build wheels from the extracted .deb/.zip files."""
29
+
30
+ PYTHON_VER_MAPPING: ClassVar[dict[str, str]] = {
31
+ "Python3.9": "cp39",
32
+ "Python3.10": "cp310",
33
+ "Python3.11": "cp311",
34
+ "Python3.12": "cp312",
35
+ "Python3.13": "cp313",
36
+ }
37
+ """The mapping of Python versions of the folder to the Python tags for the wheel."""
38
+
39
+ PYTHON_BUILD_MAPPING: ClassVar[dict[str, str]] = {
40
+ "amd64": "manylinux2014_x86_64",
41
+ "arm64": "manylinux2014_aarch64",
42
+ "armhf": "manylinux2014_armv7l",
43
+ "Windows_x64": "win_amd64",
44
+ "Windows_x86": "win32",
45
+ }
46
+ """The mapping of architectures (in the folder name) to the platform tags for the wheel."""
47
+
48
+ def _python_tag(self) -> str | None:
49
+ """Generate the Python tag (e.g., py39 for Python 3.9)."""
50
+ try:
51
+ return self.PYTHON_VER_MAPPING.get(PYTHON_BUILD_VERSION)
52
+ except KeyError as e:
53
+ raise RuntimeError(f"Unknown Python version: {PYTHON_BUILD_VERSION}") from e
54
+
55
+ def _platform_tag(self) -> str | None:
56
+ """Generate the platform tag (e.g., linux_x86_64)."""
57
+ try:
58
+ return self.PYTHON_BUILD_MAPPING.get(BUILD_ARCH)
59
+ except KeyError as e:
60
+ raise RuntimeError(f"Unknown platform: {BUILD_ARCH}") from e
61
+
62
+ def _make_tag(self) -> str:
63
+ """Generate the tag for the wheel (e.g., py39-linux_x86_64)."""
64
+ return f"{self._python_tag()}-{self._python_tag()}-{self._platform_tag()}"
65
+
66
+ def initialize(self, version, build_data):
67
+ """
68
+ Called before building the wheel/sdist.
69
+ We can download & extract the .deb here, and place
70
+ mscl.py and _mscl.so into src/mscl_pip/.
71
+ """
72
+ # Don't run build hook when a user is installing the wheel:
73
+ if PYTHON_BUILD_VERSION == "false" and BUILD_ARCH == "false":
74
+ return
75
+
76
+ build_data["pure_python"] = False
77
+ self.app.display_info(
78
+ f"Running on {version=} on {build_data=}, with "
79
+ f"{PYTHON_BUILD_VERSION=} and {BUILD_ARCH=}"
80
+ )
81
+
82
+ # --- STEP 1: Determine which python version and arch we are on: ---
83
+ # Build the folder name based on the python version and arch in the environment variables.
84
+
85
+ folder_name = f"mscl-{BUILD_ARCH}-{PYTHON_BUILD_VERSION}-{MSCL_VERSION}"
86
+
87
+ build_data["tag"] = self._make_tag()
88
+
89
+ # --- STEP 3: Copy the files ("_mscl.so" & "mscl.py") to the src/mscl/ directory: ---
90
+ # Move from root (i.e. cwd) to src/mscl
91
+
92
+ self.remove_existing_files(Path("src/python_mscl/"), ["_mscl.so", "_mscl.pyd", "mscl.py"])
93
+
94
+ # Copy files from mscl_release_assets/folder_name to src/mscl/:
95
+ p = (Path("mscl_release_assets") / folder_name).absolute()
96
+
97
+ shutil.copy(p / "mscl.py", "src/python_mscl/")
98
+ if BUILD_ARCH.startswith("Windows"): # Windows uses _mscl.pyd
99
+ shutil.copy(p / "_mscl.pyd", "src/python_mscl/")
100
+ build_data["artifacts"] = ["_mscl.pyd", "mscl.py"]
101
+ else:
102
+ shutil.copy(p / "_mscl.so", "src/python_mscl/")
103
+ build_data["artifacts"] = ["_mscl.so", "mscl.py"]
104
+
105
+ self.app.display_success("Moved files to src/python_mscl/ successfully. Building wheel...")
106
+
107
+ def remove_existing_files(self, directory: Path, files: list[str]) -> None:
108
+ """Remove the existing files from the directory."""
109
+ for file in files:
110
+ file_path = directory / file
111
+ if file_path.exists():
112
+ file_path.unlink()
@@ -1,42 +1,45 @@
1
1
  [project]
2
2
  name = "python-mscl"
3
- version = "67.0.0"
3
+ version = "67.1.0.1"
4
4
  description = "Easy to install python wrapper for the MSCL library."
5
5
  readme = "README.md"
6
6
  authors = [
7
7
  { name = "Harshil", email = "37377066+harshil21@users.noreply.github.com" }
8
8
  ]
9
- requires-python = ">=3.9"
9
+ requires-python = ">=3.11"
10
10
  classifiers = [
11
11
  "Development Status :: 4 - Beta",
12
12
  "Intended Audience :: Developers",
13
13
  "License :: OSI Approved :: MIT License",
14
14
  "Programming Language :: Python :: 3",
15
- "Programming Language :: Python :: 3.9",
16
- "Programming Language :: Python :: 3.10",
17
15
  "Programming Language :: Python :: 3.11",
18
16
  "Programming Language :: Python :: 3.12",
19
17
  "Programming Language :: Python :: 3.13",
18
+ "Programming Language :: Python :: 3.14",
20
19
  "Topic :: Scientific/Engineering",
21
20
  "Intended Audience :: Developers",
22
21
  ]
23
22
  dependencies = []
24
23
 
25
24
  [dependency-groups]
26
- dev = ["ruff", "hatchling"]
25
+ dev = [
26
+ "ruff",
27
+ "hatchling",
28
+ "pygithub>=2.5.0",
29
+ ]
27
30
 
28
- [tool.hatch.build.targets.wheel]
29
- packages = ["src/python_mscl"]
31
+ # [tool.hatch.build.targets.wheel]
32
+ # packages = ["src/python_mscl"]
30
33
 
31
- [tool.hatch.build.hooks.custom]
32
- path = "hatch_build.py"
34
+ # [tool.hatch.build.hooks.custom]
35
+ # path = "hatch_build.py"
33
36
 
34
37
  [tool.hatch.build.targets.sdist]
35
38
  exclude = ["mscl_release_assets/", "uv.lock", "main.py", "src/python_mscl/_mscl.so",
36
- "src/python_mscl/mscl.py"]
39
+ "src/python_mscl/mscl.py", "src/python_mscl/mscl.pyd"]
37
40
 
38
41
  [build-system]
39
- requires = ["hatchling", "requests", "pygithub"]
42
+ requires = ["hatchling"]
40
43
  build-backend = "hatchling.build"
41
44
 
42
45
  # [[tool.uv.index]]
@@ -48,13 +51,13 @@ build-backend = "hatchling.build"
48
51
  # RUFF:
49
52
  [tool.ruff]
50
53
  line-length = 100
51
- target-version = "py39"
54
+ target-version = "py311"
52
55
  show-fixes = true
53
56
  exclude = ["mscl_release_assets/"]
54
57
 
55
58
  [tool.ruff.lint]
56
- ignore = ["ISC001", "S603", "S605", "S607", "PLR0912"]
59
+ ignore = ["ISC001", "S603", "S605", "S607", "PLR0912", "T201"]
57
60
  select = ["E", "F", "I", "PL", "UP", "RUF", "PTH", "C4", "B", "PIE", "SIM", "RET", "RSE",
58
61
  "G", "ISC", "PT", "ASYNC", "TCH", "SLOT", "PERF", "PYI", "FLY", "AIR", "Q", "INP",
59
62
  "W", "YTT", "DTZ", "ARG", "T20", "FURB", "D100", "D101", "D300", "D418",
60
- "D419", "S", "NPY"]
63
+ "D419", "S", "NPY"]
@@ -0,0 +1,57 @@
1
+ """Script to run the hatch build for a given python version and architecture."""
2
+
3
+ import itertools
4
+ import os
5
+ import platform
6
+ import subprocess
7
+ import sys
8
+
9
+ from constants import MACHINE_MAPPING_TO_ARCH
10
+
11
+
12
+ def run_hatch_build(python_version: str, build_arch: str) -> None:
13
+ """Run the hatch build for the given Python version and architecture."""
14
+
15
+ # modify_pyproject_toml(python_version, build_arch)
16
+ env = os.environ.copy()
17
+ env["PYTHON_BUILD_VERSION"] = python_version
18
+ env["BUILD_ARCH"] = build_arch
19
+
20
+ # Run the hatch build with the environment variables set:
21
+ subprocess.run(["uv", "build", "--wheel"], check=True, env=env)
22
+
23
+
24
+ def main(github_actions: bool = False) -> None:
25
+ """Entry point to run the hatch build for the given Python version and architecture.
26
+
27
+ Make sure to have first downloaded and extracted the release assets from the Github repository.
28
+ i.e. run `uv run download_and_extract_assets.py` before running this script.
29
+
30
+ Args:
31
+ github_actions: If the script is running in a Github Actions environment. If true, the
32
+ script will run the hatch build for only the Python version and architecture detected.
33
+ """
34
+
35
+ # Iterate through the Python versions and architectures:
36
+ # See the file names in the extracted folder for the exact names:
37
+ # This must be the same as the dictionary in the hatch_build.py file
38
+ python_versions = ["Python3.9", "Python3.10", "Python3.11", "Python3.12", "Python3.13"]
39
+ build_architectures = ["amd64", "arm64", "armhf", "Windows_x64", "Windows_x86"]
40
+
41
+ if github_actions:
42
+ detected_python_version = f"Python{sys.version_info.major}.{sys.version_info.minor}"
43
+ detected_arch = MACHINE_MAPPING_TO_ARCH.get(platform.machine())
44
+ run_hatch_build(detected_python_version, detected_arch)
45
+
46
+ else:
47
+ for python_version, build_arch in itertools.product(python_versions, build_architectures):
48
+ run_hatch_build(python_version, build_arch)
49
+
50
+
51
+ if __name__ == "__main__":
52
+ if os.getenv("GITHUB_ACTIONS", "false") == "true":
53
+ print("Building in Github Actions environment.")
54
+ main(github_actions=True)
55
+ else:
56
+ print("Building locally")
57
+ main()
@@ -0,0 +1,13 @@
1
+ from warnings import warn
2
+
3
+ # from . import mscl
4
+
5
+ warn(
6
+ "The 'python_mscl' package is archived, please use the official `pymscl` package instead.",
7
+ DeprecationWarning,
8
+ stacklevel=2
9
+ )
10
+
11
+ # Intentionally make the user can do `from python_mscl import mscl` instead of `import mscl` which
12
+ # can be done by doing a from .mscl import * here.
13
+ # __all__ = ["mscl"]
@@ -1 +0,0 @@
1
- 3.13
@@ -1,116 +0,0 @@
1
- """Specifies a hatch build hook to create the wheel for mscl."""
2
-
3
- import platform
4
- import shutil
5
- import sys
6
- from pathlib import Path
7
-
8
- sys.path.insert(0, str(Path(__file__).parent))
9
-
10
- from hatchling.builders.hooks.plugin.interface import BuildHookInterface
11
-
12
- from build_helpers.release_downloader import GithubDownloader
13
-
14
- MSCL_VERSION = "v67.0.0"
15
- """The mscl version to build the wheels of."""
16
-
17
-
18
- class CustomBuildHook(BuildHookInterface):
19
- """Build hook to build wheels from the extracted .deb/.zip files."""
20
-
21
- def _python_tag(self) -> str:
22
- """Generate the Python tag (e.g., py39 for Python 3.9)."""
23
- major = sys.version_info.major
24
- minor = sys.version_info.minor
25
- return f"cp{major}{minor}"
26
-
27
- def _platform_tag(self) -> str:
28
- """Generate the platform tag (e.g., linux_x86_64)."""
29
- return platform.system().lower() + "_" + platform.machine()
30
-
31
- def initialize(self, version, build_data):
32
- """
33
- Called before building the wheel/sdist.
34
- We can download & extract the .deb here, and place
35
- mscl.py and _mscl.so into src/mscl_pip/.
36
- """
37
- if self.target_name != "wheel":
38
- return
39
-
40
- build_data["pure_python"] = False
41
- self.app.display_info(f"Running on {version=} and {build_data=}")
42
- self.app.display_info(self.target_name)
43
-
44
- # --- STEP 1: Determine which python version and arch we are on: ---
45
- # a) Python version:
46
- # syntax: Python<MAJOR>.<MINOR>
47
-
48
- py_version = f"Python{sys.version_info.major}.{sys.version_info.minor}"
49
-
50
- # b) Architecture:
51
- # possible values: amd64, arm64, armhf.
52
-
53
- arch = platform.machine()
54
- if arch == "x86_64":
55
- mscl_arch = "amd64"
56
- elif arch == "aarch64":
57
- mscl_arch = "arm64"
58
- elif arch == "armv7l":
59
- mscl_arch = "armhf"
60
- elif arch == "AMD64": # Windows
61
- mscl_arch = "x64"
62
- elif arch == "x86": # Windows
63
- mscl_arch = "x86"
64
- else:
65
- raise RuntimeError(f"Unknown architecture: {arch}")
66
-
67
- # --- STEP 2: Download the 2 mscl files (mscl.py and _mscl.so) from the git repo: ---
68
- # Folder name: mscl-<mscl_arch>-<python-ver>-<mscl-ver> -> Linux
69
- # Folder name: mscl-Windows-<mscl_arch>-<python-ver>-<mscl-ver> -> Windows
70
-
71
- # a) Create the folder name:
72
-
73
- if platform.system() == "Linux":
74
- build_data["tag"] = f"{self._python_tag()}-{self._python_tag()}-{self._platform_tag()}"
75
- folder_name = f"mscl-{mscl_arch}-{py_version}-{MSCL_VERSION}"
76
-
77
- # Windows is best effort matching since there's only python 3.11 available for v67.0.0:
78
- else:
79
- if mscl_arch == "x64":
80
- build_data["tag"] = "py3-none-win_amd64"
81
- elif mscl_arch == "x86":
82
- build_data["tag"] = "py3-none-win32"
83
- folder_name = f"mscl-Windows-{mscl_arch}-Python3.11-{MSCL_VERSION}"
84
-
85
- # b) Use PyGithub to download the files from the folder:
86
- self.app.display_waiting(f"Downloading files for {folder_name}...")
87
-
88
- gh = GithubDownloader()
89
- gh.download_assets_from_folder(
90
- tag=MSCL_VERSION,
91
- folder_name=f"mscl_release_assets/{folder_name}",
92
- )
93
-
94
- self.app.display_success("Downloaded files successfully.")
95
-
96
- # --- STEP 3: Copy the files ("_mscl.so" & "mscl.py") to the src/mscl/ directory: ---
97
- # Move from root (i.e. cwd) to src/mscl
98
- # Use shutil.move() to move the files.
99
-
100
- self.remove_existing_files(Path("src/python_mscl/"), ["_mscl.so", "_mscl.pyd", "mscl.py"])
101
- shutil.move("mscl.py", "src/python_mscl/")
102
- if platform.system() == "Windows":
103
- shutil.move("_mscl.pyd", "src/python_mscl/")
104
- build_data["artifacts"] = ["_mscl.pyd", "mscl.py"]
105
- else:
106
- shutil.move("_mscl.so", "src/python_mscl/")
107
- build_data["artifacts"] = ["_mscl.so", "mscl.py"]
108
-
109
- self.app.display_success("Moved files to src/python_mscl/ successfully. Building wheel...")
110
-
111
- def remove_existing_files(self, directory: Path, files: list[str]) -> None:
112
- """Remove the existing files from the directory."""
113
- for file in files:
114
- file_path = directory / file
115
- if file_path.exists():
116
- file_path.unlink()
@@ -1,5 +0,0 @@
1
- from . import mscl
2
-
3
- # Intentionally make the user can do `from python_mscl import mscl` instead of `import mscl` which
4
- # can be done by doing a from .mscl import * here.
5
- __all__ = ["mscl"]
File without changes