Forum Archive

Xcode Template for Pythonista

mrcoxall

I am trying to upload a Pythonista project to the Apple App Store.
I have tried many, many time and keep getting code signing errors.
I am using Xcode 8.2.1
So this is what I have done:

Started with new Xcode Swift single view project, archived it and was able to submit it to the App Store. So my certificates are all working. I downloaded the Xcode template and then archived it. When I submit to Apple, it hangs on the code signing for a really long time and then comes back with this error:

ERROR ITMS-90035: "Invalid Signature. Code object is not signed at all. Make sure you have signed your application with a distribution certificate, not an ad hoc certificate or a development certificate. Verify that the code signing settings in Xcode are correct at the target level (which override any values at the project level). Additionally, make sure the bundle you are uploading was built using a Release target in Xcode, not a Simulator target. If you are certain your code signing settings are correct, choose "Clean All" in Xcode, delete the "build" directory in the Finder, and rebuild your release target. For more information, please consult https://developer.apple.com/library/ios/documentation/Security/Conceptual/CodeSigningGuide/Introduction/Introduction.html"

The only thing I can figure out is that it seems to be trying to code sign the PythonistaKit.framework and does not seem to be able to. I can see "PythonistaKit.framework (0 Entitlements), just before I validate it.

Wondering if anyone else is able to reproduce this error, or even better have a fix to the problem.
Thanks

polymerchm

Not that I have tried it, but you might try it as an objective-c project since I believe that's how OMZ wrote pytonista.

omz

@mrcoxall I'm aware of this problem, as it's also been affecting the main Pythonista app for a while. The reason for the error seems to be a server-side change in the way code signatures are verified. In short, iTunes Connect seems to use the file utility to check for executables in the bundle, and it then treats every Python file as an executable that should be signed (which isn't actually possible, as far as I'm aware). Of course, this is pretty much an edge case, as most iOS apps don't contain any scripts.

In recent betas (when the problem started appearing), I've used a somewhat dirty hack to work around this: The file utility basically uses some heuristics to determine the type of file (text/executable...), and it's possible to trick it into recognizing Python files as something else. There are probably multiple ways to do this – the one I'm using is to prepend files with a line that contains #\input texinfo, which makes file think that it's a TeX document.

I'm using a script similar to this for automating the process:

# Change these:
pylib_path1 = '<something like ".../PythonistaKit.framework/pylib">'
pylib_path2 = '<something like ".../PythonistaKit.framework/pylib_ext">'

import shutil
import os
import subprocess

def check_is_executable(file_path):
    file_output = subprocess.check_output(['file', file_path])
    if 'executable' in file_output:
        return True, file_output
    return False, file_output

def fix_executable(file_path):
    with open(file_path, 'r') as f:
        source = f.read()
    with open(file_path, 'w') as f:
        f.write('#\input texinfo\n' + source)
    is_executable, out = check_is_executable(file_path)
    return not is_executable

def fix_pylib(pylib_path, dry_run=False):
    for path, dirs, files in os.walk(pylib_path):
        for filename in files:
            full_path = full_path = os.path.join(path, filename)
            is_executable, file_output = check_is_executable(full_path)
            if is_executable:
                extension = os.path.splitext(full_path)[1].lower()
                if extension == '.py' or extension == '.pym' or filename == 'command_template':
                    if dry_run:
                        print '### Executable found: %s' % (filename,)
                    else:
                        print 'Fixing %s...' % (filename,)
                        fixed = fix_executable(full_path)
                        if not fixed:
                            print '### FIXING %s FAILED' % (full_path,)
                        else:
                            print 'Fixed'
                else:
                    print '### Executable found, but does not seem to be Python code: %s' % (full_path,)

if __name__ == '__main__':
    fix_pylib(pylib_path1)
    fix_pylib(pylib_path2)
mrcoxall

@omz Thanks so much for getting back to me.
I will give it a try and see what happens.

By any chance do you have an update to the GitHub repo with the changes already made to the pylib and pylib_ext, so that I do not have to run the scrip and change anything?

Thanks again, Patrick

polymerchm

Trying to run my app via xcode and the current template. How do you force it to run the Python 3 interpretor?

mrcoxall

@omz I have used your script and changed all the files in pylib and pylib_ext. I even placed the header at the top of the files in "scripts". It still compiles OK to simulator and devices but I am still getting a code signing error.

error screenshot

Any ideas?
Here is my fork with the fix: https://github.com/Mr-Coxall/PythonistaAppTemplate

omz

@mrcoxall It looks like you're submitting the app directly from the Xcode organizer? Try exporting the archive first ("for App Store deployment"), and then submit it using the Application Loader tool (right-click Xcode in Dock -> Open Developer Tool...). Not sure if this will actually fix the error, but I've seen similar problems in the past that only happened with Xcode, and not with Application Loader.

polymerchm

@omz Based on my experiments, am I correct in assuming that the template only has the 2.7 interpretor? Any hope the the 3.5/3.6 template will be forthcoming? I am learning swift just in case.

mrcoxall

@omz I tried as you suggest and used the Application Loader. Same problem happening. Still getting code signing errors. Have tried using "Auto code signing" and even old school downloading the certificate myself and still getting the same messages.
Have you been able to get anything uploaded to the App Store?
Do you have a template that I could try?

Thanks

mrcoxall

Wondering if anyone has been able to submit an app successfully since Jan 1, 2017.
I still am getting signing errors and have no workaround that will work.
I have app waiting to get approved and need a solution.

Thanks

JonB

Have you tried the recommendations here?
http://stackoverflow.com/questions/39889093/itunes-software-service-authentication-error-domain-error-434

kyelewis

I know this is an older thread, but I just wanted to confirm that with the texinfo fix, I have successfully submitted and had an app approved in the last few days.

So the fix is required to get past the automatic filter, but submission is OK with the workaround.

marcus67

@omz Getting back to the question of @polymerchm : Is it possible to run python3 in Xcode? Using a she-bang line like "#! python3" does not work. sys.version still returns "2.7.5 (default, Feb 15 2016, 15:15:36)". Thanks!

omz

@marcus67 It's currently not possible, I'm afraid.

mrcoxall

@omz Thanks for getting back to me.

I was wondering if there is any explanation on why it is no longer possible?
I used Pythonista last year with my grade 11 programming course and got over a dozen apps published on the App Store. I have just started using it again with this years group and told them we will be doing the same thing. If there is anything I can do to help the process along, please let me know. We will not be starting to write the final apps until December.

Thanks

JonB

Someone just posted that they got an app approved....

JonB

@mrcoxall Did youthe texinfo trick? Sounds like @kyelewis got something submitted in january or february.

TheRealBret

@JonB The texinfo trick continues to work. Had an app accepted just last week.

ccc

Would it be possible to create a repo or a page on Pythonista-Tools that could be a FAQ for using the template? It seems like there are several prereqs and then several steps to complete the process and it would be great to have a landing page for sharing all that tribal knowledge.

TheRealBret

I spoke too soon. I had to upgrade Xcode because of iOS11 compatibility, and now I'm back to getting the code signing errors for all the .py files, even if they have the texinfo header. Building apps for local distribution works fine, I just can't sign the code as part of the validation process for the App Store.

TheRealBret

Looks like the texinfo hack needs to be modified. The code signing process uses file(1) to check the type of file in the package, and file(1) identifies executable code by checking against different file types and scoring each file type. Apple modified the matching "magic" for python to look for python keywords like "def", "import", "try", "except", etc and each use gives a higher score to python. So for the tex info hack to work, it needs to occur more frequently than the python keywords. Some files just need a single texinfo line; other files need 400+ copies of the texinfo line (some of the python checks only examine the first 4096 characters of the file). Its easy to modify the script above to accomplish this, but hardly elegant.

Hopefully somebody will find this useful and find a simple fix.... like perhaps there's another file type that short-circuits the checking magic? Also, the Apple developer documentation say that script files could go into a specially named subfolder, which would be much simpler, but I've haven't gotten this to work.

JonB

out of curiosity, is file used locally, or on the server?
Couldn't you use th older file version for identifying text files?

jumpbeen

@JonB said:

out of curiosity, is file used locally, or on the server?

Yes, It's locally.
@TheRealBret
You can replace older version of 'usr/bin/file' and 'usr/share/file' to fix it, if your mac os version has updated to 10.13.

TheRealBret

Thanks. Will give it a try and test an upload to TestFlight too.

sreyemnayr

Here's the re-worked script, which throws as many of those dummies at the top of each file as it needs to stop the madness.

EDIT: There are some problems with this method as well, as it bounces the lines indicating the encoding style, which breaks a bunch of stuff... I ended up having to regex replace them back to the top, but will work this script out to do it better later. Just be aware that this will happen!

```

Change these:

pylib_path1 = '/path/to/PythonistaKit.framework/pylib'
pylib_path2 = '/path/to/PythonistaKit.framework/pylib_ext'

import shutil
import os
import subprocess

def check_is_executable(file_path):
file_output = subprocess.check_output(['file', file_path])
if 'executable' in file_output:
return True, file_output
return False, file_output

def fix_executable(file_path):
with open(file_path, 'r') as f:
source = f.read()
with open(file_path, 'w') as f:
f.write('#\input texinfo\n' + source)
is_executable, out = check_is_executable(file_path)
return not is_executable

def fix_pylib(pylib_path, dry_run=False):
for path, dirs, files in os.walk(pylib_path):
for filename in files:
full_path = full_path = os.path.join(path, filename)
is_executable, file_output = check_is_executable(full_path)
if is_executable:
extension = os.path.splitext(full_path)[1].lower()
if extension == '.py' or extension == '.pym' or filename == 'command_template':
if dry_run:
print '### Executable found: %s' % (filename,)
else:
print 'Fixing %s...' % (filename,)
fixed = False
counter = 0
while not fixed:
fixed = fix_executable(full_path)
counter = counter + 1

                    print 'Fixed with '+str(counter)+' dummy lines.'
            else:
                print '### Executable found, but does not seem to be Python code: %s' % (full_path,)

if name == 'main':
fix_pylib(pylib_path1)
fix_pylib(pylib_path2)```

peterdougstuart

Hi @sreyemnayr, just tried your script, but still getting an error on upload to app store. Any other ideas or refinements to your script?

peterdougstuart

I'm making a bit of progress:
- My original error related to the future.py file in pylib, after running the script the Xcode error changed.
- I noticed that after running the above script the specific file that I was getting the 'Invalid Signature' error on had change to pylib/compiler/init.py. I had a look at that file and it didn't have a #\input texinfo up the top so I added it manually.
- I then reran the script and the error changed to pylib/compiler/ast.py This did have lots of #\input texinfo, so I copy and pasted all of them to double the amount of #\input texinfo lines at the top of the file. This seemed to satisfy Xcode.
- I then reran the script and the error changed one of the files in pylib/ctypes/test. I just deleted the whole pylib/ctypes/test folder.
- I than reran the script and the error changed to pylib/dateutil/READEME. I deleted the README file and the NEWS file while I was at it.
- I than reran the script and the error changes to pylib/site-packages/dropbox/init.py. As I'm not using dropbox in my app I just deleted the dropbox folder.
- I then had errors on pylib/site-packages/twitter.py, webbrowser.py, xmltodict.py and ui.py. They all had just one #\input texinfo line so I inserted an extra 1000 #\input texinfo lines at the top of each.
- I then had remaining errors in the files in pylib_ext/ so I added about #\input texinfo lines at the top of each.
- Finally my app submitted successfully!!!!

I must confess I really don't understand all of this. Feels like there's got to be a better way....

Thanks to @sreyemnayr for posting the script as I would not have solved this without it.

RomSpy

@peterdougstuart any chance you would be willing to share your updated template?

ccc

@sreyemnayr could you please update your script to work in Python 3?

ccc
if extension == '.py' or extension == '.pym'
# can be shortened to:
if extension in ('.py', '.pym')
peterdougstuart

Sorry for delay responding....

Happy to share @RomSpy, but please note that my templates have been minimized to my project i.e. deleted lots of modules I'm not using. Therefore it may not work for your project. You might be better off following the principles of steps I outlined above.

If you are still interested in my templates can you send me a PM on twitter (same handle as here) and I'll send you a zip or something. Alternatively point me to somewhere I can upload the files and I'll do so.

RomSpy

@peterdougstuart thank you for the offer. I ended up doing what you did and removing everything I wasn't using and then running the script above. I was able to successfully update my app in the store using that method in addition to your added steps. Thanks again.

xino386

@peterdougstuart
Hi, i am interested in your templates which is submitted to itunesConnect successfully, can you send me a zip ?

peterdougstuart

Hi @xino386 can you PM on twitter and I’ll send you a zip of my scripts (same handle as here). Note that my scripts have been trimmed down to match the subset of the libraries used in my app so you might be better off following the steps above to get it to work.

stepper

@omz
I have a succes storey with your fix script (June 19/18). Here’s what I did. Pasted approx 400 #\input texinfo ‘s into a text file. Pasted the contents (all one line, no line breaks) into your script as a string (replacing the existing ‘#\input texinfo’. Changed the folder permissions for the two lib folders to read/write (temporarily).ran your script. It fixed all but a half dozen of the files. Went into the folders manually. The unchanged files stood out cause they didn’t have today’s date of modification. Manually pasted in the approx 400 from the original text file into those few.
Successfully uploaded to app connect where my app is now in Beta on test flight.
Thank You very much!

omz

@stepper That's interesting, though I've found a better solution recently: You can add something like #import pythonista as the first line, and it'll be recognized as Objective-C source code (which isn't directly executable, so it doesn't cause issues with code signing).

RomSpy

@omz
Any chance we will see an updated template that uses all the great new features in version 3?

omz

@RomSpy Yes, that's something I'd really like to do soon, and I've already done some of the work required, but it's still kind of a mess.

bg2b

Is there an up-to-date summary of the idea for packaging up a Pythonista project to make an app? I see that the template linked from

https://forum.omz-software.com/topic/1911/new-xcode-template-beta

doesn't exist anymore, and I'm not sure where to begin learning.

yueqiw

@sreyemnayr I tried your re-worked script and it worked well.
I used #import pythonista\n rather than #\input texinfo\n
To make it run faster I prepend 10 strings in each iteration, e.g.f.write("#import pythonista\n" * 10 + source) and set counter to increment by 10.

amdescombes

Hello everyone,

Here is a reworked script that adds the comments at the top but preservers coding= comments.
It is not perfect, but it helped me succesfully submit an app to the Appstore, I hope it is of help to every one.

#import pythonista
# Change the ********** to point to the directory containing the Pythonista framework :
project_path = '**********/PythonistaAppTemplate'
pylib_path1 = '%s/PythonistaKit.framework/pylib' % project_path
pylib_path2 = '%s/PythonistaKit.framework/pylib_ext' % project_path
MAX_REPEATS = 10

import shutil
import os
import subprocess

def check_is_executable(file_path):
    file_output = subprocess.check_output(['file', file_path])
    if 'executable' in file_output:
        return True, file_output
    return False, file_output

def fix_executable(file_path, dry_run=False):
    with open(file_path, 'r') as f:
        source = f.readlines()
        if 'coding:' in source[0].lower():
            firstline = source[0]
            start = 1
        else:
            firstline = ''
            start = 0
    if dry_run:
        if firstline:
            print(firstline)
    else:
        with open(file_path, 'w') as f:
            f.write(firstline + '#import pythonista\n' * MAX_REPEATS + ''.join(source[start:]))
    is_executable, out = check_is_executable(file_path)
    return not is_executable

def fix_pylib(pylib_path, dry_run=False):
    print ("fixing", pylib_path)
    for path, dirs, files in os.walk(pylib_path):
        print(path, dirs, files)
        for filename in files:
            full_path = full_path = os.path.join(path, filename)
            is_executable, file_output = check_is_executable(full_path)
            if is_executable:
                extension = os.path.splitext(full_path)[1].lower()
                if extension in ['.py', '.pym'] or filename == 'command_template':
                    if dry_run:
                        print '### Executable found: %s' % (filename,)
                        fixed = fix_executable(full_path, dry_run)
                    else:
                        print 'Fixing %s...' % (filename,)
                        fixed = False
                        counter = 0
                        while not fixed:
                            fixed = fix_executable(full_path)
                            counter += MAX_REPEATS

                        print 'Fixed with '+str(counter)+' dummy lines.'
                else:
                    print '### Executable found, but does not seem to be Python code: %s' % (full_path,)

if __name__ == '__main__':
    fix_pylib(pylib_path1, False)
    fix_pylib(pylib_path2, False)

Cheers
Andre

JonB

so, this may be a stupid question, but my understanding of this problem is that file is running locally, and is getting rejected locally.

so, why not just edit /usr/share/file/magic (or copy it, edit it, then file -C to compile it to a new .mgc), or create an alias to file with a -m argument pointing to your custom magic file. It should be possible to edit the entry for pythonm or add custom search for the shebang or coding lines, to simply output a safe mimetype,

amdescombes

Hi Jon,

I think that is a very good question and a very interesting option to explore as it would avoid modifying the framework. I'll look into it as soon as I get a chance and report my findings back.

Cheers
Andre

TheRealBret

I really want to have a new Xcode template for Pythonista 3. I realize that I've already bought Pythonista so I'm not generating new income for @omz.... so I hereby pledge to send money via Paypal/Zelle (or any other method) to @omz to help support his time for the production of a new Xcode template. I'd gladly pay $25 for a new template. I'd even pay this annually if it would be updated regularly.

Thoughts anyone? @omz?? How can we help get a new Xcode template made?

vignesh

@TheRealBret Good news!
@omz said:

Here's a first attempt at a Python 3-based Xcode template: https://www.dropbox.com/s/5l94m0xjbot5je0/Pythonista3AppTemplate.zip?dl=1

This is roughly equivalent to the current App Store version (not the 3.3 beta), and not final, just something to play around with for people interested in the Xcode template. Let me know if anything's unclear.

TheRealBret

Indeed - I’m very happy to see the new template. Thank you!

My offer still stands - I would like a way to give a donation to @omz to help offset continued development of Pythonista. I can’t see how my payment a year ago is helping today.

vignesh

Is it possible for someone to upload a version of the template for python3 with the fix to include the line at the top of all the files already done? I am having lots of trouble doing it myself.

ruohola

Any update on the template? As of April 2020 the template is completely broken since it uses the deprecated UIWebView API which is not allowed anymore: https://forum.omz-software.com/topic/6474/python3-xcode-template-broken-because-of-deprecated-uiwebview

JonB

Is the binary signed in some way? I wonder if you were to edit it in a hex editor, and replace UIWebView with some other nonsense class name (same number of characters).
Since objc is message based, there is nothing linked to support UIWebView, just a runtime call with a c string with the classname. As long as you never instantiate a webview, things won't crash.

eliotradisa

@TheRealBret said:
- I’m very happy to see the new template. Thank you!

My offer still stands - I would like a way to give a donation to @omz to help offset continued development of Pythonista. I can’t see how my payment a year ago is helping today.

The texinfo trick continues to work. Had an app accepted just last week.

eliotradisa

I think that is a very good https://jpgtopdf.onl/question and a very interesting option to explore as it would avoid modifying the framework. I'll look into it as soon as I get a https://1921681001.id/ https://19216811.cam/ (192.168.100.1) chance and report my findings back.

coltonboyd

@ruohola sorry this is a little late and I hope this information is still relevant for you. I took @JonB 's advice and went into the P3kit framework and edited the P3kit file. For me it popped up as a unix executable, so I needed to download a hex editor to go in and modify it.

All I did was command-F and find all the instances of UIWebView and replace them all with UIBarItem. This is an API with the same character length and the API isn't deprecated. Save the file and make sure it is still in your project directory.

I archived and uploaded my build last night and the App Store did not reject the build. so this is a good working solution. My app is a 2D shooting game called Flyboy Adventure Game and it is currently under beta review as we speak. I've tested my game on Testflight and it works great, so hopefully there is no long term repercussions from using this workaround.

mikael

@coltonboyd, thanks for sharing, this is great news. I am (again) tempted to put something to the App Store.

coltonboyd

@mikael

Of course, just for reference the Hex editor I used was SlickEditPro2019. You can download a free trial and it’s pretty easy to use.

I’m currently trying to upload a updated Pythonista 3 Template to my Dropbox but it’s taking forever.

JonB

@coltonboyd It might be good if you could document the various steps you went through from start to end -- for instance did you have to do the workaround so file doesn't flag .py files as executable? Anything else you had to modify from the template?

coltonboyd

@JonB I’m glad you mentioned that. I forgot to inform that to get past signing errors I used @RomSpy ’s last template he posted from this forum link:

https://forum.omz-software.com/topic/5837/xcode-template

After getting past the signing errors is when I started getting the UIWebView deprecated rejections from Apple. That is when I stumbled upon this forum post and tried out your idea of downloading the hex editor, etc. I first tried replacing UIWebView with WKWebView like Apple suggested, but it ended up crashing my app after launch. Replacing it with UIBarItem had no effect.

Here is my latest version of the Pythonista 3 App Template that I used for my game I’m currently publishing to the App Store as we speak.

https://www.dropbox.com/s/442v3cp90oyk8rd/Pythonista3AppTemplate%20Updated%20.zip?dl=0

vovaburm

@coltonboyd said:

Thanks! But it seems that you upload version with WKWebView. I changed that to UIBarItem and it worked

coltonboyd

@vovaburm oops I must have uploaded the wrong version then off my desktop, my bad! I’m glad you got it to work!

coltonboyd

To anybody that needs it, here is the correct and updated Pythonista 3 Template:

https://www.dropbox.com/h?preview=Pythonista3AppTemplate+Updated+.zip

Ichicoro

@coltonboyd the last link you posted doesn't work :(

ltddev

Yes, @coltonboyd, I too cannot access this link but I would very much like to use your Python 3 Pythonista 3 template for Xcode. Could you please post a corrected link?

coltonboyd

@Ichicoro lol I hate myself. This should work, let me know if it doesn’t.

https://www.dropbox.com/s/nq899u5gv54o5t8/Pythonista3AppTemplate%20Updated%20.zip?dl=0

ritanari31

@kyelewis said:

I have successfully submitted and had an app approved in the last few days.

I have successfully submitted and had an app approved in the last few days.

Gibberish

Can someone please repost the template? That link doesn’t seem to be valid.

Thanks!

dustlancer

@coltonboyd invalid link😭😭😭 will you update please?🥺🥺

bosco

I believe this is a copy of the last XCode Template modified by @coltonboyd. I have only used it to run the simulator with the latest version of XCode. It throws some warnings, but works for testing.
https://1drv.ms/u/s!ArOye-9ij7iY2GkveJR7rZmN9eS-?e=b37KZi

ccc

@bosco Can you please post the template on GitHub or Dropbox or some more trustable URL.

Given that your last activity on the forum was 3 years ago, I am a bit worried that we trust a cryptic URL.

bosco

@ccc This link is for Microsoft OneDrive. My Dropbox space is limited.

The original link is a more permanent and reliable alias to this URL.

https://onedrive.live.com/?authkey=%21AC94lHutmY315L4&id=98B88F62EF7BB2B3%21125&cid=98B88F62EF7BB2B3