Well-written C code is easy to compile for different architectures, so the fact that iOS devices use ARM instead of x86 processors isn't a huge problem. CPython supports some ARM platforms natively (mainly Linux), so all of the processor-specific problems have been solved already. iOS is also Unix-based and relatively similar to macOS, so even though CPython doesn't support it natively, the differences aren't huge. There are also projects like https://github.com/pybee/Python-Apple-support, which is basically a set of patches to get CPython working properly on iOS/watchOS/tvOS. (I believe this isn't exactly what Pythonista uses - @omz probably has his own custom version of CPython.)
Interacting between C and Objective-C is also very easy, since Objective-C is more or less an extension of C. This works both ways - you can easily call C code from an Objective-C method, but you can also write regular C functions in Objective-C code, which can use Objective-C features in their implementation, but can also be called from regular C code.
Many of Pythonista's custom modules (like
console, etc.) are implemented using CPython's C API and extension interface, which allows writing Python modules in C. So in principle it's not too difficult to expose iOS Objective-C APIs to Python - you only need to write an extension module in C with some Python-exposed functions that call the appropriate Objective-C APIs. Things get more difficult of course when you also want to provide a nice Pythonic API on the Python side - that requires defining Python classes in C code and converting between Objective-C, C and Python data types where appropriate.
Another way to interact between Python and C is using the
ctypesmodule, which is part of the standard library, and lets you use (almost) any C API from Python at runtime, without having to compile custom C code. This can also be used to interact with Objective-C APIs, because Objective-C's runtime support library provides a pure C interface to most parts of the Objective-C language. Based on this, @omz wrote Pythonista's
objc_utillibrary, which lets you interact with Objective-C APIs and objects from Python. Some of Pythonista's modules (like
editor) are implemented in pure Python using
objc_utilinstead of using CPython's extension API. (There is also a non-Pythonista-specific library called Rubicon, which has similar goals and features as Pythonista's
If I remember correctly, the
enable_faulthandler.pycan't be used as a
pythonista_startup.pydirectly (by default the faulthandler script is meant to be importable, so it doesn't run when loaded). This gist contains the faulthandler script as a working
pythonista_startup.py. (The faulthandler prints a message in the console when it runs, so you can tell when it's working correctly.)
If you're using Python 2, this is a known issue - see https://github.com/omz/Pythonista-Issues/issues/502. At the moment the only workaround is to use Python 3 instead.
@BarryZ Are you sure that you're running exactly the same code on your Mac and in Pythonista, especially the part that you type into the Python console? There is an important difference between
q = Quadratic_Functions_4_1and
q = Quadratic_Functions_4_1()(note the parentheses at the end).
Also, it looks like you might not need to use a class here at all. Your current code would work just fine if you move the functions out of the class, then you can use
QFY(1, 2, 3, 4)directly (without
pythonista_startuprepo has a customize_sys_hooks.py that implements a better traceback display in the console. Among other things, it lets you customize the colors that are used. (It also has a few other features, for example the file paths in tracebacks can be tapped to open the source file in question.) The default colors are designed for light themes, but you can change the
set_colorcalls to use colors that work better with a dark theme.
This only affects tracebacks though, any other stderr output will still be displayed in red. You could probably customize that too, by writing a
sys.stderrreplacement that sets the console color to something different. Alternatively, if you don't care about the difference between stdout and stderr, you can do
sys.stderr = sys.stdout.
It's not possible to install
scipyinto Pythonista yourself, because it requires large amounts of compiled code. (Apple's code signing requirements make it impossible to run any compiled code in Pythonista that doesn't come from Apple or the app developer.) This means that any libraries that depend on
scipyprobably can't be used either. If matplotlib-venn is a pure Python library, it will install successfully, but without its dependencies it won't work properly.
It might be possible to get the library to work if
scipyisn't used in many places in the library. You could try to edit the library source code (under site-packages) and comment out all
scipyimports, and see if the library still works. If you're lucky, you might be able to get the library at least partially working in Pythonista.
(Note: when you modify a library under site-packages, and you have already imported that library, your changes won't take effect right away because the imported module is cached. To fix this, you need to restart Pythonista, so that the library is reloaded properly.)
I'll add my vote for using a JSON file to save settings :) JSON maps nicely to Python lists/dicts, so I find it very convenient to use for this sort of thing. I wouldn't put it in the keychain unless the data is actually sensitive, simply because it seems like the wrong tool for the job. I don't know enough about Pythonista's keychain module and the iOS keychain in general to say if it would actually be bad, but personally I wouldn't want to test it out.
@cvp By the way, you can use
dict.pop(key, None)to remove a key if it's in the dict, and do nothing if it's already missing. That way you can simplify your code to this:
for key in settings_del: settings.pop(key, None)
dict.setdefault(key, value): if
keyis already in the dict, it returns the existing value, otherwise it does
dict[key] = valueand returns
value. That way you can write code like
language = settings.setdefault("language", "en-US"), which gets the language from the settings and sets it to