Today, the BeeWare project is making 2 changes to the way we organize our community.
Firstly, we're going to move our real-time chat community from Gitter to Discord.
When we originally set up Gitter, it was a strong option for a chat community - especially one that was focussed on a software project, due to its tight integration with Github. However, over the years, Gitter has undergone multiple changes of ownership, but has remained essentially unchanged - in some cases, it's gotten appreciably worse (their native iOS and Android clients are effectively deprecated). In the meantime, Discord has emerged as a dominant player for community chat. It has a robust mobile client, and really good tools for community moderation, as well as the option of hosting video and voice chats - something we hope to be able to use for coordinating virtual sprints.
To join the new BeeWare Discord server, visit this link.
Secondly, we're going to start using Github Discussions.
For many years, we've tried to use Github Issues as a pseudo-forum. There's a lot of similarity between how a forum works and how Github displays and manages issues. Each "issue" is effectively a forum thread, and each comment is a message in that thread. However, there are also some important differences. Issues get closed when they're resolved; forum threads, however, don't necessarily have a resolution. Most importantly, "closing" an issue can look like someone is trying to kill discussion - when all they're really trying to do is keep the list of issues manageable.
The good news is that Github has noticed the similarity too, and has launched Github Discussions. Discussions offers a familiar "forum" interface, but with the familiar Github message interface, and tight integration with Github Issues and pull requests.
Naturally, all of these new community spaces - along with all existing BeeWare spaces - are subject to the BeeWare Community Code of Conduct.
We hope these two changes will make it easier to participate in the BeeWare community. See you there!
9 months ago, we announced that the BeeWare Project was the recipient of a PSF Education Grant. In late 2019, we choose Asheesh Laroia to do the work. Today, we're proud to announce that BeeWare's Android support has reached a point where it is ready for mass consumption.
The BeeWare tutorial has been updated to include an Android track. The tutorial walks you through the process of writing your first app, and deploying it - first as a desktop app, and then on your phone. All you need is a Python install; everything else you need is downloaded automatically by the BeeWare tools as part of the development process.
And, to prove that it's real - we have uploaded Travel Tips to the Google Play Store. This is a Python app, in the Google Play Store, deployed from the same source code as the version in the iOS App Store.
Huge thanks go to Asheesh for all the work he's put into this project. Delivering Android support in BeeWare has required considerable technical skill, attention to detail, and creative hacks; and Asheesh has consistently delivered. Huge thanks also go to the Education Grants Committee of the Python Software Foundation for the faith they placed in BeeWare when they funded this project. In 6 months (while simultaneously negotiating a world pandemic), we've gone from a nothing to a full Android implementation. Without their financial support, this project would still be a dream.
There's still plenty of work to be done, though. There are still a lot of widgets that need Android implementations, and new widgets that we want to add. We'd like to add support for device features like cameras, GPS and accelerometers. We'd like to make it easier to use binary Python packages like NumPy, Keras, and more. And we'd like to merge the work that we've done into CPython itself.
All of those are significant projects in themselves, and will require effort comparable to that required to add Android as a supported platform. And so, we're looking for the financial support to make that happen. We're applying for new grants as opportunities arise, but the most helpful source of funds are the ongoing funds that come from memberships. Ongoing funding means we can focus on improving BeeWare, rather than chasing grants. It means being able to hire permanent staff, rather than offering short term contracts. And it means being able to make long term plans and promises to the community.
If this project proves anything, it's that money makes things happen. If you're excited by the prospects of Python on mobile platforms, please consider joining the BeeWare Project as a financial member. Or, if you've got experience with commercialisation of Open Source projects, or any other ideas for how we could please get in touch.
For the last couple of months, we've had a contractor (Asheesh Laroia) working on fixing Android support in the BeeWare suite of tools.
I've incredibly happy to announce that we've just hit our first major milestone: a working pure-Python application, running on an Android device!
This isn't the end of the project - it's just the beginning. There's still lots of fine tuning to be done (especially on the size of the support libraries), and we need to integrate this support into Briefcase and Toga.
However, in the meantime, if you're adventurous, you can take Asheesh's work-in-progress for a spin. His Python Android Support repository contains the current state of the work, and includes fairly comprehensive instructions for getting started. You'll need to know at least a little bit about native Android programming to make full use of this repository at the moment; but if you want to replicate the results from the video, that repository (and the other repositories it links to) should have everything you need.
Huge thanks go once again to the Python Software Foundation. Without their financial support, this work would still be on the drawing board. This project is just one of many ways that the PSF uses donations to improve the Python community and ecosystem. If your company uses Python in any capacity, I strongly encourage you to contribute financially to the PSF so that they can continue to fund worthwhile projects like this.
Huge thanks also go to Asheesh. Without his remarkable talents, attention to detail, and delight for obscure compiler errors, we wouldn't have made the incredibly fast progress that we've seen.
Stay tuned for more announcements soon!
A couple of months ago, we announced that the BeeWare project had received a grant from the PSF to improve our support for Android. At that time, we issued a call for contractors to help us complete this work.
We're very happy to announce that we've now selected a contractor: Asheesh Laroia.
Asheesh is a regular speaker at Python events, where he has delved into a range of detailed and complex topics. He also impressed us with the list of unconventional engineering integration projects he's been involved with in a professional and casual capacity.
When asked why he applied to work with BeeWare on this contract, Asheesh said: "I use an Android phone every day, and I'm honored to be able to help implement the BeeWare vision of using Python to build first-class, native applications."
Asheesh will be starting work in mid December, and if all goes well, we should start seeing significant results by mid to late February. If you'd like to keep track of progress, you can follow BeeWare on Twitter; we'll also post larger updates on this blog.
The BeeWare Project wants to make it possible for all Python developers to write native apps for desktop and mobile platforms. We have solid support for most desktop operating systems and iOS, but we know our Android support is lacking. The BeeWare core team knows what needs to be done to address the problem - what we’ve been missing are time and resources.
Thanks to the PSF Education Grants group, that’s no longer an issue. We’ve been awarded a US$50,000 grant to bring BeeWare’s Android support to a level comparable with our iOS support. We currently don’t have the time to do the work ourselves, so we’re calling for contractors to help us deliver this support.
This is a paid contract, which we anticipate lasting 3-6 months (depending on the experience of the winning contractor). You don’t have to be based in the US or Europe, either; the opportunity is open to anyone who can meet the requirements of the contract.
Unfortunately, the task calls for some sophisticated skills, and we’re not in a position to provide extensive mentoring. A successful bid is likely to require some prior experience, and a history with the technologies involved.
We look forward to being able to announce full Android support in the near future!
Google Summer of Code is coming to an end. I've spent the summer working on optimizing the VOC compiler, and I’m super excited to share the results.
There are a couple of ways to evaluate the performance improvement from my project.
Firstly, we introduced a microbenchmarking suite. Each microbenchmark is a small piece of Python code that tests a single and specific Python construct, or datatype, or control flow. The benchmarking infrastructure itself is crude (essentially it just tells you the total amount of processor time it took to run, with no fancy statistics) but it has been extremely useful to me while working on performance features to verify performance gain.
The idea is that the benchmarking suite is not to be run as part of the full test suite, but rather as needed and manually whenever an optimization is implemented. It also provides a way to check and prevent performance regression, especially on the "optimized" parts of VOC. While it doesn't really make sense to record specific numbers, as they will always vary from machine to machine, it should be reasonably easy to compare two versions of VOC. Benchmark numbers are included on each optimization-related PR I've worked on this summer (see PR log below), and I hope that more benchmarks will be added as more performance efforts are carried out in the future.
May 10th, 2018:
$ python setup.py test -s tests.test_pystone test_pystone (tests.test_pystone.PystoneTest) ... Pystone(1.2) time for 50000 passes = 101.833 This machine benchmarks at 490.998 pystones/second
$ python setup.py test -s tests.test_pystone test_pystone (tests.test_pystone.PystoneTest) ... Pystone(1.2) time for 50000 passes = 101.298 This machine benchmarks at 493.595 pystones/second
$ python setup.py test -s tests.test_pystone test_pystone (tests.test_pystone.PystoneTest) ... Pystone(1.2) time for 50000 passes = 102.247 This machine benchmarks at 489.014 pystones/second
On current master (Aug 14th, 2018):
$ python setup.py test -s tests.test_pystone test_pystone (tests.test_pystone.PystoneTest) ... Pystone(1.2) time for 50000 passes = 11.2300 This machine benchmarks at 4452.37 pystones/second
$ python setup.py test -s tests.test_pystone test_pystone (tests.test_pystone.PystoneTest) ... Pystone(1.2) time for 50000 passes = 10.9833 This machine benchmarks at 4552.36 pystones/second
$ python setup.py test -s tests.test_pystone pystone (tests.test_pystone.PystoneTest) ... Pystone(1.2) time for 50000 passes = 10.9498 This machine benchmarks at 4566.29 pystones/second
Some things that I learned about VOC while working on this project:
1. Object creation in the JVM is expensive. This definitely does not mean that the VOC user writing Python should think about minimizing the number of objects that she creates, but rather that any time we can non-trivially reduce the number of objects created during bytecode transpilation or in VOC-defined function calls, we can expect to see a huge performance boost. Integer and boolean preallocation, which is about reusing objects that have already been created, was one of the most significant improvements we made this summer.
2. Method calls in VOC are expensive. This is essentially due to the process of invoking a callable: you have to check that the method is defined on the object, then construct it (read: object creation!), and check the arguments, before it can actually be called. (This is done using reflection, which is super interesting and confusing in itself.) And this is the reason why refactoring the Python comparison functions made such a big performance impact, because we were able to circumvent this process.
3. Exception-heavy code is expensive. Again, this is not to say that the programmer is on the hook for being frugal when throwing exceptions, but that VOC benefits greatly by avoiding the use of exceptions internally except when strictly necessary. For instance, Python uses StopIteration exceptions to signal the end of a for loop, and they quickly rack up when you have nested loops (everything is ultimately related to object creation!). That was the motivation for the nested loops optimization.
If I may be a bit more reflective here, one of the a-ha! moments I had this summer was realizing that to really optimize something, you have to understand where its biggest problems are first. I remember pitching to Russ at the start of the summer things like loop unrolling, constant folding, even converting to SSA-form (you know, stuff I heard about optimzation in my compilers class) and he was saying to me, think simpler. While working on my project, I used a profiler to understand exactly which parts of VOC were slow, and that information drove the changes we implemented. I think it worked out pretty well!
- Minimize boxing of primitive types like String and Int. As VOC is written half in Python, half in Java, a single integer can be found in various representations on its way through the compiler -- as a Python object, unboxed to a primitive Java int, then packaged back up to a Python object. This problem was (somewhat incoherently) addressed in my proposal, but ultimately we couldn't come up with a good abstraction to support it.
- Build a peephole optimizer. CPython's peephole optimizer scans generated bytecode to identify sequences of bytecode that can be optimized, VOC could benefit from this too.
- Hook up more benchmarks, which serve as both proof of the kinds of programs VOC can currently compile and areas ripe for performance improvement.
I will wrap this up by giving big thanks to Russ, my mentor. The time you spent helping me form my ideas, patiently answering my questions and reviewing my work was invaluable to me. It couldn't have been easy keeping up with what I was doing especially since I started improvising halfway through the summer. I am so grateful for your help, thank you.
PR Log (in chronological order)
Bug Fixes and Miscellaneous
- Fix Method repr
- Fix custom substitutions
- Fix List Bug
- Remove Unnecessary Instruction
- Fix __setitem__ error messages
- Fix contains/not contains bugs and refactor
- Add tests for problematic exception raising
- Add test for with + exception combo
- Add test for wrong iter error message
- Add tests for globals bug
- Remove unnecessary type casts and clean up
- Add test for problematic builtin function call
- Introduce org/python/Object type tests
In the blink of an eye, Google Summer of Code (GSoC) 2018 has come to an end. During the three months long coding period, I have contributed several patches in VOC repository of BeeWare, all working towards the ultimate end goal of running asyncio module in VOC. In this blog post (which is my first actual blog post by the way 😄), I will document what I have done so far, why I couldn't make it to the end goal (yea, unfortunately I couldn't get asyncio to work at the end of GSoC 2018), and what's left that needs to be done in order to achieve the end goal (or at least make part of asyncio work).
The first error that the transpiler throws when attempting to compile asyncio module was "No handler for YieldFrom", so it makes sense to start from this issue first.
Another feature related to generator was Yield expression. Before GSoC 2018, Yield statement in VOC was just a statement, meaning yield could not be used as expression. Generator methods such as generator.send, generator.throw and generator.close were not supported as well. Those features are what make asynchronous programming with generator possible, so I spent a few weeks to extend generator functionality in VOC, laying down the path to asyncio module.
PRs related to generator are listed below:
Nonlocal statement was another syntax not supported by VOC. After completion of generator's features, implementing this is the next step towards compiling asyncio module.
Implementing this feature took about 3 ~ 4 weeks as this is not as trivial as it seems. I took several approaches on this, while some of them do work, the code is not pretty and hacky, which could come back to bite me/other contributors in the long run. After many discussions with Russell, I refactored the closure mechanism in VOC and took a much cleaner approach in nonlocal implementations. I must admit that I took some short-cuts for the sake of "making nonlocal works" in the process of implementing nonlocal statement, resulting in poor design and messy codes. Many thanks to Russell, who helped me to improve my coding style and told me not to be discouraged when I'm stuck. 😄
The Collections Module
Next item on my hit list was pure Java implementations of the collections module. asyncio module depends on 3 data structures from collections, namely defauldict, Deque and OrderedDict. Two of them (defaultdict and Deque) are implemented in C in CPython, plus they have good analog in Java, so it makes senses to implement the module in Java. Porting defauldict, Deque and OrderedDict to Java in VOC is relatively straight-forward, taking about 1.5 weeks to complete.
Other PRs submitted during GSoC 2018
- PR #817 : Added coroutine related exception class [WIP] (closed due to not needed)
- PR #836 : Changed Bool construction to use getBool instead (merged)
- PR #847 : Add custom exceptions test cases (closed due to more comprehensive handling in PR #844)
- PR #849 : Fixed Unknown constant type <class 'frozenset'> in function definition (merged)
- PR #858 : Added test case for Issue #857 (merged)
- PR #860 : Added test case for Issue #859 (merged)
- PR #862 : Added test case for Issue #861 (merged)
- PR #867 : Fixed Issue #866 RunTimeError when generator is nested in more than 1 level of function definition (merged)
- PR #868 : Fixed Issue #861 Redefining nested function from other function overrides original nested function (merged)
- PR #879 : Fixed Incompatible Stack Height caused by expression statement (merged)
- PR #901 : Added test case for Issue #900 (merged)
- PR #788 : Implements asyncio.coroutines [WIP] (open, the dream 😎)
Issues submitted during GSoC 2018
- Issue #861 : Redefining nested function from other function overrides original nested function (fixed in PR #868)
- Issue #866 : RunTimeError when generator is nested in more than 1 level of function definition (fixed in PR #867)
- Issue #828 : Finally block of generator is not executed during garbage collection (open)
- Issue #857 : Complex datatype in set cause java.lang.StackOverflowError (open)
- Issue #859 : Duplicated values of equivalent but different data types in set (open)
- Issue #900 : Exception in nested try-catch suite is 'leaked' to another enclosing try-catch suite (open)
- Issue #827 : Maps reserved Java keywords to Python built-in function/method call (closed)
Towards The Ultimate End Goal
Unfortunately, three months of GSoC coding period was not enough for me to bring asyncio module to VOC. The nonlocal statement implementation was the biggest blocker for me mainly because I didn't think thoroughly before writing code. If I were to plan carefully and lay out a general coding direction, I would've completed it in much shorter time and have time for other implementations. An advice for the aspiring and upcoming GSoC-er, don't rush your code, make sure you know 100% about what you're doing before diving into the codes.
With that said, following are the list of modules to be implemented/ported to Java before asyncio will work in VOC:
- socket module (a bit tricky since Java doesn't support Unix domain socket natively)
- selectors module (high level I/O operations)
- threading module (might be easier to implement this first since threading in Python is an emulation of Java's Thread)
- time module (partially implemented in VOC)
Huge thanks to my mentor, Russell Keith-Magee for accepting my proposal, providing guidance and encouraging me when things didn't go as intended. It is truly an honor to be a part of the BeeWare community. I had a blast contributing to BeeWare project, and I'm sure I will stick around as a regular contributor. Also shout out to the BeeWare community for answering my queries and reviewing my pull requests. 😄
This article was originally published on the BeeWare Enthusiasts mailing list. If you'd like to receive regular updates about the BeeWare project, why not subscribe?
When you're designing a GUI app - be it for desktop, mobile, or browser - one of the most fundamental tasks is describing how to lay widgets out the screen. Most widget toolkits will use a grid or box packing model of some kind to solve this problem. These models tend to be relatively easy to get started, but rapidly fall apart when you have complex layout needs - or when you have layouts that need to adapt to different screen sizes.
Instead of inventing a new grid or box model, the Toga widget toolkit takes a different approach, using a well known scheme for laying out content: Cascading Style Sheets, or CSS. Although CSS is best known for specifying layout in web pages, there's nothing inherently web specific about it. At the end of the day, it's a system for describing the layout of a hierarchical collection of content nodes. However, to date, every implementation of CSS is bound to a browser, so the perception is that CSS is a browser-specific standard.
That's where Colosseum comes in. Colosseum is a browser independent implementation of a CSS rendering engine. It takes a tree of content "nodes" - such as a DOM from a HTML document - an applies CSS styling instructions to layout those nodes as boxes on the screen. In the case of Toga, instead of laying out <div> and <span> elements, you lay out Box and Button objects. This allows you to specify incredibly complex, adaptive layouts for Toga applications.
But Colosseum as a project has many other possible uses. It could be used anywhere that there is a need for describing layout outside a browser context. For example, Colosseum could be the cornerstone of a HTML to PDF renderer that doesn't require the involvement of a browser. It could also be used as a test harness and reference implementation for the CSS specification itself, providing a lightweight way to encode and test proposed changes to the specification.
This week, we started a big project: rewriting Colosseum to be a fully standard-compliant CSS engine. The work so far can be found in the globe branch of the colosseum repository on Github. The first goal is CSS2.1 compliance, with an implementation of the traditional CSS box model and flow layout. Once we've got a reasonable implementation of that, we'll look to adding Grid and FlexBox layouts from the CSS3 specification set.
This is obviously a big job. CSS is a big specification, so there's a lot of work to be done - but that also means there's lots of places to contribute! Pick a paragraph of the CSS specification, build some test cases that demonstrate the cases described in that paragraph, and submit a patch implementing that behaviour!
It also highlights why your financial support is so important. While we could do this entirely with volunteered effort, we're going to make much faster progress if a small group of people could focus on this project full time. Financial support would allow up to significantly ramp up the development speed of Colosseum, and the rest of the BeeWare suite.
If you would like to see Colosseum and the rest of BeeWare develop to the point where it can be used for commercial applications, please consider supporting BeeWare financially. And if you have any leads for larger potential sources of funding, please get in touch.
After almost 4 months of work on Google Summer of Code 2017, finally I'm completing my proposal. Every widget migration and every commit/PR/issue/discussion with my mentors about Cricket , Toga and rubicon-objc were detailed on the Issue 58.
"Eating your own dog food"
The best way to show that a product is reliable to the customers is use it. So, the way to show that Toga is an effective tool to build a GUI is to build a complete application using it.
Cricket is a graphical tool that helps you run your test suites. Its current version is implemented using Tkinter as the main GUI framework. So, why not test Toga inside of another product from BeeWare? That's what I have acomplished during my GSoC work.
The proposal focus not only on the port of Tkinter to Toga, but on mapping the necessary widgets for a real application using Toga framework. To help me to map this I studied more about Tkinter, Toga, Colosseum, rubicon-objc, Objective-C, Cocoa and CSS.
The work I did during GSoC were sent throught the PR 65, reported on the Issue 58 and the final demonstration of the work can be seen in this link. There were widgets used on Cricket that weren't ready yet on Toga, so some improvements were necessary on Toga so that I could use them on Cricket. In summary here are some PRs and issues that I contributed to get my work done in Cricket:
Open PR that I sent to Toga:
- PR 201 : [Core][Cocoa] Refactoring of the Tree widget
Merged PRs that I sent to Toga:
- PR 112 : [Core][Cocoa] Enable/disable state for buttons, solved Issue 91
- PR 170 : [Cocoa] Content and retry status for stack trace dialog
- PR 172 : [Cocoa] Window resize
- PR 173 : [Core][Cocoa] Button color
- PR 174 : [Doc] Examples folder and button features example
- PR 178 : [Doc] Fix tutorial 2 setup
- PR 180 : [Doc] Update Toga widgets roadmap
- PR 182 : [Cocoa] Update the label of the Stack trace button for critical dialog
- PR 184 : [Core][Cocoa] Hide/show boxes widget
- PR 188 : [Cocoa] Fix error on MultilineTextInput widget, solved Issue 187
- PR 204 : [Core][Cocoa] Clear method to MultilineTextInput widget, solved Issue 203
- PR 206 : [Core][Cocoa] Readonly and placeholder for MultilineTextInput widget
- PR 208 : [Cocoa] Fix apply style to a SplitContainer widget, solved Issue 207
Merged PR that I sent to Cricket:
Merged PR that I sent to rubicon-objc:
- PR 34 : [Doc] Add reference to NSObject
Open issues that I sent to Toga:
- Issue 175 : [Core] Add more properties for Label and Font widgets
- Issue 176 : [Core] Add "rehint()" on the background of the widget after changing font size
- Issue 186 : [Core] Set initial position of the divisor of a SplitContainer
- Issue 197 : [Core] Get the id of the selected Tab View on the OptionContainer
Closed issues that I reported to Toga:
- Issue 167 : [Cocoa] Addition of a SplitContainer on a Box doesn't show the SplitContainer, was fixed by Russell Keith-Magee
- Issue 168 : [Cocoa] Addition of 2 boxes on an OptionContainer emits Rubicon's error, was fixed by Russell Keith-Magee
- Issue 169 : [Cocoa] Addition of 2 empty boxes on an OptionContainer emits error from Toga Cocoa platform, was fixed by Russell Keith-Magee
- Issue 181 : [Core][Cocoa] "Hide" option for widgets, was solved by me
- Issue 187 : [Cocoa] Errors on MultilineTextInput, was fixed by me
- Issue 189 : [Cocoa] ProgressBar doesn't appears in a Box, was fixed by Jonas Schell
- Issue 194 : [Cocoa] The frame of the MultilineTextInput doesn't appear, was fixed by Russell Keith-Magee
- Issue 195 : [Cocoa] ProgressBar doesn't appear inside of a Box oriented by row, was fixed by Russell Keith-Magee
- Issue 196 : [Cocoa] Set max value and value on a ProgressBar doesn't make any effect on the layout, was fixed by Russell Keith-Magee
- Issue 203 : [Core][Cocoa] Clear text on MultilineTextInput widget, was solved by me
- Issue 207 : [Cocoa] Set SplitContainer height doesn't update its size, was solved by me
Closed issues that I didn't reported but I solved on Toga:
Closed issue that I reported to Cricket:
- Issue 59 : Run selected doesn't count/ runs every test selected in a test module, was fixed by me
- Issue 1 : Seg Fault when iterate through a NSIndexSet using block notation
There are some features on Cricket that I want to help develop in a near future, for example:
- A button to refresh all the tests tree
- Cricket settings
- A gap between the output and error boxes when there is no output message
- Run a test if the user click on it
I truly believe that Toga will be the oficial framework on Python to build GUI for multiplatforms applications, so I'll continue to contribute to this project because I want to use in every application that I would need a GUI.
I would like to truly thank my mentors Russell Keith-Magee and Elias Dorneles for guide and help me so much during this period. The opportunity to be part of this community was a great honor to me, thank you so much to accept me in this program Russell Keith-Magee. Also, I want to thank Philip James that made some reviews in my PRs and Jonas Schell that fixed one issue that I sent to Toga.
With Google Summer of Code 2017 program nearing its end, it is time to summarize what I got done during the summer working on Batavia.
Batavia is a part of BeeWare's collection of projects. As it is still in its early stage of development, for my part I offered to implement a number of features missing from Batavia, ranging from elemental data types, through JSON manipulation and language constructs such as generators. I posted my proposal in this GitHub thread and kept it updated with my progress on a weekly basis.
Note that by the end of GSoC, we have decided to diverge from the proposal and forgo implementation of contextlib in favor of support for Python 3.6 2-byte wide opcodes.
Overall it was great learning experience and fun. Big thanks to my mentors Russell Keith-Magee and Katie McLaughlin, and the whole BeeWare community.