Skip to content

Commit

Permalink
Merge pull request #185 from spyoungtech/rewrite
Browse files Browse the repository at this point in the history
v1
  • Loading branch information
spyoungtech authored May 2, 2023
2 parents 7988c13 + 8d5688e commit 7d7a234
Show file tree
Hide file tree
Showing 179 changed files with 18,139 additions and 6,352 deletions.
1 change: 0 additions & 1 deletion .coveragerc
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
[run]
branch = True
source = ahk
36 changes: 36 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
on: [ push, pull_request ]

jobs:
build:
strategy:
fail-fast: false
matrix:
python_version: ["3.10", "3.9", "3.8", "3.11"]
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python_version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements-dev.txt
python -m pip install .
python -m pip install tox
python -m pip install ahk-binary
- name: Test with coverage/pytest
timeout-minutes: 5
env:
PYTHONUNBUFFERED: "1"
run: |
tox -e py
- name: Coveralls
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
pip install --upgrade coveralls
coveralls --service=github
31 changes: 25 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff
.idea/

# CMake
cmake-build-*/


# File-based project format
*.iws

# IntelliJ
out/

# mpeltonen/sbt-idea plugin
.idea_modules/


### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand All @@ -20,7 +42,6 @@ parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
Expand Down Expand Up @@ -73,6 +94,7 @@ instance/
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
Expand Down Expand Up @@ -134,8 +156,5 @@ dmypy.json
# pytype static type analyzer
.pytype/

# VS Code settings
.vscode

# Windows desktop icon
desktop.ini
# Cython debug symbols
cython_debug/
52 changes: 50 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,64 @@
repos:

- repo: local
hooks:
- id: unasync-rewrite
name: unasync-rewrite
entry: python .unasync-rewrite.py
language: python
types: [python]
files: ^(ahk/_async/.*\.py|\.unasync-rewrite\.py|tests/_async/.*\.py)
pass_filenames: false
additional_dependencies:
- unasync
- tokenize_rt
- black
- id: set-constants
name: set-constants
entry: python _set_constants.py
language: python
types: [python]
pass_filenames: false
files: ^(ahk/daemon\.ahk|ahk/_constants\.py)

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
rev: v4.4.0
hooks:
- id: mixed-line-ending
args: ["-f", "lf"]
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- id: double-quote-string-fixer
- repo: https://github.com/psf/black
rev: '22.10.0'
rev: '23.1.0'
hooks:
- id: black
args:
- "-S"
- "-l"
- "120"
exclude: ^(ahk/_sync/.*\.py)
- repo: https://github.com/asottile/reorder_python_imports
rev: v3.9.0
hooks:
- id: reorder-python-imports

- repo: https://github.com/pre-commit/mirrors-mypy
rev: 'v0.991'
hooks:
- id: mypy
args:
- "--strict"
exclude: ^(tests/.*|setup\.py|\.build\.py|\.unasync-rewrite\.py|_tests_setup\.py|buildunasync\.py)
additional_dependencies:
- jinja2

- repo: https://github.com/pycqa/flake8
rev: '6.0.0' # pick a git hash / tag to point to
hooks:
- id: flake8
args:
- "--ignore"
- "E501,E704,E301,W503"
files: ahk\/(?!_sync).*
91 changes: 91 additions & 0 deletions .unasync-rewrite.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import ast
import os
import shutil
import subprocess
import sys

import black
from black import check_stability_and_equivalence
from tokenize_rt import reversed_enumerate
from tokenize_rt import src_to_tokens
from tokenize_rt import tokens_to_src

GIT_EXECUTABLE = shutil.which('git')

changes = 0


def _rewrite_file(filename: str) -> int:
with open(filename, encoding='UTF-8') as f:
contents = f.read()
tree = ast.parse(contents, filename=filename)
tokens = src_to_tokens(contents)
nodes_on_lines_to_remove = []
for tok in tokens:
if tok.name == 'COMMENT' and 'unasync: remove' in tok.src:
nodes_on_lines_to_remove.append(tok.line)
lines_to_remove = set()
for node in ast.walk(tree):
if hasattr(node, 'lineno') and node.lineno in nodes_on_lines_to_remove:
for lineno in range(node.lineno, node.end_lineno + 1):
lines_to_remove.add(lineno)
for i, tok in reversed_enumerate(tokens):
if tok.line in lines_to_remove:
tokens.pop(i)
new_contents = tokens_to_src(tokens)
if new_contents != contents:
with open(filename, 'w') as f:
f.write(new_contents)
return new_contents != contents


def _copyfunc(src, dst, *, follow_symlinks=True):
global changes
with open(src, encoding='UTF-8') as f:
contents = f.read()
if os.path.exists(dst):
with open(dst, encoding='UTF-8') as dst_f:
dst_contents = dst_f.read()
try:
black.assert_equivalent(
src=contents,
dst=dst_contents,
)
except AssertionError:
changes += 1
print('MODIFIED', dst)
shutil.copy2(src, dst, follow_symlinks=follow_symlinks)
else:
changes += 1
print('ADDED', dst)
shutil.copy2(src, dst, follow_symlinks=follow_symlinks)
if GIT_EXECUTABLE is None:
print('WARNING could not find git!', file=sys.stderr)
else:
subprocess.run([GIT_EXECUTABLE, 'add', '--intent-to-add', dst])
return dst


def main() -> int:
if os.path.isdir('build'):
shutil.rmtree('build')
subprocess.run([sys.executable, 'setup.py', 'build_py'], check=True)
for root, dirs, files in os.walk('build/lib/ahk/_sync'):
for fname in files:
if fname.endswith('.py'):
fp = os.path.join(root, fname)
_rewrite_file(fp)
subprocess.run([sys.executable, '_tests_setup.py', 'build_py'], check=True)
for root, dirs, files in os.walk('build/lib/tests/_sync'):
for fname in files:
if fname.endswith('.py'):
fp = os.path.join(root, fname)
_rewrite_file(fp)
shutil.copytree('build/lib/ahk/_sync', 'ahk/_sync', dirs_exist_ok=True, copy_function=_copyfunc)
shutil.copytree('build/lib/tests/_sync', 'tests/_sync', dirs_exist_ok=True, copy_function=_copyfunc)

return changes


if __name__ == '__main__':
raise SystemExit(main())
21 changes: 0 additions & 21 deletions LICENSE

This file was deleted.

5 changes: 3 additions & 2 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
include LICENSE
include ahk/templates/daemon.ahk
include ahk/templates/hotkeys.ahk
include docs/README.md
recursive-include ahk/templates *
include buildunasync.py
1 change: 0 additions & 1 deletion README.md

This file was deleted.

37 changes: 37 additions & 0 deletions _set_constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import shutil
import subprocess
import sys

with open('ahk/templates/daemon.ahk') as f:
daemon_script = f.read()

with open('ahk/templates/hotkeys.ahk') as hotkeyfile:
hotkey_script = hotkeyfile.read()

GIT_EXECUTABLE = shutil.which('git')

if not GIT_EXECUTABLE:
raise RuntimeError('git executable not found')

new_contents = f'''\
# THIS FILE IS AUTOGENERATED BY _set_constants.py
# DO NOT EDIT BY HAND
DAEMON_SCRIPT_TEMPLATE = r"""{daemon_script}
"""
HOTKEYS_SCRIPT_TEMPLATE = r"""{hotkey_script}
"""
'''

with open('ahk/_constants.py', encoding='utf-8') as f:
constants_text = f.read()

if constants_text != new_contents:
with open('ahk/_constants.py', 'w', encoding='utf-8') as f:
f.write(new_contents)
print('MODIFIED _constants.py', file=sys.stderr)
subprocess.run([GIT_EXECUTABLE, 'add', '--intent-to-add', 'ahk/_constants.py'])
raise SystemExit(1)
else:
raise SystemExit(0)
41 changes: 41 additions & 0 deletions _tests_setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""
Not a real setup package
This is just to unasync our tests files
"""
import setuptools
import unasync

setuptools.setup(
name='ahk',
version='0.0.1',
author='Example Author',
author_email='author@example.com',
description='A package used to test customized unasync',
url='https://github.com/pypa/sampleproject',
packages=['tests', 'tests._async'],
cmdclass={
'build_py': unasync.cmdclass_build_py(
rules=[
unasync.Rule(
fromdir='/tests/_async/',
todir='/tests/_sync/',
additional_replacements={
'AsyncAHK': 'AHK',
'AsyncTransport': 'Transport',
'AsyncWindow': 'Window',
'AsyncDaemonProcessTransport': 'DaemonProcessTransport',
'_AIOP': '_SIOP',
'async_create_process': 'sync_create_process',
'adrain_stdin': 'drain_stdin',
'IsolatedAsyncioTestCase': 'TestCase',
'asyncSetUp': 'setUp',
'asyncTearDown': 'tearDown',
'async_sleep': 'sleep',
# "__aenter__": "__aenter__",
},
),
]
)
},
# package_dir={"": "src"},
)
29 changes: 26 additions & 3 deletions ahk/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,27 @@
from ahk.autohotkey import AHK, ActionChain, AsyncAHK
from ahk.keyboard import Hotkey
from typing import Any
from typing import Optional

__all__ = ['AHK']
from ._async import AsyncAHK
from ._async import AsyncControl
from ._async import AsyncWindow
from ._sync import AHK
from ._sync import Control
from ._sync import Window

__all__ = ['AHK', 'Window', 'AsyncWindow', 'AsyncAHK', 'Control', 'AsyncControl']

_global_instance: Optional[AHK] = None


def __getattr__(name: str) -> Any:
global _global_instance
if name in dir(AHK):
if _global_instance is None:
try:
_global_instance = AHK()
except EnvironmentError as init_error:
raise EnvironmentError(
'Tried to create default global AHK instance, but it failed. This is most likely due to AutoHotkey.exe not being available on PATH or other default locations'
) from init_error
return getattr(_global_instance, name)
raise AttributeError(f'module {__name__!r} has no attribute {name!r}')
Loading

0 comments on commit 7d7a234

Please sign in to comment.