TweetFollow Us on Twitter

Python For AppleScripters

Volume Number: 20 (2004)
Issue Number: 11
Column Tag: Programming

Python For AppleScripters

by Ryan Wilcox

Introduction By Comparison

A Tale of Two Languages

The advent of OS X brought with it a wealth (some might say invasion) of tools from the Unix world: the command shells, grep, sed, ls, cat, less, vi, emacs — all these utilities and countless others. It also brought with it programming languages — probably the most popular one being Perl. OS X 10.2, however, added to its repertoire a scripting language called Python.

Introduction

Python is easy to use, simple, powerful, and chock-full of great modules (similar to AppleScripts you load via the load script command). The design of the language "just makes sense," the modules are well thought out, and best of all the language has many similarities to AppleScript. Every day it seems I find more uses for Python than I could have imagined. I use Python along with BBEdit to automate all sorts of common text-based tasks: I have scripts to help me resolve CVS conflicts, to convert decimal to hexadecimal (and back), to encode selected text into URL encoded format and more. Python's readable structure and multitude of included modules lends itself to quick one-off utilities, often with less pain than a similar AppleScript - at least in this author's opinion. In this article I'll discuss how Python and AppleScript are similar, and how they differ. Then we'll walk through an example script in both languages. Finally, I'll conclude showing how you can use Python and AppleScript simultaneously in your projects.

AppleScript and Python share many similar traits

Looking at a Python script should be a vaguely familiar experience for an AppleScripter - the same indented flow, and understandable syntax. When you are creating a Python script you often try out little chunks of code first, make sure they work, then put them in a larger whole - just like you might when adding code to an AppleScript. Let's tackle these similarities in more detail:

Whitespace matters

In AppleScript whitespace is automatically added by the compiler so that nested commands (such as those in an if, repeat, try, tell, etc) are always indented properly. In Python whitespace is also important - in fact whitespace tells the compiler that a line or block of code is nested. When the indentation stops, the block of code has ended. Contrast this to AppleScript's approach, where blocks of code are ended with end statements. The key difference with Python is that it does not automatically add whitespace as AppleScript does. This isn't as much of an issues as it sounds, as most text editors auto-indent when you type a return. It's worth mentioning here that statements that mark a block of code (such as for loops, if statements, and even functions) require a colon at the end of the "parent" line. The sample script presented later in the article shows several indented blocks of code.

Having whitespace matter is both a good thing and a bad thing. The good news: every Python script you run into will have a similar style, indentation-wise. The bad news: the compiler will complain if you mix spaces and tabs to indent, and it's annoying to have to debug something you can't see. For this reason using a text editor that can Show Invisibles is so very important(maybe even a requirement) while programming in Python. As a sidenote, in cross-platform scripts, using 4 spaces to indent is recommended over using a tab, as spaces are not so easily mangled by unsavvy text editors.

"simple" syntax

Python's syntax is very straightforward, and often compared to pseudo-code. For contrast, look at the sample script later in this article, implemented first in AppleScript, then in Python. The Python version, while it is not as readable as the near-English AppleScript, reads like English plus a bit of 8th grade algebra. AppleScript's approach of English-Like-Syntax-Wherever-Possible often results in extra typing. Compare if you will AppleScript's:

 set end of myList to "the end" 
to Python's:
myList.append("the end").

Python is not AppleScript

or some, the apparent similarity stops there. Python brings its own unique flavor to the language party, differing from AppleScript in some key areas: cross-platformness, case sensitivity, and Python's (significantly) different approach to types are some of what make Python a unique scripting language when compared to AppleScript.

Python is Cross-Platform

Python runs on most major platforms - both flavors of Mac OS, Windows, Linux, Unix, even the PalmOS. Much of Python's functionality knows what platform a script is currently running under, and adjusts platform specific things. For example, the linesep attribute of the os module will return the line separator character(s) for the current platform. There are certain times when you want to use a platform specific API, and that's perfectly acceptable as well. One Python rule of thumb is "We're all consenting adults here," meaning that the language won't try to prevent you from doing something potentially "naughty" if you want to.

Case Matters

In AppleScript, the compiler changes the case of a variable to be the same as the first instance of that variable. So, while case matters, the compiler takes care of it for you. In Python case also matters, except there is no automatic correction - what you type is what you get.

What do you contain? Types Matter

As any experienced scripter knows, AppleScript plays fast-and-loose with type. Sometimes you can't be sure exactly what you will get back. This has its advantages as well as its disadvantages. Take this line of AppleScript for example:

 set firstNum to "1"
 set testVar to firstNum + 1 

If you know that firstNum can always be converted into number, this works great - it saves everybody some typing. But here's the puzzle: what is testVar? Is it a string? A number? Without a specific declaration, AppleScript will automatically coerce all of the values to the same type, but the question still remains: what type of object will you end up with? (To those of you who answered that the result will be a number, go to the head of the class.) However, as scripts grow in complexity, being explicit regarding what type a variable is becomes essential - you end up almost fighting the implicit coercion you used (and loved) with your smaller script.

With Python, there is no implicit coercion - instead, variables have a very strict sense about what type they are, and what they can do. (For those of you versed in programming terminology, Python is dynamically, but strongly, typed. You can create a variable without caring what type it will be, but Python keeps track of what kind of data that variable currently has in it. Here is that same sample in Python:

 testVar = int("1") + 1

This is how Python does coercion - instead of AppleScript's as xxxxx notation, Python uses xxxx(), as C/C++ does. Trying to run "1" + 1 in python will give a runtime error, as you can not concatenate 'str' and 'int' objects. Python has no idea what to do (it could do two things: cast "1" to an integer, or cast 1 to a string. One answer will result in 2, while the other gives "11"). One of the guidelines (Zens) of Python says: "When faced with ambiguity, resist the temptation to guess." The "Zens of Python" guide both the development of Python as a language and provide a good framework for writing your own scripts and modules. To read more about the culture of Python, and the Zen/Design Principles of Python, visit the following URL:


http: //www.python.org/dev/culture.html


Batteries Included

Like AppleScript, Python has a small core language, while external modules provide additional functionality. In AppleScript, these external modules come in the form of Scripting Additions and Scriptable Applications (created by Apple and third parties). There are a few Scripting Additions that come preinstalled with every Mac OS installation (Standard Additions, URL Access Scripting, Image Capture Scripting, among others), and several of the apps that come preinstalled are scriptable. All Scriptable Applications and Scripting Additions are written in languages like C/C++ or Objective-C. In Python the focus is not so much on applications as it is on modules - collections of Python routines or objects, usually written in Python, that perform certain tasks. These modules are similar in style to AppleScript's script libraries. While some Python modules include C/C++ code, these seem to be the exception, rather than the rule. Python comes with a huge collection of modules called the Standard Library, so instead of asking the Finder for the size of a file, you would call a function in the Standard Library.

It's in the __doc__s

In AppleScript, there is always some human readable documentation: the dictionary of the application or scripting addition. Sometimes the dictionary is not enough but it is always there, on your machine. When I am writing AppleScript, I always have at least one or two dictionaries open, referring to them as I write my script, like a cheat-sheet right there on my desktop.

Python, on the other hand, takes more of a "reference book" approach to documentation - it is available in a number of different formats, (downloadable from http://python.org), but like any reference book, you hope the documentation is up to date, complete, and that it describes the method you want to use. There have been several utilities written to reduce the risk of these mistakes in the documentation happening, and the Python documentation is usually of high quality. Still, the possibility of out of date documentation exists. The Mac Python IDE includes a module browser, letting you explore different modules like you do an AppleScript dictionary, but it's often not as helpful. As mentioned before, most Python modules are coded in Python itself, and you can usually view the source code for a module, trying to figure out what a function actually does.

The standard Python practice is to add a string literal describing the function and parameters it takes as the first line of the function. This string is called a "docstring." If you view a module in the Mac Python IDE's Module Browser, this string will be described as __doc__ (pronounced "under under doc under under") - however this __doc__ string is what is rendered for the documentation - meaning that if the documentation is poor, the __doc__ will probably be as well.

Here's an example of a function with a docstring. But first it is also important to note Python's string literal functionality. If you have a character in a string literal that you would ordinarily have to escape, for example a quote character, you can instead triple-quote the string literal - the string is considered everything enclosed in triple quotes ("""I'm in triple quotes""", for example, is a perfectly valid string literal.)

def addValues(value1, value2): 
  """addValues adds two numbers. Simple. value1 is 
  the first value to add, value2 is the second. Returns 
  these two values added together"""
  return (value1 + value2) 

This standard practice is a great practice to adopt for your own methods. Adopting this documentation convention will help you remember what a function does, why you need it, and what the parameters do when you revisit the function at a later date. AppleScript is without such a standard practice; everybody has their own styles of documenting an AppleScript method, if they do it at all.

An IDE and an example: Kicking the tires

Python makes a great multi-purpose language. Internally we use it from everything from creating shell programs, to making BBEdit Unix filters, creating throw-away one-time scripts, or designing custom CGI scripts for our clients. You can even use Python in conjunction with Apple's Cocoa application framework using PyObjC. With some additional modules, you can use Python just like you would AppleScript - to display simple GUIs, talk to other applications, and do other user administration tasks.

Starting at the beginning: Installing a GUI friendly Python

While you can use Python on the command line, the command line program gives you everything you would expect from a Unix based tool: no GUI capabilities, no IDE and no graphical debugger. In short, it's not the best environment for Mac people who are used to such niceties.

In the pre-OS X days, a Mac OS 9 version of Python, including an IDE, was provided by Jack Jansen. The IDE and all the Mac specific modules from those days still work under OS X, but their appearance has not been updated for OS X. Those looking for prettier IDEs on OS X shouldn't fret - there are several that show promise, but as of this writing most are still in the early stages of development.

You can download the MacPython package at


http://homepages.cwi.nl/ ~jack/macpython/

This package will install the PythonIDE application (found in your Applications/MacPython-2.3 folder) along with some other things. Double click on the Python IDE and you should get something similar to this:


Figure 1.

Got it? Does it look something like this? Good. Let's go to work.

A simple illustration, line by line

Let's start things off with a simple example - a script that accepts user input and appends it to a file. It should be noted here that simple AppleScript display dialog like interfaces aren't Python's strong suit. While the MacPython package helps, it's still not as easy as AppleScript's display dialog. This (and inter-application communication) are two of the things that Python does poorly, however there are two packages currently competing to become the de facto standard for inter-application communication in Python, so the tide (at least on that front) should turn rather quickly.

First, the AppleScript:

set filepath to choose file with prompt "select a file to append to"
set fileRef to open for access filepath with write permission 
repeat 
 set dialogResult to display dialog "enter a line" default answer "line" buttons -
  {"No More", "Enter"} default button 2 
 

 if button returned of dialogResult is "Enter" then 
  set textReturned to text returned of dialogResult 
  write textReturned & return to fileRef 
 else 
  exit repeat 
 end if 
end repeat 
close access fileRef 
Now, the Python: 
import EasyDialogs, os 


filepath = EasyDialogs.AskFileForOpen("select a file to append to") 


if filepath: 
 fileRef = open(filepath, 'w') 
 while True: 
  textReturned = EasyDialogs.AskString( 
   prompt = "enter a line", default = "line", 
   ok="Enter", cancel = "No more") 
  if textReturned: 
   fileRef.write(textReturned + os.linesep) 
  else: 
   break 
 fileRef.close() 

Let's take the Python sample line by line:

import EasyDialogs, os

As mentioned before, Python organizes sets of functionality into modules. Import loads these modules into your script. Here we import both the EasyDialogs module (a Mac specific module) and the cross-platform os module.

filepath = EasyDialogs.AskFileForOpen("file to append 
 to please")

This line calls the AskFileForOpen method in the EasyDialogs module, which will ask the user to select a file. By comparison, AppleScript searches all of the installed scripting additions for you, looking for the command, and sometimes it "helpfully" finds the wrong one. This is what often causes a terminology conflict. If AppleScript required you to specify where to get the terminology from, you might have to write something like set filepath to standard addition's choose file which may be more typing, but would remove any potential ambiguity. Sadly, AppleScript does not support this style of reference.

 if filepath:

In AppleScript, if the user presses cancel in a choose file dialog, AppleScript raises an error and terminates the script (unless you handle the error in an on error block). Python's AskFileForOpen function does no such thing - it just returns None and keeps on executing the script. We must explicitly test the value of filepath for its existence (filepath would be None if the user pressed the "Cancel" button on the dialog).

In Python variables that are None are simply considered false. Truth in Python is a tricky thing, but best explained by the following web page:


http://www.users.csbsju.edu/~clusena/python/fundamentals/node10.html

fileRef = open(filepath, 'w')

Again, similar looking to the AppleScript - open the file at filepath with write permissions.

while True:

Here the aforementioned Zen of Python "when faced with ambiguity, resist the temptation to guess" returns. The above line shows how deeply this statement is ingrained in the Python culture. The equivalent AppleScript statement is just "repeat" - to which Pythonistas would ask "repeat what?". Here Python explicitly says "do the following as long as this statement is true". The True must be capitalized - True means true, while true means nothing. Got it? Good.

 te xtReturned = EasyDialogs.AskString( 
  prompt = "enter a line", default = "line", 
  ok="Enter", cancel = "No more")

By reading the documentation I found this method, and figured out what parameters to pass to it. These parameters are self-explanatory, but it did take a bit of hunting in the documentation (and maybe even a read of the source) to learn exactly how to construct this line.

if textReturned:

Here again we test the value of textReturned - if it contains anything, the if executes. Same as the if filepath line above. It is worth repeating that lines that begin blocks of indented code, such as this line, need a colon at the end.

fileRef.write(textReturned + os.linesep)

Here we write the text the user entered, and a line separator (of whatever platform we're on) to the file. As mentioned before, os.linesep will return the end-of-line character(s) for whatever platform the script is on.

else: 
  break 

Here we come to the end of the if textReturned block. If textReturned is None, as belabored in more detail above, the user pressed the cancel button - we should abort our while loop.

fileRef.close()

Always close our file - in this case, by calling fileRef object's close() method. Note the indentation level of this line - it is on the same level indentation wise, as the while statement. This signals the end of the while loop - the indentation level changed. While this was mentioned previously in the article, in the "whitespace matters" section, it deserves repeating here.

Two Worlds Collide: AppleScript, meet Python

Even if you don't want to use Python as your main scripting language, you can slowly move parts of your AppleScripts into Python - for instance having your Python scripts do things that are hard to do (or slow to do) in AppleScript, but easy in Python. Here's an example that will find a string inside a string (or return 0 if it does not). This task is easy to do in AppleScript (using the offset of functionality), but it can be very slow. Instead of using offset of we use a Python script to do it.

Python script: substr.py:

#!/usr/bin/env python 
#first line tells us where to find python. 


#a # character means the rest of the 
#line is a comment, just like AppleScript's --



import sys 


findWord = sys.argv[1] #get the first command line argument 
thestring = sys.argv[2] #get the string 


print thestring.find(findWord) + 1 
#AppleScript strings start at 1, python's @ 0. Adjust the answer for AS. 

Create the above Python script your favorite text editor, and save it. Make sure the line endings are set to Unix line endings, just to be safe.

Now, create the following AppleScript, and save it in the same folder as the above Python script, in Application format.

 on run 
 display dialog ( "world has been found at character: "

  & pythonSubStr("world", "hello world") ) 
end run 


to pythonSubStr(toFind, theString) 
 set myContainer to getContainerofMe() 


 set myResult to do shell script "python " & myContainer 
  & "substr.py " & " \"" & toFind & "\"" & " \"" &

  theString & "\""



 -- tell python what script to open up, and what params to pass 
 -- also note that the quotes we put around both strings are to prevent the shell from 
 -- breaking them into lots of different arguments (the shell sees a space 
 -- as an argument separator) 
 -- this is usually not what we want to do. These will be removed 
 -- automatically by Python. 
 

 return myResult 
end pythonSubStr 


on getContainerofMe() 
 tell application "Finder"

  set dest to path to me 
  set temp_container to container of dest as alias 
  return (quoted form of POSIX path of temp_container) 
 --POSIX = unix path 
 end tell 
end getContainerofMe

However, it's worth noting here that do shell script on my test machine (400Mhz Powerbook G4) takes about .5 seconds to execute. This is not because Python is slow, but rather do shell script can take a while to do its initialization and termination routines. This slowness, however, may just beat out a vanilla AppleScript using offset of, depending on the data.

Using Python, you can sometimes build functionality into your scripts that normally would require third party OSAXen in AppleScript. Complex string manipulations, regular expressions, even sending email. Using do shell script to merge AppleScript and Python code might just provide that extra oomph for your script, or may just speed up your development process.

Conclusion

With it's familiar-feeling language, cross-platform abilities, large standard library, and simple, readable syntax, you might find Python an interesting choice for your next project - even if it's only a part of it. Feel free to experiment with the built-in Python interpreter. Fire up Terminal.app and enter the command python to be taken into the command line Python's interactive mode (Control-D to get out). For those of you of the GUI persuasion, see the Python Interactive window in the Python IDE. Learn more about Python by visiting the Python website athttp://www.python.org , in particular the Introduction section (http://www.python.org/doc/Intros.html).

References

For additional information on Python, see http://www.python.org. For additional information on using Python on the Mac, see http://www.pythonmac.org/ . Thanks go to Matthew Strange and Jared Barden for reviewing this article.


Ryan Wilcox is the founder of Wilcox Development Solutions (www.wilcoxd.com) specializing in carbonization, cross-platform application development and e-commerce solutions. He often has a hard time thinking of witty things to say in these blurbs. You can reach him at rwilcox@wilcoxd.com.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

ESET Cyber Security 6.11.414.0 - Basic i...
ESET Cyber Security provides powerful protection against phishing, viruses, worms, and spyware. Offering similar functionality to ESET NOD32 Antivirus for Windows, ESET Cyber Security for Mac allows... Read more
Opera 105.0.4970.29 - High-performance W...
Opera is a fast and secure browser trusted by millions of users. With the intuitive interface, Speed Dial and visual bookmarks for organizing favorite sites, news feature with fresh, relevant content... Read more
Slack 4.35.131 - Collaborative communica...
Slack brings team communication and collaboration into one place so you can get more work done, whether you belong to a large enterprise or a small business. Check off your to-do list and move your... Read more
Viber 21.5.0 - Send messages and make fr...
Viber lets you send free messages and make free calls to other Viber users, on any device and network, in any country! Viber syncs your contacts, messages and call history with your mobile device, so... Read more
Hazel 5.3 - Create rules for organizing...
Hazel is your personal housekeeper, organizing and cleaning folders based on rules you define. Hazel can also manage your trash and uninstall your applications. Organize your files using a familiar... Read more
Duet 3.15.0.0 - Use your iPad as an exte...
Duet is the first app that allows you to use your iDevice as an extra display for your Mac using the Lightning or 30-pin cable. Note: This app requires a iOS companion app. Release notes were... Read more
DiskCatalogMaker 9.0.3 - Catalog your di...
DiskCatalogMaker is a simple disk management tool which catalogs disks. Simple, light-weight, and fast Finder-like intuitive look and feel Super-fast search algorithm Can compress catalog data for... Read more
Maintenance 3.1.2 - System maintenance u...
Maintenance is a system maintenance and cleaning utility. It allows you to run miscellaneous tasks of system maintenance: Check the the structure of the disk Repair permissions Run periodic scripts... Read more
Final Cut Pro 10.7 - Professional video...
Redesigned from the ground up, Final Cut Pro combines revolutionary video editing with a powerful media organization and incredible performance to let you create at the speed of thought.... Read more
Pro Video Formats 2.3 - Updates for prof...
The Pro Video Formats package provides support for the following codecs that are used in professional video workflows: Apple ProRes RAW and ProRes RAW HQ Apple Intermediate Codec Avid DNxHD® / Avid... Read more

Latest Forum Discussions

See All

New ‘Dysmantle’ iOS Update Adds Co-Op Mo...
We recently had a major update hit mobile for the open world survival and crafting adventure game Dysmantle ($4.99) from 10tons Ltd. Dysmantle was one of our favorite games of 2022, and with all of its paid DLC and updates, it is even better. | Read more »
PUBG Mobile pulls a marketing blinder wi...
Over the years, there have been a lot of different marketing gimmicks tried by companies and ambassadors, some of them land like Snoop Dog and his recent smoking misdirection, and some are just rather frustrating, let’s no lie. Tencent, however,... | Read more »
‘Goat Simulator 3’ Mobile Now Available...
Coffee Stain Publishing and Coffee Stain Malmo, the new mobile publishing studio have just released Goat Simulator 3 on iOS and Android as a premium release. Goat Simulator 3 debuted on PS5, Xbox Series X|S, and PC platforms. This is the second... | Read more »
‘Mini Motorways’ Huge Aurora Borealis Up...
Mini Motorways on Apple Arcade, Nintendo Switch, and Steam has gotten a huge update today with the Aurora Borealis patch bringing in Reykjavik, new achievements, challenges, iCloud improvements on Apple Arcade, and more. Mini Motorways remains one... | Read more »
Fan-Favorite Action RPG ‘Death’s Door’ i...
Last month Netflix revealed during their big Geeked Week event a number of new titles that would be heading to their Netflix Games service. Among them was Acid Nerve and Devolver Digital’s critically acclaimed action RPG Death’s Door, and without... | Read more »
SwitchArcade Round-Up: Reviews Featuring...
Hello gentle reader, and welcome to the SwitchArcade Round-Up for December 4th, 2023. I’ve been catching up on my work as much as possible lately, and that translates to a whopping six reviews for you to read today. The list includes Astlibra... | Read more »
‘Hi-Fi Rush’ Anniversary Interview: Dire...
Back in January, Tango Gameworks and Bethesda released one of my favorite games of all time with Hi-Fi Rush. As someone who adores character action and rhythm games, blending both together seemed like a perfect fit for my taste, but Hi-Fi Rush did... | Read more »
Best iPhone Game Updates: ‘Pizza Hero’,...
Hello everyone, and welcome to the week! It’s time once again for our look back at the noteworthy updates of the last seven days. Things are starting to chill out for the year, but we still have plenty of holiday updates ahead of us I’m sure. Some... | Read more »
New ‘Sonic Dream Team’ Performance Analy...
Sonic Dream Team (), the brand new Apple Arcade exclusive 3D Sonic action-platformer releases tomorrow. Read my in-depth interview with SEGA HARDLight here covering the game, future plans, potential 120fps, playable characters, the narrative, and... | Read more »
New ‘Zenless Zone Zero’ Trailer Showcase...
I missed this late last week, but HoYoverse released another playable character trailer for the upcoming urban fantasy action RPG Zenless Zone Zero. We’ve had a few trailers so far for playable characters, but the newest one focuses on Nicole... | Read more »

Price Scanner via MacPrices.net

Apple is clearing out last year’s M1-powered...
Apple has Certified Refurbished 11″ M1 iPad Pros available starting at $639 and ranging up to $310 off Apple’s original MSRP. Each iPad Pro comes with Apple’s standard one-year warranty, features a... Read more
Save $50 on these HomePods available today at...
Apple has Certified Refurbished White and Midnight HomePods available for $249, Certified Refurbished. That’s $50 off MSRP and the lowest price currently available for a full-size Apple HomePod this... Read more
New 16-inch M3 Pro MacBook Pros are on sale f...
Holiday MacBook deals are live at B&H Photo. Apple 16″ MacBook Pros with M3 Pro CPUs are in stock and on sale for $200-$250 off MSRP. Their prices are among the lowest currently available for... Read more
Christmas Deal Alert! Apple AirPods Pro with...
Walmart has Apple’s 2023 AirPods Pro with USB-C in stock and on sale for $189.99 on their online store as part of their Holiday sale. Their price is $60 off MSRP, and it’s currently the lowest price... Read more
Apple has Certified Refurbished iPhone 12 Pro...
Apple has unlocked Certified Refurbished iPhone 12 Pro models in stock starting at $589 and ranging up to $350 off original MSRP. Apple includes a standard one-year warranty and new outer shell with... Read more
Holiday Sale: Take $50 off every 10th-generat...
Amazon has Apple’s 10th-generation iPads on sale for $50 off MSRP, starting at $399, as part of their Holiday Sale. Their discount applies to all models and all colors. With the discount, Amazon’s... Read more
The latest Mac mini Holiday sales, get one to...
Apple retailers are offering Apple’s M2 Mac minis for $100 off MSRP as part of their Holiday sales. Prices start at only $499. Here are the lowest prices available: (1): Amazon has Apple’s M2-powered... Read more
Save $300 on a 24-inch iMac with these Certif...
With the recent introduction of new M3-powered 24″ iMacs, Apple dropped prices on clearance M1 iMacs in their Certified Refurbished store. Models are available starting at $1049 and range up to $300... Read more
Apple M1-powered iPad Airs are back on Holida...
Amazon has 10.9″ M1 WiFi iPad Airs back on Holiday sale for $100 off Apple’s MSRP, with prices starting at $499. Each includes free shipping. Their prices are the lowest available among the Apple... Read more
Sunday Sale: Apple 14-inch M3 MacBook Pro on...
B&H Photo has new 14″ M3 MacBook Pros, in Space Gray, on Holiday sale for $150 off MSRP, only $1449. B&H offers free 1-2 day delivery to most US addresses: – 14″ 8-Core M3 MacBook Pro (8GB... Read more

Jobs Board

Mobile Platform Engineer ( *Apple* /AirWatch)...
…systems, installing and maintaining certificates, navigating multiple network segments and Apple /IOS devices, Mobile Device Management systems such as AirWatch, and Read more
Omnichannel Associate - *Apple* Blossom Mal...
Omnichannel Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Senior Product Manager - *Apple* - DISH Net...
…Responsibilities** We are seeking an ambitious, data-driven thinker to assist the Apple Product Development team as our Wireless Product division continues to grow Read more
Senior Product Manager - *Apple* - DISH Net...
…Responsibilities** We are seeking an ambitious, data-driven thinker to assist the Apple Product Development team as our Wireless Product division continues to grow Read more
Senior Software Engineer - *Apple* Fundamen...
…center of Microsoft's efforts to empower our users to do more. The Apple Fundamentals team focused on defining and improving the end-to-end developer experience in Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.