Eggs Mac OS

Posted on  by

Easter Eggs found in Mac OS X Software. Find hidden easter eggs in movies, tv shows, software, music, books, and art. The scrambled egg sausage mix in a McDonald’s breakfast burrito is also precooked by food suppliers, then mixed in with other ingredients such as meat, vegetables, spices, sugar, and additives. In classic Mac OS, if you go to Apple Menu - About this computer and press command + option + control, it will change to 'About the Mac OS Team' and display a credits of the OS. Mac OS Easter Eggs Wiki Fandom. Easter Eggs Wiki is a FANDOM Movies Community.

  1. Eggs Macronutrients
  2. Mac Os Mojave

STOP! This is not the first document you should read!

Table of Contents

A “Python egg” is a logical structure embodying the release of aspecific version of a Python project, comprising its code, resources,and metadata. There are multiple formats that can be used to physicallyencode a Python egg, and others can be developed. However, a keyprinciple of Python eggs is that they should be discoverable andimportable. That is, it should be possible for a Python application toeasily and efficiently find out what eggs are present on a system, andto ensure that the desired eggs’ contents are importable.

There are two basic formats currently implemented for Python eggs:

  1. .egg format: a directory or zipfile containing the project’scode and resources, along with an EGG-INFO subdirectory thatcontains the project’s metadata

  2. .egg-info format: a file or directory placed adjacent to theproject’s code and resources, that directly contains the project’smetadata.

Both formats can include arbitrary Python code and resources, includingstatic data files, package and non-package directories, Pythonmodules, C extension modules, and so on. But each format is optimizedfor different purposes.

The .egg format is well-suited to distribution and the easyuninstallation or upgrades of code, since the project is essentiallyself-contained within a single directory or file, unmingled with anyother projects’ code or resources. It also makes it possible to havemultiple versions of a project simultaneously installed, such thatindividual programs can select the versions they wish to use.

The .egg-info format, on the other hand, was created to supportbackward-compatibility, performance, and ease of installation for systempackaging tools that expect to install all projects’ code and resourcesto a single directory (e.g. site-packages). Placing the metadatain that same directory simplifies the installation process, since itisn’t necessary to create .pth files or otherwise modifysys.path to include each installed egg.

Its disadvantage, however, is that it provides no support for cleanuninstallation or upgrades, and of course only a single version of aproject can be installed to a given directory. Thus, support from apackage management tool is required. (This is why setuptools’ “install”command refers to this type of egg installation as “single-version,externally managed”.) Also, they lack sufficient data to allow them tobe copied from their installation source. easy_install can “ship” anapplication by copying .egg files or directories to a targetlocation, but it cannot do this for .egg-info installs, becausethere is no way to tell what code and resources belong to a particularegg – there may be several eggs “scrambled” together in a singleinstallation location, and the .egg-info format does not currentlyinclude a way to list the files that were installed. (This may changein a future version.)

The layout of the code and resources is dictated by Python’s normalimport layout, relative to the egg’s “base location”.

For the .egg format, the base location is the .egg itself. Thatis, adding the .egg filename or directory name to sys.pathmakes its contents importable.

For the .egg-info format, however, the base location is thedirectory that contains the .egg-info, and thus it is thedirectory that must be added to sys.path to make the egg importable.(Note that this means that the “normal” installation of a package to asys.path directory is sufficient to make it an “egg” if it has an.egg-info file or directory installed alongside of it.)

If eggs contained only code and resources, there would of course beno difference between them and any other directory or zip file onsys.path. Thus, metadata must also be included, using a metadatafile or directory.

For the .egg format, the metadata is placed in an EGG-INFOsubdirectory, directly within the .egg file or directory. For the.egg-info format, metadata is stored directly within the.egg-info directory itself.

The minimum project metadata that all eggs must have is a standardPython PKG-INFO file, named PKG-INFO and placed within themetadata directory appropriate to the format. Because it’s possible forthis to be the only metadata file included, .egg-info format eggsare not required to be a directory; they can just be a .egg-infofile that directly contains the PKG-INFO metadata. This eliminatesthe need to create a directory just to store one file. This option isnot available for .egg formats, since setuptools always includesother metadata. (In fact, setuptools itself never generates.egg-info files, either; the support for using files was added sothat the requirement could easily be satisfied by other tools, suchas distutils).

In addition to the PKG-INFO file, an egg’s metadata directory mayalso include files and directories representing various forms ofoptional standard metadata (see the section on Standard Metadata,below) or user-defined metadata required by the project. For example,some projects may define a metadata format to describe their applicationplugins, and metadata in this format would then be included by plugincreators in their projects’ metadata directories.

To allow introspection of installed projects and runtime resolution ofinter-project dependencies, a certain amount of information is embeddedin egg filenames. At a minimum, this includes the project name, andideally will also include the project version number. Optionally, itcan also include the target Python version and required runtimeplatform if platform-specific C code is included. The syntax of anegg filename is as follows:

The “name” and “version” should be escaped using the to_filename()function provided by pkg_resources, after first processing them withsafe_name() and safe_version() respectively. These latter twofunctions can also be used to later “unescape” these parts of thefilename. (For a detailed description of these transformations, pleasesee the “Parsing Utilities” section of the pkg_resources manual.)

The “pyver” string is the Python major version, as found in the first3 characters of sys.version. “required_platform” is essentiallya distutils get_platform() string, but with enhancements to properlydistinguish Mac OS versions. (See the get_build_platform()documentation in the “Platform Utilities” section of thepkg_resources manual for more details.)

Finally, the “ext” is either .egg or .egg-info, as appropriatefor the egg’s format.

Normally, an egg’s filename should include at least the project name andversion, as this allows the runtime system to find desired projectversions without having to read the egg’s PKG-INFO to determine itsversion number.

Setuptools, however, only includes the version number in the filenamewhen an .egg file is built using the bdist_egg command, or whenan .egg-info directory is being installed by theinstall_egg_info command. When generating metadata for use with theoriginal source tree, it only includes the project name, so that thedirectory will not have to be renamed each time the project’s versionchanges.

This is especially important when version numbers change frequently, andthe source metadata directory is kept under version control with therest of the project. (As would be the case when the project’s sourceincludes project-defined metadata that is not generated from bysetuptools from data in the setup script.)

In addition to the .egg and .egg-info formats, there is a thirdegg-related extension that you may encounter on occasion: .egg-linkfiles.

These files are not eggs, strictly speaking. They simply provide a wayto reference an egg that is not physically installed in the desiredlocation. They exist primarily as a cross-platform alternative tosymbolic links, to support “installing” code that is being developed ina different location than the desired installation location. Forexample, if a user is developing an application plugin in their homedirectory, but the plugin needs to be “installed” in an applicationplugin directory, running “setup.py develop -md /path/to/app/plugins”will install an .egg-link file in /path/to/app/plugins, thattells the egg runtime system where to find the actual egg (the user’sproject source directory and its .egg-info subdirectory).

.egg-link files are named following the format for .egg and.egg-info names, but only the project name is included; no version,Python version, or platform information is included. When the runtimesearches for available eggs, .egg-link files are opened and theactual egg file/directory name is read from them.

Each .egg-link file should contain a single file or directory name,with no newlines. This filename should be the base location of one ormore eggs. That is, the name must either end in .egg, or else itshould be the parent directory of one or more .egg-info format eggs.

As of setuptools 0.6c6, the path may be specified as a platform-independent(i.e. /-separated) relative path from the directory containing the.egg-link file, and a second line may appear in the file, specifying aplatform-independent relative path from the egg’s base directory to itssetup script directory. This allows installation tools such as EasyInstallto find the project’s setup directory and build eggs or perform other setupcommands on it.

In addition to the minimum required PKG-INFO metadata, projects caninclude a variety of standard metadata files or directories, asdescribed below. Except as otherwise noted, these files and directoriesare automatically generated by setuptools, based on information suppliedin the setup script or through analysis of the project’s code andresources.

Most of these files and directories are generated via “egg-infowriters” during execution of the setuptools egg_info command, andare listed in the egg_info.writers entry point group defined bysetuptools’ own setup.py file.

Project authors can register their own metadata writers as entry pointsin this group (as described in the setuptools manual under “Adding newEGG-INFO Files”) to cause setuptools to generate project-specificmetadata files or directories during execution of the egg_infocommand. It is up to project authors to document these new metadataformats, if they create any.

Files described in this section that have .txt extensions have asimple lexical format consisting of a sequence of text lines, each lineterminated by a linefeed character (regardless of platform). Leadingand trailing whitespace on each line is ignored, as are blank lines andlines whose first nonblank character is a # (comment symbol). (Thisis the parsing format defined by the yield_lines() function ofthe pkg_resources module.)

All .txt files defined by this section follow this format, but someare also “sectioned” files, meaning that their contents are divided intosections, using square-bracketed section headers akin to Windows.ini format. Note that this does not imply that the lines withinthe sections follow an .ini format, however. Please see anindividual metadata file’s documentation for a description of what thelines and section names mean in that particular file.

Sectioned files can be parsed using the split_sections() function;see the “Parsing Utilities” section of the pkg_resources manual forfor details.

Mac

This is a “sectioned” text file. Each section is a sequence of“requirements”, as parsed by the parse_requirements() function;please see the pkg_resources manual for the complete requirementparsing syntax.

The first, unnamed section (i.e., before the first section header) inthis file is the project’s core requirements, which must be installedfor the project to function. (Specified using the install_requireskeyword to setup()).

The remaining (named) sections describe the project’s “extra”requirements, as specified using the extras_require keyword tosetup(). The section name is the name of the optional feature, andthe section body lists that feature’s dependencies.

Note that it is not normally necessary to inspect this file directly;pkg_resources.Distribution objects have a requires() methodthat can be used to obtain Requirement objects describing theproject’s core and optional dependencies.

Much like requires.txt except represents the requirementsspecified by the setup_requires parameter to the Distribution.

A list of dependency URLs, one per line, as specified using thedependency_links keyword to setup(). These may be directdownload URLs, or the URLs of web pages containing direct downloadlinks. Please see the setuptools manual for more information onspecifying this option.

This file follows an identical format to requires.txt, but isobsolete and should not be used. The earliest versions of setuptoolsrequired users to manually create and maintain this file, so the runtimestill supports reading it, if it exists. The new filename was createdso that it could be automatically generated from setup() informationwithout overwriting an existing hand-created depends.txt, if onewas already present in the project’s source .egg-info directory.

A list of namespace package names, one per line, as supplied to thenamespace_packages keyword to setup(). Please see the manualsfor setuptools and pkg_resources for more information aboutnamespace packages.

This is a “sectioned” text file, whose contents encode theentry_points keyword supplied to setup(). All sections arenamed, as the section names specify the entry point groups in which thecorresponding section’s entry points are registered.

Each section is a sequence of “entry point” lines, each parseable usingthe EntryPoint.parse classmethod; please see the pkg_resourcesmanual for the complete entry point parsing syntax.

Note that it is not necessary to parse this file directly; thepkg_resources module provides a variety of APIs to locate and loadentry points automatically. Please see the setuptools andpkg_resources manuals for details on the nature and uses of entrypoints.

This directory is currently only created for .egg files built bythe setuptools bdist_egg command. It will contain copies of allof the project’s “traditional” scripts (i.e., those specified using thescripts keyword to setup()). This is so that they can bereconstituted when an .egg file is installed.

The scripts are placed here using the distutils’ standardinstall_scripts command, so any #! lines reflect the Pythoninstallation where the egg was built. But instead of copying thescripts to the local script installation directory, EasyInstall writesshort wrapper scripts that invoke the original scripts from inside theegg, after ensuring that sys.path includes the egg and any eggs itdepends on. For more about script wrappers, see the section below onInstallation and Path Management Issues.

A list of C extensions and other dynamic link libraries contained inthe egg, one per line. Paths are /-separated and relative to theegg’s base location.

This file is generated as part of bdist_egg processing, and as suchonly appears in .egg files (and .egg directories created byunpacking them). It is used to ensure that all libraries are extractedfrom a zipped egg at the same time, in case there is any direct linkagebetween them. Please see the Zip File Issues section below for moreinformation on library and resource extraction from .egg files.

A list of resource files and/or directories, one per line, as specifiedvia the eager_resources keyword to setup(). Paths are/-separated and relative to the egg’s base location.

Resource files or directories listed here will be extractedsimultaneously, if any of the named resources are extracted, or if anynative libraries listed in native_libs.txt are extracted. Pleasesee the setuptools manual for details on what this feature is used forand how it works, as well as the Zip File Issues section below.

These are zero-length files, and either one or the other should exist.If zip-safe exists, it means that the project will work properlywhen installed as an .egg zipfile, and conversely the existence ofnot-zip-safe means the project should not be installed as an.egg file. The zip_safe option to setuptools’ setup()determines which file will be written. If the option isn’t provided,setuptools attempts to make its own assessment of whether the packagecan work, based on code and content analysis.

If neither file is present at installation time, EasyInstall defaultsto assuming that the project should be unzipped. (Command-line optionsto EasyInstall, however, take precedence even over an existingzip-safe or not-zip-safe file.)

Note that these flag files appear only in .egg files generated bybdist_egg, and in .egg directories created by unpacking such an.egg file.

This file is a list of the top-level module or package names providedby the project, one Python identifier per line.

Subpackages are not included; a project containing both a foo.barand a foo.baz would include only one line, foo, in itstop_level.txt.

This data is used by pkg_resources at runtime to issue a warning ifan egg is added to sys.path when its contained packages may havealready been imported.

(It was also once used to detect conflicts with non-egg packages atinstallation time, but in more recent versions, setuptools installs eggsin such a way that they always override non-egg packages, thuspreventing a problem from arising.)

This file is roughly equivalent to the distutils’ MANIFEST file.The differences are as follows:

  • The filenames always use / as a path separator, which must beconverted back to a platform-specific path whenever they are read.

  • The file is automatically generated by setuptools whenever theegg_info or sdist commands are run, and it is notuser-editable.

Although this metadata is included with distributed eggs, it is notactually used at runtime for any purpose. Its function is to ensurethat setuptools-built source distributions can correctly discoverwhat files are part of the project’s source, even if the list had beengenerated using revision control metadata on the original author’ssystem.

In other words, SOURCES.txt has little or no runtime value for beingincluded in distributed eggs, and it is possible that future versions ofthe bdist_egg and install_egg_info commands will strip it beforeinstallation or distribution. Therefore, do not rely on its beingavailable outside of an original source directory or sourcedistribution.

Although zip files resemble directories, they are not fullysubstitutable for them. Most platforms do not support loading dynamiclink libraries contained in zipfiles, so it is not possible to directlyimport C extensions from .egg zipfiles. Similarly, there are manyexisting libraries – whether in Python or C – that require actualoperating system filenames, and do not work with arbitrary “file-like”objects or in-memory strings, and thus cannot operate directly on thecontents of zip files.

To address these issues, the pkg_resources module provides a“resource API” to support obtaining either the contents of a resource,or a true operating system filename for the resource. If the eggcontaining the resource is a directory, the resource’s real filenameis simply returned. However, if the egg is a zipfile, then theresource is first extracted to a cache directory, and the filenamewithin the cache is returned.

The cache directory is determined by the pkg_resources API; pleasesee the set_cache_path() and get_default_cache() documentationfor details.

Resources are extracted to a cache subdirectory whose name is basedon the enclosing .egg filename and the path to the resource. Ifthere is already a file of the correct name, size, and timestamp, itsfilename is returned to the requester. Otherwise, the desired file isextracted first to a temporary name generated usingmkstemp('.$extract',target_dir), and then its timestamp is set tomatch the one in the zip file, before renaming it to its final name.(Some collision detection and resolution code is used to handle thefact that Windows doesn’t overwrite files when renaming.)

If a resource directory is requested, all of its contents arerecursively extracted in this fashion, to ensure that the directoryname can be used as if it were valid all along.

If the resource requested for extraction is listed in thenative_libs.txt or eager_resources.txt metadata files, thenall resources listed in either file will be extracted before therequested resource’s filename is returned, thus ensuring that allC extensions and data used by them will be simultaneously available.

Eggs Macronutrients

Since Python’s built-in zip import feature does not support loadingC extension modules from zipfiles, the setuptools bdist_egg commandgenerates special import wrappers to make it work.

The wrappers are .py files (along with corresponding .pycand/or .pyo files) that have the same module name as thecorresponding C extension. These wrappers are located in the samepackage directory (or top-level directory) within the zipfile, so thatsay, foomodule.so will get a corresponding foo.py, whilebar/baz.pyd will get a corresponding bar/baz.py.

These wrapper files contain a short stanza of Python code that askspkg_resources for the filename of the corresponding C extension,then reloads the module using the obtained filename. This will causepkg_resources to first ensure that all of the egg’s C extensions(and any accompanying “eager resources”) are extracted to the cachebefore attempting to link to the C library.

Mac Os Mojave

Note, by the way, that .egg directories will also contain thesewrapper files. However, Python’s default import priority is such thatC extensions take precedence over same-named Python modules, so theimport wrappers are ignored unless the egg is a zipfile.

Python’s initial setup of sys.path is very dependent on the Pythonversion and installation platform, as well as how Python was started(i.e., script vs. -c vs. -m vs. interactive interpreter).In fact, Python also provides only two relatively robust ways to affectsys.path outside of direct manipulation in code: the PYTHONPATHenvironment variable, and .pth files.

However, with no cross-platform way to safely and persistently changeenvironment variables, this leaves .pth files as EasyInstall’s onlyreal option for persistent configuration of sys.path.

But .pth files are rather strictly limited in what they are allowedto do normally. They add directories only to the end of sys.path,after any locally-installed site-packages directory, and they areonly processed in the site-packages directory to start with.

This is a double whammy for users who lack write access to thatdirectory, because they can’t create a .pth file that Python willread, and even if a sympathetic system administrator adds one for themthat calls site.addsitedir() to allow some other directory tocontain .pth files, they won’t be able to install newer versions ofanything that’s installed in the systemwide site-packages, becausetheir paths will still be added aftersite-packages.

So EasyInstall applies two workarounds to solve these problems.

The first is that EasyInstall leverages .pth files’ “import” featureto manipulate sys.path and ensure that anything EasyInstall addsto a .pth file will always appear before both the standard libraryand the local site-packages directories. Thus, it is alwayspossible for a user who can write a Python-read .pth file to ensurethat their packages come first in their own environment.

Second, when installing to a PYTHONPATH directory (as opposed toa “site” directory like site-packages) EasyInstall will also installa special version of the site module. Because it’s in aPYTHONPATH directory, this module will get control before thestandard library version of site does. It will record the state ofsys.path before invoking the “real” site module, and thenafterwards it processes any .pth files found in PYTHONPATHdirectories, including all the fixups needed to ensure that eggs alwaysappear before the standard library in sys.path, but are in a relativeorder to one another that is defined by their PYTHONPATH and.pth-prescribed sequence.

The net result of these changes is that sys.path order will beas follows at runtime:

  1. The sys.argv[0] directory, or an empty string if no scriptis being executed.

  2. All eggs installed by EasyInstall in any .pth file in eachPYTHONPATH directory, in order first by PYTHONPATH order,then normal .pth processing order (which is to say alphabeticalby .pth filename, then by the order of listing within each.pth file).

  3. All eggs installed by EasyInstall in any .pth file in each “site”directory (such as site-packages), following the same orderingrules as for the ones on PYTHONPATH.

  4. The PYTHONPATH directories themselves, in their original order

  5. Any paths from .pth files found on PYTHONPATH that were noteggs installed by EasyInstall, again following the same relativeordering rules.

  6. The standard library and “site” directories, along with the contentsof any .pth files found in the “site” directories.

Notice that sections 1, 4, and 6 comprise the “normal” Python setup forsys.path. Sections 2 and 3 are inserted to support eggs, andsection 5 emulates what the “normal” semantics of .pth files onPYTHONPATH would be if Python natively supported them.

For further discussion of the tradeoffs that went into this design, aswell as notes on the actual magic inserted into .pth files to makethem do these things, please see also the following messages to thedistutils-SIG mailing list:

EasyInstall never directly installs a project’s original scripts toa script installation directory. Instead, it writes short wrapperscripts that first ensure that the project’s dependencies are activeon sys.path, before invoking the original script. These wrappershave a #! line that points to the version of Python that was used toinstall them, and their second line is always a comment that indicatesthe type of script wrapper, the project version required for the scriptto run, and information identifying the script to be invoked.

The format of this marker line is:

The script_type is one of SCRIPT, DEV-SCRIPT, orENTRY-SCRIPT. The tuple_of_strings is a comma-separatedsequence of Python string constants. For SCRIPT and DEV-SCRIPTwrappers, there are two strings: the project version requirement, andthe script name (as a filename within the scripts metadatadirectory). For ENTRY-SCRIPT wrappers, there are three:the project version requirement, the entry point group name, and theentry point name. (See the “Automatic Script Creation” section in thesetuptools manual for more information about entry point scripts.)

In each case, the project version requirement string will be a stringparseable with the pkg_resources modules’ Requirement.parse()classmethod. The only difference between a SCRIPT wrapper and aDEV-SCRIPT is that a DEV-SCRIPT actually executes the originalsource script in the project’s source tree, and is created when the“setup.py develop” command is run. A SCRIPT wrapper, on the otherhand, uses the “installed” script written to the EGG-INFO/scriptssubdirectory of the corresponding .egg zipfile or directory.(.egg-info eggs do not have script wrappers associated with them,except in the “setup.py develop” case.)

The purpose of including the marker line in generated script wrappers isto facilitate introspection of installed scripts, and their relationshipto installed eggs. For example, an uninstallation tool could use thisdata to identify what scripts can safely be removed, and/or identifywhat scripts would stop working if a particular egg is uninstalled.

Background

I like to use OS X for as much as possible when doing assessments, but on a recent Android test I had a hell of a time getting Drozer installed. I finally got it working and figured I’d share the steps in case anyone else out there runs into the same problems I had.

If you’re not familiar, Drozer is an awesome attack and testing framework for Android. You can read more about it here: https://labs.mwrinfosecurity.com/tools/drozer/ or on its main GitHub page https://github.com/mwrlabs/drozer

It’s written in Python and you can download the egg file. Since I do most of my android testing from Mac (with Genymotion and Burp), I figured I would just download the Drozer egg and install it with my native Python. The installation instructions don’t mention OS X, but they seemed simple enough for Linux (just using easy_install).

Turns out there’s quite a few dependency issues which were a pain to resolve. I’m gonna walk through the steps I took to finally get it up and running.

Dependency Hell

If you just download the egg and try to use “easy_install” on Mac, you’ll get some spectacular error codes when trying to install the dependencies. Drozer requires the following python modules:

The root of the problems is in pyOpenSSL. OS X El Capitan doesn’t come with OpenSSL installed anymore, and trying to compile pyOpenSSL will fail because it can’t find the required headers.

Installing Dependencies

First of all, don’t try to use Mac’s built-in python. Install python with homebrew ($ brew install python) and make sure you can “pip install” modules without needing sudo. Secondly, since Drozer has some hard coded dependencies on specific versions, I opted to install everything in a python virtual environment. I prefer to use virtualenvwrapper to create and manger virtualenvs:

Install OpenSSL. Use brew to install OpenSSL back onto OS X El Capitan. If it’s already present, uninstall and reinstall it:

Compile pyOpenSSL. Unfortunately, Drozer requires a specific version of pyOpenSSL - and this version has a typo that prevents it from compiling successfully. This took me forever to figure out until I saw a similar error and the fix here. We need to download the source for pyOpenSSL v0.13 then fix the typo (using sed):

The sed command fixes the typo (‘dup’ vs ‘dupe’). Next we need to build pyOpenSSL, but need to specify the location of the OpenSSL headers we installed from brew (using build_ext the ‘-L’ and ‘-I’ options):

Note: make sure you are in your drozer virtualenv before doing the build/install steps!

Install other dependencies. Once pyOpenSSL v0.13 is installed in the virtualenv, use easy_install to install the other dependencies:

Install Drozer. Finally, download the latest Drozer egg file from here: https://www.mwrinfosecurity.com/products/drozer/. Still inside your drozer virtualenv, use easy_install to install it. If all goes right it should work with no errors:

Running Drozer

You can now always run drozer from the virtual environment you created. Since I get sick of switching to virtual environments, it’s possible to just create a shortcut to run drozer from the virtual environment it’s in.

Create the file /usr/local/bin/drozer (or wherever you want the shortcut to be). For the shebang, put the absolute path the python executable for the drozer virtual environment. The file should look like this:

Now you have a command “drozer” in your path and can run it anywhere:

Hope this helps somebody! Happy android hacking :)

-ropnop

See also