Skip to content

Commit

Permalink
Python 3.12 changes (#44)
Browse files Browse the repository at this point in the history
* use importlib.machinery instead of imp

* python 3.12 changes

* update build matrix

* build on pull_request, not push

* add to_filename helper

* open pyproject.toml as bniary

* redirect "tomllib or tomli" through enscons.toml

* update workflow

* add pypy3.10

* edit CHANGES

* note packaging normalizers

* syntax

* require successful SCons exit code

* add python 3.8+ to workflow
  • Loading branch information
dholth authored Jul 21, 2024
1 parent 4fa7342 commit f1d2aba
Show file tree
Hide file tree
Showing 18 changed files with 127 additions and 71 deletions.
1 change: 0 additions & 1 deletion .github/workflows/sphinx.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
name: Sphinx
on:
- push
- pull_request

jobs:
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/upload-pypi-source.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
name: Build

on: [push, pull_request]
on: [pull_request]

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", pypy3.9]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "pypy3.9", "pypy3.10"]

steps:
- uses: actions/checkout@v3
Expand All @@ -20,7 +20,7 @@ jobs:
run: python -c "import sys; print(sys.version)"
- name: Build
run: |
python -m pip install scons pytoml packaging
python -m pip install scons tomli packaging
scons -c
scons
python -m pip install dist/enscons*.whl
Expand Down
6 changes: 6 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
0.30.0
------
- Support Python 3.12 with removed distutils, imp.
- Use setuptools for enscons.cpyext, only required for enscons projects with extensions.
- Use tomllib (Python 3.11+) or tomli.

0.28.0
------
- Update editables for approved PEP 660
Expand Down
5 changes: 2 additions & 3 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.

import pytoml as toml
import enscons.toml as toml
import enscons
import sys

metadata = toml.load(open("pyproject.toml"))["project"]
metadata = toml.load(open("pyproject.toml", "rb"))["project"]

full_tag = "py2.py3-none-any"

Expand Down
21 changes: 10 additions & 11 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information

project = 'enscons'
copyright = '2023, Daniel Holth & enscons developers'
author = 'Daniel Holth & enscons developers'
release = '0.28.0'
project = "enscons"
copyright = "2023, Daniel Holth & enscons developers"
author = "Daniel Holth & enscons developers"
release = "0.30.0"

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
Expand All @@ -18,17 +18,16 @@
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'myst_parser',
"sphinx.ext.autodoc",
"myst_parser",
]

templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']

templates_path = ["_templates"]
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]


# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

html_theme = 'furo'
html_static_path = ['_static']
html_theme = "furo"
html_static_path = ["_static"]
8 changes: 4 additions & 4 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ builder, a `WhlFile` builder, and an `SDist` builder.
Here's a simple and complete example. The following sections will go over each part in more detail.

```python
import pytoml as toml
import tomllib
import enscons

metadata = toml.load(open("pyproject.toml"))["project"]
metadata = tomllib.load(open("pyproject.toml", "rb"))["project"]
tag = "py3-none-any"

env = Environment(
Expand All @@ -110,7 +110,7 @@ by the SCons runtime.
The SConstruct `Environment` object should be created as shown:

```python
metadata = toml.load(open("pyproject.toml"))["project"]
metadata = tomllib.load(open("pyproject.toml", "rb"))["project"]
tag = "py3-none-any"

env = Environment(
Expand Down Expand Up @@ -234,7 +234,7 @@ These variables are settable using kwargs to the `Environment()` constructor.
.. code-block:: python
metadata = toml.load(open("pyproject.toml"))["project"]
metadata = toml.load(open("pyproject.toml", "rb"))["project"]
This variable is required.
Expand Down
4 changes: 2 additions & 2 deletions enscons/SConstruct.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
# (filled by enscons.setup2toml)

import enscons
import pytoml as toml
import enscons.toml as toml

metadata = dict(toml.load(open("pyproject.toml")))["project"]
metadata = dict(toml.load(open("pyproject.toml", "rb")))["project"]

# set to True if package is not pure Python
HAS_NATIVE_CODE = False
Expand Down
14 changes: 4 additions & 10 deletions enscons/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,9 @@

from SCons.Script import Copy, Action, FindInstalledFiles, GetOption, AddOption

from distutils import sysconfig
from collections import defaultdict

from .util import safe_name, to_filename, generate_requirements

import codecs
import distutils.ccompiler, distutils.sysconfig, distutils.unixccompiler
import os.path
import SCons.Node.FS

Expand All @@ -82,7 +78,7 @@ def get_binary_tag():
"""
from packaging import tags

return str(next(tag for tag in tags.sys_tags() if not "manylinux" in tag.platform))
return str(next(tag for tag in tags.sys_tags() if "manylinux" not in tag.platform))


def get_universal_tag():
Expand Down Expand Up @@ -187,7 +183,6 @@ def egg_info_builder(target, source, env):
"""
Minimum egg_info. To be used only by pip to get dependencies.
"""
metadata = env["PACKAGE_METADATA"]
for dnode in env.arg2nodes(target):
if dnode.name == "PKG-INFO":
with open(dnode.get_path(), "w") as f:
Expand Down Expand Up @@ -249,7 +244,7 @@ def metadata_source(env):
# Maybe the two should be unified.
if "license" in metadata:
if not _is_string(metadata["license"]):
if not ("text" in metadata["license"]):
if "text" not in metadata["license"]:
source.append(metadata["license"]["file"])
if "readme" in metadata:
if _is_string(metadata["readme"]):
Expand Down Expand Up @@ -386,7 +381,6 @@ def add_editable(target, source, env):
archive = zipfile.ZipFile(
target[0].get_path(), "a", compression=zipfile.ZIP_DEFLATED
)
lines = []
for f, data in project.files():
archive.writestr(zipfile.ZipInfo(f, time.gmtime(SOURCE_EPOCH_ZIP)[:6]), data)
archive.close()
Expand Down Expand Up @@ -497,7 +491,7 @@ def init_wheel(env):
# editable may need an extra dependency, so it gets its own dist-info directory.
env.Command(editable_dist_info, env["DIST_INFO_PATH"], Copy("$TARGET", "$SOURCE"))

metadata2 = env.Command(
env.Command(
editable_dist_info.File("METADATA"), metadata_source(env), metadata_builder
)

Expand Down Expand Up @@ -593,7 +587,7 @@ def SDist(env, target=None, source=None):
env.Clean(egg_info, env["EGG_INFO_PATH"])
env.Alias("egg_info", egg_info)

pkg_info = env.Command("PKG-INFO", metadata_source(env), metadata_builder)
env.Command("PKG-INFO", metadata_source(env), metadata_builder)

# also the root directory name inside the archive
target_prefix = "-".join((env["PACKAGE_NAME"], env["PACKAGE_VERSION"]))
Expand Down
5 changes: 3 additions & 2 deletions enscons/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
def _run(alias):
try:
SCons.Script.Main.main()
except SystemExit:
pass
except SystemExit as e:
if e.code != 0:
raise
# extreme non-api:
lookup = SCons.Node.arg2nodes_lookups[0](alias).sources[0]
return os.path.basename(str(lookup))
Expand Down
4 changes: 2 additions & 2 deletions enscons/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
import pprint
import os.path
import click
import pytoml as toml
import tomllib as toml


class Backend(object):
def __init__(self):
self.metadata = dict(toml.load(open("pyproject.toml")))
self.metadata = dict(toml.load(open("pyproject.toml", "rb")))
build_backend = self.metadata["build-system"]["build-backend"]
module, _, obj = build_backend.partition(":")
__import__(module)
Expand Down
27 changes: 13 additions & 14 deletions enscons/cpyext.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@

from __future__ import print_function

import distutils.sysconfig, sysconfig, os, os.path
import sysconfig
import os
import os.path

from distutils.core import Distribution
from distutils.extension import Extension
from distutils.command.build_ext import build_ext
from setuptools import Distribution
from setuptools.extension import Extension
from setuptools.command.build_ext import build_ext

import imp
import importlib
import importlib.machinery


# not used when generate is passed directly to Environment
def exists(env):
Expand All @@ -28,8 +31,6 @@ def extension_filename(modname, abi3=False):
If abi3=True and supported by the interpreter, return e.g.
"a/b/c.abi3.so".
"""
from distutils.sysconfig import get_config_var

# we could probably just split modname by '.' instead of using ext here:
ext = get_build_ext()
fullname = ext.get_ext_fullname(modname)
Expand All @@ -42,10 +43,7 @@ def extension_filename(modname, abi3=False):
suffix = suffixes[0] if suffixes else None
except AttributeError:
pass
if not suffix:
suffix = get_config_var("EXT_SUFFIX")
if not suffix:
suffix = get_config_var("SO") # py2
suffix = sysconfig.get_config_var("EXT_SUFFIX")

if abi3:
suffix = get_abi3_suffix() or suffix
Expand All @@ -55,6 +53,7 @@ def extension_filename(modname, abi3=False):

class no_build_ext(build_ext):
output = [] # for testing

# Are you kidding me? We have to run build_ext() to finish configuring the compiler.
def build_extension(self, ext):
def noop_spawn(*args):
Expand Down Expand Up @@ -88,7 +87,7 @@ def get_build_ext(name="zoot"):
# from setuptools
def get_abi3_suffix():
"""Return the file extension for an abi3-compliant Extension()"""
for suffix, _, _ in (s for s in imp.get_suffixes() if s[2] == imp.C_EXTENSION):
for suffix in importlib.machinery.EXTENSION_SUFFIXES:
if ".abi3" in suffix: # Unix
return suffix
elif suffix == ".pyd": # Windows
Expand All @@ -102,8 +101,8 @@ def generate(env):
# Actually this has side effects adding redundant arguments to ext's compiler.
# Could copy the compiler from ext before run() is called.
if False:
compiler = distutils.ccompiler.new_compiler()
distutils.sysconfig.customize_compiler(compiler)
compiler = setuptools.ccompiler.new_compiler()
setuptools.sysconfig.customize_compiler(compiler)

ext = get_build_ext()

Expand Down
6 changes: 3 additions & 3 deletions enscons/pytar.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ def tar(target, source, env):

def _filter(info):
"""Return potentially anonymize tarinfo"""
if taruid != None:
if taruid is not None:
info.uid = taruid
info.uname = ""
if targid != None:
if targid is not None:
info.gid = targid
info.gname = ""
if tarmtime != None:
if tarmtime is not None:
info.mtime = tarmtime
return info

Expand Down
6 changes: 5 additions & 1 deletion enscons/setup.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
"""
enscons' implementation of setup.py, to be called from a shim setup.py for
compatibility with traditional style packaging & tools.
Now that pyproject.toml is widely supported, this should not be needed.
"""

import sys, pkg_resources, argparse
import sys
import pkg_resources
import argparse


def develop(path):
Expand Down
22 changes: 15 additions & 7 deletions enscons/setup2toml.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@

import runpy
from collections import OrderedDict
import setuptools, distutils.core
import sys, os, codecs, errno
import pytoml
import setuptools
try:
import distutils.core as distutils_core
except ImportError:
distutils_core = None
import sys
import os
import codecs
import errno
import tomli_w

import pkgutil

Expand Down Expand Up @@ -90,7 +97,8 @@ def setup_(**kw):
setup_.arguments = kw

setuptools.setup = setup_
distutils.core.setup = setup_
if distutils_core:
distutils_core.setup = setup_

sys.path[0:0] = "."

Expand Down Expand Up @@ -138,14 +146,14 @@ def setup_(**kw):
if "long_description" in ordered_arguments:
sys.stderr.write("Consider replacing long_description with description_file\n")

pyproject = pytoml.dumps(
OrderedDict(
pyproject = tomli_w.dumps(
dict(
[
["project", ordered_arguments],
[
"build-system",
{
"requires": ["pytoml>=0.1", "enscons"],
"requires": ["enscons"],
"build-backend": "enscons.api",
},
],
Expand Down
8 changes: 8 additions & 0 deletions enscons/toml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""
Import available toml.load
"""
try:
# Python 3.11+
from tomllib import load
except ImportError:
from tomli import load
Loading

0 comments on commit f1d2aba

Please sign in to comment.