-
Notifications
You must be signed in to change notification settings - Fork 112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement type stubs for ecodes #216
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
#! /usr/bin/env python3 | ||
""" | ||
Generate a Python extension module with the constants defined in linux/input.h. | ||
""" | ||
|
||
from __future__ import print_function | ||
import os, sys, re | ||
|
||
|
||
# ----------------------------------------------------------------------------- | ||
# The default header file locations to try. | ||
headers = [ | ||
"/usr/include/linux/input.h", | ||
"/usr/include/linux/input-event-codes.h", | ||
"/usr/include/linux/uinput.h", | ||
] | ||
|
||
if sys.argv[1:]: | ||
headers = sys.argv[1:] | ||
|
||
uname = list(os.uname()) | ||
del uname[1] | ||
uname = " ".join(uname) | ||
print(f"# used_linux_headers: {headers}") | ||
|
||
|
||
# ----------------------------------------------------------------------------- | ||
macro_regex = r"#define +((?:KEY|ABS|REL|SW|MSC|LED|BTN|REP|SND|ID|EV|BUS|SYN|FF|UI_FF|INPUT_PROP)_\w+)" | ||
macro_regex = re.compile(macro_regex) | ||
|
||
# ----------------------------------------------------------------------------- | ||
template = rf""" | ||
# Automatically generated by evdev.genecodes | ||
# Generated on {uname} | ||
# Headers: {headers} | ||
|
||
""" | ||
|
||
def parse_header(header): | ||
lines = "" | ||
for line in open(header): | ||
macro = macro_regex.search(line) | ||
if macro: | ||
#lines += f" {macro.group(1)}: int{os.linesep}" | ||
lines += f"{macro.group(1)}: int{os.linesep}" | ||
|
||
return lines | ||
|
||
|
||
for header in headers: | ||
try: | ||
fh = open(header) | ||
except (IOError, OSError): | ||
print(f"Unable to read header file: {header}") | ||
continue | ||
template += f"{parse_header(header)}" | ||
|
||
print(template) | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,10 +5,11 @@ | |
|
||
from setuptools import setup, Extension, Command | ||
from setuptools.command import build_ext as _build_ext | ||
|
||
from setuptools.command import install as _install | ||
|
||
curdir = Path(__file__).resolve().parent | ||
ecodes_path = curdir / "evdev/ecodes.c" | ||
ecodes_c_path = curdir / "evdev/ecodes.c" | ||
ecodes_pyi_path = curdir / "evdev/ecodes.pyi" | ||
|
||
|
||
def create_ecodes(headers=None): | ||
|
@@ -54,11 +55,16 @@ def create_ecodes(headers=None): | |
|
||
from subprocess import run | ||
|
||
print("writing %s (using %s)" % (ecodes_path, " ".join(headers))) | ||
with ecodes_path.open("w") as fh: | ||
print("writing %s (using %s)" % (ecodes_c_path, " ".join(headers))) | ||
with ecodes_c_path.open("w") as fh: | ||
cmd = [sys.executable, "evdev/genecodes.py", *headers] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder why this was done using the For example in the case of the pyi stub, what would be a reason to not call Anyhow, I'm fine with doing it as a subprocess since it has already been working like that in the past. |
||
run(cmd, check=True, stdout=fh) | ||
|
||
print("writing %s (using %s)" % (ecodes_pyi_path, " ".join(headers))) | ||
with ecodes_pyi_path.open("w") as fh: | ||
cmd = [sys.executable, "evdev/genpyi.py", *headers] | ||
run(cmd, check=True, stdout=fh) | ||
|
||
|
||
class build_ecodes(Command): | ||
description = "generate ecodes.c" | ||
|
@@ -80,20 +86,36 @@ def run(self): | |
|
||
class build_ext(_build_ext.build_ext): | ||
def has_ecodes(self): | ||
if ecodes_path.exists(): | ||
if ecodes_c_path.exists(): | ||
print("ecodes.c already exists ... skipping build_ecodes") | ||
return not ecodes_path.exists() | ||
return not ecodes_c_path.exists() | ||
|
||
def run(self): | ||
for cmd_name in self.get_sub_commands(): | ||
self.run_command(cmd_name) | ||
_build_ext.build_ext.run(self) | ||
|
||
sub_commands = [("build_ecodes", has_ecodes)] + _build_ext.build_ext.sub_commands | ||
sub_commands = [("build_ecodes", has_ecodes)] + _build_ext.build_ext.sub_commands # type: ignore | ||
use_stubs = True | ||
|
||
# I've been reading through setuptools docs, but i can't for the lofe of me figure out how to bring the pyi stubs into the package "cleanly" | ||
class install(_install.install): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The generation of ecodes.c doesn't seem to require such a step, why does ecodes.pyi? |
||
def run(self): | ||
print(os.listdir(os.getenv("src"))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. where does the "src" environment variable come from? Is it something from when you were developing the change for debugging or something? |
||
#_install.install.copy_file(self, "evdev/ecodes.pyi", "evdev/ecodes.pyi") | ||
installdir = "build/lib.linux-x86_64-cpython-311/evdev" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
Path(f"{installdir}/ecodes.pyi").write_bytes(Path("evdev/ecodes.pyi").read_bytes()) | ||
print("CUSTOM INSTALLER") | ||
print(self.build_lib) | ||
_install.install.run(self) | ||
|
||
|
||
cflags = ["-std=c99", "-Wno-error=declaration-after-statement"] | ||
setup( | ||
#include_package_data=True, | ||
packages=["evdev"], | ||
package_dir={'evdev': 'evdev'}, | ||
package_data={'evdev': ["*.pyi"]}, | ||
ext_modules=[ | ||
Extension("evdev._input", sources=["evdev/input.c"], extra_compile_args=cflags), | ||
Extension("evdev._uinput", sources=["evdev/uinput.c"], extra_compile_args=cflags), | ||
|
@@ -102,5 +124,6 @@ def run(self): | |
cmdclass={ | ||
"build_ext": build_ext, | ||
"build_ecodes": build_ecodes, | ||
"install": install, | ||
}, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't tested my suggested code yet. Anyhow
if __name__ == '__main__':
. (I think the same way about genecodes.py, but refactoring this now is not important)I wouldn't want to bother you with somewhat opinionated review comments, so I just made the refactor myself: