Beta Status Update
Unfortunately, I've recently been unable to provide a new beta version of Pythonista 1.6. This is partly my own fault, and partly due to unexpected difficulties with TestFlight.
First off, I've been working on two different branches of Pythonista for quite some time, one being the current (expired) 1.6 beta, a relatively minor update with new Python modules but not much else, the other a more significant update with a major UI refresh and quite a few other new features that I'm pretty excited about (more on that soon).
This approach has sometimes made it difficult to keep both versions in a working state. When I changed something in version B, I sometimes ended up accidentally breaking stuff in version A... So a couple of weeks ago, I decided to ditch the current beta branch, and exclusively focus on the new version instead, but I have to admit that I vastly underestimated the amount of work that this would take – a lot of basic things were still missing in the new branch, and even though it had some nice new features, it would have been a step down in terms of stability and basic functionality that you'd expect, even if you were coming from 1.5.
Right now, it's still a bit rough around the edges, but definitely usable and an improvement over the current version. Unfortunately, I haven't been able to get TestFlight to work with it yet. I continue running into server-side issues with builds not processing properly after I upload them. In order to make some new features work, I had to change the App ID (for code-signing), and it seems that this is a scenario that just doesn't work very well with TestFlight – it's difficult to go back now because that would mean sacrificing new functionality that I spent quite a lot of time on... At first, the only reason for the new App ID requirement was the document picker support in the new
dialogsmodule (requires iCloud entitlements), but the new version also contains an app extension (for running scripts from the share sheet in other apps), and I've realized now that this also doesn't work with the old App ID, and while the document picker support wasn't that important to me, the app extension is a major feature that I really want to ship.
If you do have the current (expired) beta installed and would like to get your data out of it, here are two options you can use:
Option 1 (if you have a Mac with Xcode):
- Connect your device via USB
- Start Xcode and select Devices from the Window menu, then select the connected device in the sidebar
- Under Installed Apps, select Pythonista
- Click on the "Gear" icon and select Download Container...
The downloaded container is a package (i.e. folder), so you can view the individual files in Finder by selecting Show Package Contents from the context menu.
Option 2 (if you're on a PC or don't want to install Xcode):
- Make an unencrypted(!) backup of your device using iTunes
- Download the iBackup Viewer tool (Mac or Windows) – (the free version will do, if you have the paid version, you could also encrypt your backup)
- Go to "(your device)/Applications" (this may take a while to load)
- Select Pythonista in the list of apps, then click the "gear" button and select Save all Files.... I would recommend that you create a new folder for this because the app will create multiple folders while extracting the backup files.
Edit: You can also try downgrading by downloading 1.5 from the App Store. Apparently, this didn't result in data loss for some people, but I'm not quite sure if this always works.
That's all I have for now. I'm very sorry this took so long. When I know more, I'll post it here.
@JonB here is the code I'm using now, have restarted Pythonista many times and can't think of any other changes I've made other than removing
light.alpha = 1:
# coding: utf-8 import sk import random MAXSPD = 700 MAXLIFE = 10 TEXTURE = 'shp:Circle' MINLIFED = -120 MAXLIFED = 120 SCALE = 2 decayrate = 0.005 collider_f = 0.3 def randvec(maxspd): return (random.randint(-maxspd, maxspd), random.randint(-maxspd, maxspd)) particle_tpl = sk.SpriteNode(sk.Texture(TEXTURE)) particle_tpl.name = 'particle' particle_tpl.color_blend_factor = 1 particle_tpl.age = 0 particle_tpl.lighting_bit_mask = 1 particle_tpl.x_scale = SCALE particle_tpl.y_scale = SCALE particle_tpl.alpha = 1 particle_tpl.shadow_cast_bit_mask = 1 physics = sk.PhysicsBody.circle(particle_tpl.size.x/2 * collider_f) physics.restitution = 1.2 physics.affected_by_gravity = False physics.allows_rotation = True physics.mass = 0.3 physics.pinned = False physics.angular_velocity = 0 physics.category_bit_mask = 1 physics.contact_test_bit_mask = 1 particle_tpl.physics_body = physics class Game (sk.Scene): def __init__(self): sk.Scene.__init__(self) self.name = 'scene' self.img = sk.Texture(TEXTURE) self.maxspd = MAXSPD self.handles_node_touches = False self.maxlife = MAXLIFE * 60 # convert to frames self.background_color = (0, 0, 0) self.lighting_bit_mask = 1 # init walls walls = sk.Node() walls.position = (0, 0) physics = sk.PhysicsBody.edge_loop_rect(0, 0, 1024, 768) physics.dynamic = False physics.restitution = 1.1 walls.physics_body = physics self.add_child(walls) # lighting light = sk.LightNode() light.position = (10, 758) light.shadow_color = (1, 0, 0) light.ambient_color = (0, 0, 1) light.light_color = (0, 1, 0) light.enabled = True light.category_bit_mask = 1 light.falloff = 1 light.name = 'light' self.add_child(light) def update(self): for p in self['particle']: p.age += 1 if p.age >= p.lifespan: # if exceeded life, reduce alpha by 1 p.alpha -= decayrate if p.alpha <= 0: p.run_action(sk.Action.call(p.remove_from_parent)) def touch_began(self, node, touch): self.selected = None new = particle_tpl.__copy__() new.physics_body = new.physics_body.__copy__() new.lighting_bit_mask = 1 new.position = touch.location new.physics_body.velocity = randvec(MAXSPD) new.color = (random.random(), random.random(), random.random()) new.lifespan = self.maxlife + random.randint(MINLIFED, MAXLIFED) new.alpha = 1 self.add_child(new) def touch_moved(self, node, touch): self.touch_began(node, touch) def did_begin_contact(self, collison): if collison.body_a.node.name == 'particle' and collison.body_b.node.name == 'particle': collison.body_a.node.color = (random.random(), random.random(), random.random()) collison.body_b.node.color = (random.random(), random.random(), random.random()) def main(): game = Game() scene_view = sk.View(game) scene_view.shows_fps = True scene_view.shows_node_count = True scene_view.present() return game if __name__ == '__main__': g = main()
However, it still just gives me a black screen. As before, when I touch the screen the node count goes up but I cannot see anything.
I can see the balls appear just fine with your code on ios 8.2 on ipad2. For the platformer game I had a similar problem which was solved by rotating the display. You might try running it, then rotating the device so that it tries to resize.
The code above works for me.
Not sure if this is a bug or an odd feature, but Pythonista strips all whitespace (including trailing newlines) from the end of a file when it is saved. This only becomes apparent when closing the editor tab for that file or restarting the app. If this is intentional, it would be nice if this were optional.
In the beta release
ui.View().present(orientations=['landsacpe'])is not forcing the view to display in landscape mode. It is just me or are others seeing the same behavior?
Can somebody among the beta users tell me whether the extensions can be made to handle files (e.g., Mail attachments) in a way that was possible with Open In?
The scenario I used in the days of Open In was this: I have an email attachment of specific type (e.g., .txt), I open it in Pythonista, the Open In handler then performs some automated actions (in my case, uploads it via SCP and then runs several commands on the remote server). Can this be done with the extensions now? Should I wait for the new release or try and find other ways to do this?
That's exactly what the extensions let you do.
How can I sign up for the test flight beta? I want to try it, looks AMAZING.
Modules that are in site-packages are not importable when in the app extension. Is this expected behavior?
The extension runs in its own sandbox.. As I recall there was an extensions site packages? You have to separately install packages to both locations.