TweetFollow Us on Twitter

Python Power Tools

Volume Number: 22 (2006)
Issue Number: 11
Column Tag: Programming Python

Python Power Tools

An Introduction to Some Tools Available for Python Developers Running OS X

by Christopher Roach

Introduction

One thing that every craftsman loves are new tools, and programmers are no exception to this rule. If you fall into the category of a Python developer, then this article was written precisely for you. What I propose to do during the course of this article is to introduce you, the Python programmer, to a few libraries that will aid you in your development ritual and perhaps even inspire you to develop in new and interesting areas.

One thing you'll no doubt notice once we start our exploration into the tools available for Python developers, is that there is no limit to the number of libraries, packages, modules, etc. that you can use to get your job done. What I've tried to do here in this article is concentrate on the most popular and most stable, and then perhaps point out a couple of alternatives for those of you not content with using just the mainstream tools.

So, with our goal clear in our minds, let's press on, and begin our journey with a look at some of the GUI libraries available for Python on OS X.

GUI Libraries

GUI libraries are an area that in no way, contradict the observation I made in the introduction. There is a plethora of GUI libraries available to Python programmers, and many of these are open source and cross-platform so they can easily be used on the Macintosh OS, as well as many of the other operating systems that you may be forced to use outside of your own little world. A few of these libraries are Tkinter (the standard Python interface to the Tk GUI toolkit), wxPython (a Python wrapper for wxWidgets, a popular cross-platform GUI library written in C++), PyQt (a set of Python bindings for the Qt toolkit that is also cross-platform), and many more. I'll concentrate on two of the most popular libraries in the next two subsections of this article starting with Tkinter, and then I'll mention a few alternatives quickly in the final section.

Tkinter

As I stated in the previous paragraph, Tkinter is the standard interface to the Tk GUI toolkit for Python programmers. It is also pretty much the de facto standard for GUI development with Python on any platform. There are many advantages to using Tkinter as your GUI library of choice, when developing Python-based applications.

First, it's one of the most portable GUI libraries. Tcl and Tk have been around for such a long time, and have developed such a devoted following, that it is nearly impossible to name a platform that doesn't have a port of the toolkit available. Second, it's really easy to install on the Macintosh operating system; simplyinstall MacPython on your system, rather than going with the default version of Python. Finally, it's extremely easy to develop GUI-based applications with it. This is, of course, one of the reasons why Tk has such a large following amongst programmers. So, with all of these great benefits in mind, how do we get Tkinter installed?

Well, if you installed the MacPython binary--and I recommend that you do <http://homepages.cwi.nl/~jack/macpython/download.html>--you're already halfway there. Basically, you have Python and the Tkinter interface already, now all you need to do is get a copy of the Tk toolkit. To do this you'll need to download and install the latest distribution of the Tcl/Tk Aqua binary from <http://tcltkaqua.sourceforge.net> I installed the Batteries Included binary (~30MB), but you can probably get away with just installing the 5MB version, but really, why not install the whole thing and give yourself some more toys to play with later? You can always learn Tcl/Tk after toying around with your new Python libraries; after all you can never know too many programming languages.

Once you've got a version of Tk installed on your computer, the only thing left to do is enable the Tkinter binary module using the MacPython PackageManager application. To do this, find the MacPython folder on your system and double click on the PackageManager application. Once opened, you should see a package named _tkinter-x.x-binary in the package list. Select this package and click on the install button in the form below the package list. That's it. You should now be able to create Python programs with a Tk-based graphical interface. If you wish to try it out, you can just run the simple application below to see a quick "hello world" dialog.

Listing 1: TkinterSample.py

TkinterSample.py

Create a new Tk application with a root and label object and display it to the user.
from Tkinter import *
# All Tk applications should have a root
root = Tk()
# Create a new label, assign it to the root, and give it the text "Hello World"
w = Label(root, text="Hello world!", pady=10, padx=10)
# The command packs the root frame tightly around the label
w.pack()
# This command starts the main Tk event loop
root.mainloop()

To run this program, you'll need to run the script through the Python interpreter by typing pythonw TkinterSample.py into the Terminal. One thing to take notice of, is that we use something called pythonw rather than calling the normal Python interpreter to run our program. The reason for this is because our application is a window-based application (i.e., it does not display inside of the Terminal). The pythonw script executes the Python interpreter using a fully qualified path to overcome a bug within OS X. This allows a Python GUI-based application to interact properly with the Window Manager.

If you got everything typed in correctly, and you used pythonw instead of python to run your script, you should see a dialog that looks similar to the one in the figure below.



Figure 1 - TkinterSample.py and Emacs

Well then, you've tried out the short application above to make sure that your installation of Tkinter works properly, and you're still curious to learn more. Well have no fear, wxPython is another very popular GUI library for Python and we're going to cover it in the very next subsection.

wxPython

Back in 1992, at the Artificial Intelligence Applications Institute, at the University of Edinburgh, Julian Smart was designing a tool that needed to run on both Windows PCs and X-based Unix workstations. The existing cross-platform GUI libraries were all too expensive for an in-house experimental project, and so the decision was made to develop an easy to use, cross-platform, GUI library. Thus, wxWidgets was born--actually wxWindows at the time, the name was later changed.

Over time, the library developed a strong following, and in 1996, a version for the Python programming language was created by Robin Dunn. The port for Python was called wxPython, and it was implemented as an extension module wrapping the wxWidgets C++ class library. Since then, the wxPython library has grown to become a very stable, powerful, and easy to use GUI toolkit. Just like Tkinter, it has been ported to nearly every computing platform imaginable, which means that - when using wxPython - you'll be able to develop your GUI-based apps with little regard for the final target architecture or operating system.

The wxPython library is an Open Source project, so the source code can be downloaded and manipulated if need be, but the most important thing to remember is that Open Source means free, as in beer. Just like Tkinter, you can download, use, and freely distribute applications that you create with this library without paying a fee to anyone. The library is also extremely easy to install, since a binary installer is available for the Mac OS X platform which can be found at the main wxPython website <http://www.wxpython.org/>.

Through my experiments with wxPython, I have found that I prefer it to all of the other GUI libraries that I have tried thus far. I found its installation to be the easiest out of the GUI libraries listed in this article and its popularity is second only to Tkinter and rapidly gaining on the Tk toolkit. Also, just like Tkinter, there are ports of the library to several other popular languages. So, by learning Tkinter or wxPython, you are essentially getting a tool that can be used with several different languages and not just for Python development.

Other Libraries

As I stated in the section introduction, I decided to cover the two GUI libraries that I found to be the most popular. The reason for this was that, I had assumed (however wrong my assumption may be) that the most popular libraries would be the easiest to use, the easiest to find help for, the most stable, and the most available to the consumer of our applications. That said, there are several other very nice options for Python GUI-based development, a few of which we'll quickly look over in the remainder of this section.

For anyone who wants to develop applications specifically for the Mac OS X platform, PyObjC provides a bridge between the Python programming language, and the Cocoa Objective-C classes. With PyObjC installed, you can create OS X native applications using the Interface Builder application to create your GUIs. For those of you interested in using the PyObjC Bridge to create your Python applications, we'll be covering it in the next section on code editors and IDEs.

If you're not really interested in Cocoa development, you're looking for something a little more cross-platform, and you have experience with Java, you may want to look into Jython. Jython is an implementation of the Python language written in 100% pure Java, so it's actually much more than just a conduit to Java's Swing library, but for the purpose of fitting into this section, we'll look at as such.

Ok, I know what you're thinking. Why would I ever need a Java implementation of Python? Well, just let me point out a few of the reasons why you may find Jython useful when developing Python applications.

First, having Python implemented in Java means that you now have the ability to run Python applications on any system that can run the JVM. This opens up the opportunity of writing programs for many more platforms, since nearly every platform now runs Java.

Second--and what I really wanted to cover in this section--if you're like me and you basically cut your teeth on Java, then Jython gives you a good starting point to get up and running quickly with Python, without the additional overhead of learning a GUI library as well. When I first started learning Python, I was able to write GUI-based applications in Python using Swing--with which I already had quite extensive experience. This meant that I was able to concentrate more on learning the language, and less on learning a GUI library.

Finally, there's PyQt. Trolltech's Qt is a very popular GUI library for Linux programming, but it also happens to be a very able toolkit on several different platforms (including Windows and Mac OS X, of course). PyQt is a set of bindings for Trolltech's Qt GUI toolkit and like many of our other libraries, it's available on a non-commercial license for free, and can be downloaded at <http://www.riverbankcomputing.co.uk/pyqt/download.php> My only complaint about using Qt is that it doesn't seem to scale that well. Larger projects written in PyQt seemed a bit sluggish, even on a beefy G4, 1.25GHz processor and 1GB of RAM. Although, with that said, I have noticed that larger projects using some of the other libraries are not the speediest either. It would seem that very large-scale, GUI-based projects might still be out of reach of the Python developer for the time being; much like the Java-based apps of a few years ago (recently Java applications have become much more responsive, though still a little too slow for my taste).

Scientific Libraries

Since overhauling their operating system by adding Unix underpinnings to its already venerable user interface, Apple has been gaining ground in the scientific community. Researchers in Bioinformatics and Computational Biology, Applied Physics, and Mathematics--you name it--have found OS X to be a formidable system for research as well as their day-to-day tasks. The Mac OS provides a scientist with an all-in-one solution. OS X makes it easy for a researcher to run all of the Unix-based scientific apps they need, develop programs in a multitude of scripting and programming languages, write their research publications using Microsoft Word or LaTeX, and do it all on one machine. It is this versatility that has made OS X, the preferred operating system of many researchers.

One thing that you'll find common across most scientists is a need for powerful scripting languages. Bioinformatics, for example, is one area of research where we have seen a strong use of popular and powerful scripting languages. Perl has historically been the scripting language de rigueur for many bioinformaticions, but Python has been steadily gaining ground for several years now. Loved by many for its combination of power and readability, (the latter of which is something that many will say Perl definitely lacks) Python has grown on the scientific community, and we are starting to see several different libraries created specifically for the tasks required by these researchers.

The rest of this section will try to introduce you to a few of the more popular libraries for researchers. So, for any of you out there considering graduate school a possibility in the near future, listen up and take notes.

NumPy

Numerical Python, or NumPy, is a library created principally by Jim Hugunin while a student at MIT, and currently maintained by a group of developers headed by Paul Dubois. This library provides Python with the facilities to handle matrices and Linear Algebra mathematics. It's a powerful library that is extremely easy to install, as well as use.

Installation of the NumPy library is typical of most python command line installations, that is, you'll need to run a setup script through the Python interpreter with the command line argument install. In our case we will need to modify this a bit by using the setup_all.py script instead, and thus, our install line should look like this: python setup_all.py install.

Running this line from the NumPy directory in the Terminal application should install NumPy on your system without any problems. Before you get started with the installation, however, you may need to download the library. You can do so at its homepage at <http://numpy.scipy.org//>.

One more thing: you may need to be root to install the library. So, if you run into any problems during the installation, especially ones that mention invalid permissions, you may want to try running the script again, this time with the sudo command.

Once you get NumPy installed, and you're able to play around with it a bit, you'll notice how greatly it simplifies doing complicated linear algebra in your Python programs. However, even though it's great by itself, the true power of NumPy can be appreciated only when coupled with other libraries such as the popular DISLIN library--a library for data visualization. With that thought in mind, it only seems natural to look into the DISLIN library next.

DISLIN

DISLIN, as was mentioned in previous subsection, is a library for producing data visualizations. It's cross platform and also quite easy to use. Once again though, we have found a tool that makes use of X windows to produce its visual displays. So, remember when running your DISLIN visualizations, you must run them from whatever X windows implementation you have decided to install on your system.

Even with the caveat that we have to run our visualizations under a distribution of X windows, the library is definitely worth the download, if you plan on doing anything where it will become important to graphically visualize large sets of data. So, I would suggest that you run out to its homepage <http://www.mps.mpg.de/dislin/> and download the Darwin, ppc distribution for the Mac.

Once you've downloaded the library and unpacked it into a temporary directory, you can proceed with the installation of the package. Once again, this library will need to be installed from the command line (no binaries available, but hey its free, so stop complaining). This one is a bit more complex than the one for NumPy, but all of the steps are clearly labeled in the README file provided with the distribution. Just make sure that you don't stop after the installation, but that you also run through the directions for using DISLIN with Python that are listed below the install instructions.

Once you've got the library properly installed, you'll definitely want to give it a try. So, to satisfy your curiosity, and also as an example of the ease at which you can create impressive data visualizations using Python and DISLIN, I have included the code for a simple surface map visualization below.

Listing 3: NumPy and DISLIN sample surface map application

surface_map.py

Creates a surface map visualization using NumPy and DISLIN.
from dislin import *
from Numeric import *
z_mat = zeros((180,180),Float)
x_ray = arange(180.0)
y_ray = arange(180.0)
dtr = 3.141592654/180.0
for x in x_ray:
    for y in y_ray:
        z_mat[int(x)][int(y)] = sin(x*3*dtr)*sin(y*2*dtr)
surshade(z_mat,x_ray,y_ray)
disfin()

The results of running the code above, through the Python interpreter from X11, can be seen in the figure below. Take notice of how very little code you need, to perform a complex visualization like the example that was provided. (See figure 2.)



Figure 2 - DISLIN surface_map.py Sample

Biopython

With the overwhelming popularity of the Bioinformatics field recently, I feel it is important to have a portion of our discussion look into at least one library for researchers in this field. Yet, keep in mind that I am not a researcher in the computational biology field (my chosen area of study is Computer Science), nor do I profess to understand all that I am about to cover below. Regardless of my ineptitude, however, I hope that at least a few bioinformaticions out there will find this subsection to be helpful and informative.

So, with that disclaimer out of the way (and hopefully all the hate mail from the bio-crowd avoided), let's take a look at the Biopython set of tools, and what they have to offer the scientific community.

First, Biopython refers to a project that brings together many developers of freely available Python tools for computational biology. Biopython also refers to the tool suite that is available online at the Biopython website <http://www.biopython.org>. There are several tools for running common operations on sequences as well as the data structures to represent them. There are tools for running translations and BLASTing and for performing classifications of data using k Nearest Neighbors, Naive Bayes, or Support Vector Machines. Biopython is an extremely large and comprehensive set of tools for the biological researcher.

For grins and giggles, I decided to download Biopython and try it out (I had recently begun looking into pursuing a bioinformatics path for my Ph.D., although I may be rethinking that again very soon). I found that the installation was actually not very difficult as long as you don't mind command line installations--sorry, once again no binary distributions here--however, it was very time consuming. Biopython has so many tools that it has quite a large set of dependencies, so I found myself downloading and installing quite a few other packages just to get it to work on my machine.

Nevertheless, after about an hour or so, I finally had it installed (with a few optional libraries left out) and I was able to write up a quick script that took a DNA sequence and returned its RNA translation. Not that I understood what I did, mind you, but I did feel like a scientist for a very short time, and in the process I found that the library should be very intuitive for anyone already possessing knowledge of the bioinformatics field.

Also, as a hint for anyone wishing to install this library, first download and install Fink (a project dedicated to bringing Unix Open Source software to OS X). I was able to use it to install most of the dependencies of Biopython, making the installation a heck of a lot simpler.

A Few Others

In the final section I wanted to just quickly mention a few other libraries that I found for Python, which were no less important than those in the sections prior, but since I'm not writing a book, I had to draw the line somewhere. So, this section just quickly introduces a few more libraries that I think are must haves for any serious Python programmer.

We'll start with a couple of libraries that allow Python scripts to access and utilize arguably the two most popular open source databases: MySQL and PostgreSQL. Then, we'll quickly look into two more libraries that allow the Python programmer to create 3D graphics on OS X.

Databases

In order to standardize the many modules that allow Python developers to access a database, a database API specification, which is currently in version 2.0, was developed. This makes Python programs that access a database, not only easier to write, but also infinitely more portable, since all that needs to change for the code to work with another database is the module that implements the specification.

In this section I wanted to quickly point out two modules that allowed Python programmers to access two of the most popular Open Source databases. These modules are: MySQLdb and PyGreSQL, both, of course, are compliant with version 2.0 of the Python Database specification.

The first, MySQLdb, is, of course, an interface to the MySQL database. This module is fully thread safe and supports transactions. It's easy to install and easy to use, and it can be used with any version of Python above v1.5.2, and with versions of MySQL v3.22 or greater. The other module I wanted to point out works with the PostgreSQL database. PyGreSQL is the name of the module that provides Python with the ability to access and utilize a PostgreSQL database.

If neither database is currently installed on your machine, and you're not particularly interested in going through a long install with the source, Marc Liyanage has links and instructions on his website <http://www.entropy.ch/software/macosx/> for downloading and installing each database on OS X with a binary installer.

If, however, you prefer installing from a source distribution, you can find some documentation on installing each one in the Open Source section of Apple's Developer Connection <http://developer.apple.com/internet/opensource/index.html>.

Once you've installed the databases, you'll be ready to install MySQLdb and PyGreSQL modules. You can find the MySQLdb module through the Sourceforge site at the following address: <http://sourceforge.net/projects/mysql-python> The PostgreSQL database module, PyGreSQL, can be found at its homepage: <http://www.pygresql.org/>

Graphics

There are several choices for graphics libraries when working with Python on the Mac. As I already mentioned earlier, Python developers on the Mac have access to the DISLIN visualization library. However, these obviously are not the only ones, in this section I'll quickly introduce two other 3D graphics libraries.

To start with, VPython is a data visualization library similar to the DISLIN library. However, its main aim is ease of use, and at least from my readings, it seems as if it is being geared towards students in the sciences. As for the installation of the library, my recommendation would be to install it from Fink (use the command fink install visual-py23), and that seems to be the general consensus since even the homepage of VPython <http://www.vpython.org> recommends the same.

The other library gives us access to what is probably the most popular cross platform graphics library: OpenGL. PyOpenGL binds Python to the OpenGL 3D graphics library, version 1.1. The library is a bit behind, since at last check, OpenGL was up to version 2.0. Nevertheless, it works well, it's cross platform, and it's extremely easy to use.

Once again, this library does not have a binary installer, so you'll have to download the source <http://pyopengl.sourceforge.net/> and build it. Nevertheless, when I built the library on my machine, the build and install steps went by without any incident whatsoever, and before I knew it, I had a sample Python-based OpenGL program up and running.

Conclusion

Well, we've certainly covered a lot of ground over the course of this article. I hope you've found some interesting new tools to play with in your future Python development. I also hope that I've inspired you to go out and start doing some research on the web to find even more new tools for your Mac. And who knows, perhaps you'll find a void somewhere out there in the tools available, and you'll be able to organize an effort that delivers another powerful library back to the Python community.

This article's main objective was to whet your appetite, and hopefully get a few of you to try something new in your daily development ritual. In the future, I'll be publishing a few articles that take a look at some of the technologies we covered here, a little closer. So, if you enjoyed this article, and you find yourself thirsty to learn some more, have no fear, I'll have a few more in depth tutorials out there for you to sink your teeth into, sometime very soon.

Bibliography and References

http://www.python.org/doc

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

http://tcltkaqua.sourceforge.net

http://www.wxpython.org/

http://www.jython.org/

http://pyobjc.sourceforge.net/

http://www.biopython.org/

http://www.pfdubois.com/numpy/

http://www.linmpi.mpg.de/dislin/

http://sourceforge.net/projects/mysql-python

http://www.druid.net/pygresql/

http://vpython.org/

http://pyopengl.sourceforge.net/


Christopher Roach recently earned his MS in Computer Science from Virginia Tech and currently works as a software engineer in Florida's Space Coast. On the weekend he tries to find time to write articles on Macintosh programming and do battle with insanely powerful hurricanes, while still trying to preserve some semblance of a life. If you have questions or comments on the article, you can email him at croach@vt.edu

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Top Mobile Game Discounts
Every day, we pick out a curated list of the best mobile discounts on the App Store and post them here. This list won't be comprehensive, but it every game on it is recommended. Feel free to check out the coverage we did on them in the links... | Read more »
Price of Glory unleashes its 1.4 Alpha u...
As much as we all probably dislike Maths as a subject, we do have to hand it to geometry for giving us the good old Hexgrid, home of some of the best strategy games. One such example, Price of Glory, has dropped its 1.4 Alpha update, stocked full... | Read more »
The SLC 2025 kicks off this month to cro...
Ever since the Solo Leveling: Arise Championship 2025 was announced, I have been looking forward to it. The promotional clip they released a month or two back showed crowds going absolutely nuts for the previous competitions, so imagine the... | Read more »
Dive into some early Magicpunk fun as Cr...
Excellent news for fans of steampunk and magic; the Precursor Test for Magicpunk MMORPG Crystal of Atlan opens today. This rather fancy way of saying beta test will remain open until March 5th and is available for PC - boo - and Android devices -... | Read more »
Prepare to get your mind melted as Evang...
If you are a fan of sci-fi shooters and incredibly weird, mind-bending anime series, then you are in for a treat, as Goddess of Victory: Nikke is gearing up for its second collaboration with Evangelion. We were also treated to an upcoming... | Read more »
Square Enix gives with one hand and slap...
We have something of a mixed bag coming over from Square Enix HQ today. Two of their mobile games are revelling in life with new events keeping them alive, whilst another has been thrown onto the ever-growing discard pile Square is building. I... | Read more »
Let the world burn as you have some fest...
It is time to leave the world burning once again as you take a much-needed break from that whole “hero” lark and enjoy some celebrations in Genshin Impact. Version 5.4, Moonlight Amidst Dreams, will see you in Inazuma to attend the Mikawa Flower... | Read more »
Full Moon Over the Abyssal Sea lands on...
Aether Gazer has announced its latest major update, and it is one of the loveliest event names I have ever heard. Full Moon Over the Abyssal Sea is an amazing name, and it comes loaded with two side stories, a new S-grade Modifier, and some fancy... | Read more »
Open your own eatery for all the forest...
Very important question; when you read the title Zoo Restaurant, do you also immediately think of running a restaurant in which you cook Zoo animals as the course? I will just assume yes. Anyway, come June 23rd we will all be able to start up our... | Read more »
Crystal of Atlan opens registration for...
Nuverse was prominently featured in the last month for all the wrong reasons with the USA TikTok debacle, but now it is putting all that behind it and preparing for the Crystal of Atlan beta test. Taking place between February 18th and March 5th,... | Read more »

Price Scanner via MacPrices.net

AT&T is offering a 65% discount on the ne...
AT&T is offering the new iPhone 16e for up to 65% off their monthly finance fee with 36-months of service. No trade-in is required. Discount is applied via monthly bill credits over the 36 month... Read more
Use this code to get a free iPhone 13 at Visi...
For a limited time, use code SWEETDEAL to get a free 128GB iPhone 13 Visible, Verizon’s low-cost wireless cell service, Visible. Deal is valid when you purchase the Visible+ annual plan. Free... Read more
M4 Mac minis on sale for $50-$80 off MSRP at...
B&H Photo has M4 Mac minis in stock and on sale right now for $50 to $80 off Apple’s MSRP, each including free 1-2 day shipping to most US addresses: – M4 Mac mini (16GB/256GB): $549, $50 off... Read more
Buy an iPhone 16 at Boost Mobile and get one...
Boost Mobile, an MVNO using AT&T and T-Mobile’s networks, is offering one year of free Unlimited service with the purchase of any iPhone 16. Purchase the iPhone at standard MSRP, and then choose... Read more
Get an iPhone 15 for only $299 at Boost Mobil...
Boost Mobile, an MVNO using AT&T and T-Mobile’s networks, is offering the 128GB iPhone 15 for $299.99 including service with their Unlimited Premium plan (50GB of premium data, $60/month), or $20... Read more
Unreal Mobile is offering $100 off any new iP...
Unreal Mobile, an MVNO using AT&T and T-Mobile’s networks, is offering a $100 discount on any new iPhone with service. This includes new iPhone 16 models as well as iPhone 15, 14, 13, and SE... Read more
Apple drops prices on clearance iPhone 14 mod...
With today’s introduction of the new iPhone 16e, Apple has discontinued the iPhone 14, 14 Pro, and SE. In response, Apple has dropped prices on unlocked, Certified Refurbished, iPhone 14 models to a... Read more
B&H has 16-inch M4 Max MacBook Pros on sa...
B&H Photo is offering a $360-$410 discount on new 16-inch MacBook Pros with M4 Max CPUs right now. B&H offers free 1-2 day shipping to most US addresses: – 16″ M4 Max MacBook Pro (36GB/1TB/... Read more
Amazon is offering a $100 discount on the M4...
Amazon has the M4 Pro Mac mini discounted $100 off MSRP right now. Shipping is free. Their price is the lowest currently available for this popular mini: – Mac mini M4 Pro (24GB/512GB): $1299, $100... Read more
B&H continues to offer $150-$220 discount...
B&H Photo has 14-inch M4 MacBook Pros on sale for $150-$220 off MSRP. B&H offers free 1-2 day shipping to most US addresses: – 14″ M4 MacBook Pro (16GB/512GB): $1449, $150 off MSRP – 14″ M4... Read more

Jobs Board

All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.