Skip to content
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

Add support for Windows #110

Merged
merged 3 commits into from Oct 18, 2019
Merged

Add support for Windows #110

merged 3 commits into from Oct 18, 2019

Conversation

avylove
Copy link
Collaborator

@avylove avylove commented Sep 23, 2019

This should address #18 and #90. (and maybe #73?)

This mostly came out of my efforts to support Enlighten on Windows. I just needed a subset of Blessed for Enlighten, so that's what I originally implemented, but I kept looking at it and eventually it seemed like I had enough pieces to add Windows support to Blessed itself.

I decided to move the bulk of the logic to its own library, Jinxed. It provides a pure Python (with some ctypes calls) implementation for the parts of curses needed by Blessed. The terminfo is implemented through inherited dictionaries rather than by parsing the upstream terminfo. While that's a little more work upfront, it's more efficient and should make it easier for people to add new terminals. For new versions of Windows 10, it enables the build-in terminal processing and, for older versions of Windows, it relies on ANSICON which will be automatically loaded. ANSICON is missing a few things. For example, there's no smcup equivalent and some key combinations are not recognized, but it provides enough capabilities for most projects. If another library provides better support, it's relatively easy to add.

The tests currently don't run on Windows, but this is primarily due to the way the tests are constructed. Mostly, it's replacing some of the termios calls like echo_off() with a Windows equivalent and making a dummy version of as_subprocess() since Jinxed will allow you to rerun setupterm() multiple times. That can be done if you think it's necessary. The actual implementation for Windows is pretty thin and contained in blessed/win_terminal.py.

Let me know what you think.

@jquast
Copy link
Owner

jquast commented Sep 23, 2019

Very exciting I’ll look soon thanks

@jquast
Copy link
Owner

jquast commented Oct 1, 2019

This looks great so far, I like non-secular pure-python curses replacement for common terminfo entries. This seems even more portable than what blessed already is.

I'm pretty OK with merging it as it is, I would hope to, and release, at the end of the week. If I gave you contributor access and you preferred, you could put yourself down for co-maintainer and we can maintain all of the code in this one library, something to think about, I'm not able to keep up with much volume and could use the help, thanks again!

@avylove
Copy link
Collaborator Author

avylove commented Oct 1, 2019

I'm happy to help maintain Blessed. I depend on it, so I have an vested interest in keeping it maintained.

As far as if the code should live within Blessed or not. What I usually ask myself is if the code is useful independently or might require more frequent updates. That's why I figured it might be better to keep the code in Jinxed. What may be useful is making Jinxed more generic so it can be used with non-Windows systems as well for generic things like looking up the terminfo or running a pure python version of tparm. In fact, I think the only blocker to *nix use is get_term() is imported from jinxed.win32. I could make a generic version of get_term() that simply calls os.environ.get('TERM', 'unknown') and conditionally load it.

There is another issue that came up recently with Enlighten and would affect Blessed once it supports Windows. When using universal wheels, the dependencies for the wheels are determined on the system the wheels were built on. So if you have logic in setup.py with extra dependencies for Windows, build a wheel on Linux, and install the wheel on Windows, unless those dependencies use PEP 508 logic, they won't be installed. This does not affect installing from a tarball. So basically there are four options:

  1. Don't provide a wheel. Pip will install from source. Downside is people tend to favor wheels.
  2. Hack setup.py to not build universal wheels and build both Linux and Windows wheels. The problem with this is we'd probably have to figure out how to build these with a CI tool and get them up to PyPI.
  3. Install all dependencies. This is easy, though a bit of a waste (100kb for the wheels) and people might wonder why we're installing things not for their platform.
  4. Use PEP 508 logic in dependencies, for example 'jinxed; platform_system == "Windows"'. This is obviously the prescribed method, but could cause issues for people running in older environments. I believe this requires setuptools >= 20.2.2 or pip >= 9.0.0 depending on how you're installing. They came out in 2016. It's probably not an unreasonable ask, but will cause for people running older software. This has specifically been an issue in Windows test environments running tox on Appveyor for versions of Python older than 3.6 unless they upgrade pip before installing dependencies. This would also be an issue for me personally since I maintain the Blessed for EPEL, which also has ancient software, but I can simply remove the line from requirements programatically in the RPM build environment.

I went with number 4 for Enlighten for now. I'm not sure the impact since I just moved to it yesterday, but so far the only issue has been on Appveyor.

Sorry for the brain dump, but let me know what you think and I can adjust the dependencies in this branch. The way it's currently done, it will break on an installation from wheel on Windows.

@avylove
Copy link
Collaborator Author

avylove commented Oct 16, 2019

I added the PEP 508 dependencies. They haven't seemed to be an issue with Enlighten and the issue with AppVeyor is known and easy to work around. So it shouldn't be an issue as long as people are using a version of pip that came out in the last 3 years. For RHEL/CentOS 6/7, I already maintain an RPM version of Blessed through EPEL, so it's generally installed without pip. I can implement a different approach if you think it will be an issue.

# support python2.6 by using backport of 'orderedict'
ordereddict==1.1; python_version < "2.7"
# Windows requires jinxed
jinxed>=0.5.4; platform_system == "Windows"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well I hope you will do nicely and not break jinxed any day in the future :)

I don't typically care for these >=, anything could happen in the future, nefarious, even, but I'm a bit FOSS tired and feeling more trusting these days.

@jquast
Copy link
Owner

jquast commented Oct 18, 2019

I'm merging and publishing to pypi shortly, great contribution, thanks a bunch.

@jquast jquast merged commit 0dade64 into jquast:master Oct 18, 2019
@jquast
Copy link
Owner

jquast commented Oct 18, 2019

@jquast
Copy link
Owner

jquast commented Oct 18, 2019

oh yeah, i'm ok with number 4 option too, merged as-is, hope it goes well :)

@avylove
Copy link
Collaborator Author

avylove commented Oct 18, 2019

Awesome! I'll keep an eye on things in case there are any issues. And I'll update my code to use it! As far as maintenance, I'm subscribed to Blessed, so I'll try to help out where I can. Jinxed was created primarily to support Blessed, so I'm not seeing much changing there. In the future, maybe we can think about creating a GitHub org for these terminal-related libraries.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants