<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[147824] trunk/dports/python</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="https://trac.macports.org/changeset/147824">147824</a></dd>
<dt>Author</dt> <dd>stromnov@macports.org</dd>
<dt>Date</dt> <dd>2016-04-16 17:00:55 -0700 (Sat, 16 Apr 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>py-entrypoints: new port</pre>

<h3>Added Paths</h3>
<ul>
<li>trunk/dports/python/py-entrypoints/</li>
<li><a href="#trunkdportspythonpyentrypointsPortfile">trunk/dports/python/py-entrypoints/Portfile</a></li>
<li>trunk/dports/python/py-entrypoints/files/</li>
<li><a href="#trunkdportspythonpyentrypointsfilesentrypointspy">trunk/dports/python/py-entrypoints/files/entrypoints.py</a></li>
<li><a href="#trunkdportspythonpyentrypointsfilessetuppy">trunk/dports/python/py-entrypoints/files/setup.py</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkdportspythonpyentrypointsPortfile"></a>
<div class="addfile"><h4>Added: trunk/dports/python/py-entrypoints/Portfile (0 => 147824)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/dports/python/py-entrypoints/Portfile                                (rev 0)
+++ trunk/dports/python/py-entrypoints/Portfile        2016-04-17 00:00:55 UTC (rev 147824)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim: fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
+# $Id$
+
+PortSystem          1.0
+PortGroup           python 1.0
+
+name                py-entrypoints
+version             0.2
+revision            0
+categories-append   devel
+platforms           darwin
+license             BSD
+supported_archs     noarch
+
+python.versions     27 34 35
+
+maintainers         stromnov openmaintainer
+
+description         Discover and load entry points from installed packages.
+long_description    ${description}
+
+homepage            https://github.com/takluyver/entrypoints
+master_sites        pypi:[string index ${python.rootname} 0]/${python.rootname}
+
+distfiles
+
+if {${name} ne ${subport}} {
+
+    post-extract {
+        file mkdir ${worksrcpath}
+        file copy ${filespath}/setup.py ${filespath}/entrypoints.py ${worksrcpath}
+    }
+
+    livecheck.type      none
+} else {
+    livecheck.type      pypi
+}
</ins><span class="cx">Property changes on: trunk/dports/python/py-entrypoints/Portfile
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkdportspythonpyentrypointsfilesentrypointspy"></a>
<div class="addfile"><h4>Added: trunk/dports/python/py-entrypoints/files/entrypoints.py (0 => 147824)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/dports/python/py-entrypoints/files/entrypoints.py                                (rev 0)
+++ trunk/dports/python/py-entrypoints/files/entrypoints.py        2016-04-17 00:00:55 UTC (rev 147824)
</span><span class="lines">@@ -0,0 +1,204 @@
</span><ins>+&quot;&quot;&quot;Discover and load entry points from installed packages.&quot;&quot;&quot;
+import configparser
+from contextlib import contextmanager
+import glob
+from importlib import import_module
+import io
+import itertools
+import os.path as osp
+import re
+import sys
+import warnings
+import zipfile
+
+entry_point_pattern = re.compile(r&quot;&quot;&quot;
+(?P&lt;modulename&gt;\w+(\.\w+)*)
+(:(?P&lt;objectname&gt;\w+(\.\w+)*))?
+\s*
+(\[(?P&lt;extras&gt;.+)\])?
+$
+&quot;&quot;&quot;, re.VERBOSE)
+
+__version__ = '0.2'
+
+class BadEntryPoint(Exception):
+    &quot;&quot;&quot;Raised when an entry point can't be parsed.
+    &quot;&quot;&quot;
+    def __init__(self, epstr):
+        self.epstr = epstr
+
+    def __str__(self):
+        return &quot;Couldn't parse entry point spec: %r&quot; % self.epstr
+
+    @staticmethod
+    @contextmanager
+    def err_to_warnings():
+        try:
+            yield
+        except BadEntryPoint as e:
+            warnings.warn(str(e))
+
+class NoSuchEntryPoint(Exception):
+    &quot;&quot;&quot;Raised by :func:`get_single` when no matching entry point is found.&quot;&quot;&quot;
+    def __init__(self, group, name):
+        self.group = group
+        self.name = name
+
+    def __str__(self):
+        return &quot;No {!r} entry point found in group {!r}&quot;.format(self.name, self.group)
+
+
+class EntryPoint(object):
+    def __init__(self, name, module_name, object_name, extras=None, distro=None):
+        self.name = name
+        self.module_name = module_name
+        self.object_name = object_name
+        self.extras = extras
+        self.distro = distro
+
+    def __repr__(self):
+        return &quot;EntryPoint(%r, %r, %r, %r)&quot; % \
+            (self.name, self.module_name, self.object_name, self.distro)
+
+    def load(self):
+        &quot;&quot;&quot;Load the object to which this entry point refers.
+        &quot;&quot;&quot;
+        mod = import_module(self.module_name)
+        obj = mod
+        if self.object_name:
+            for attr in self.object_name.split('.'):
+                obj = getattr(obj, attr)
+        return obj
+    
+    @classmethod
+    def from_string(cls, epstr, name, distro=None):
+        &quot;&quot;&quot;Parse an entry point from the syntax in entry_points.txt
+
+        :param str epstr: The entry point string (not including 'name =')
+        :param str name: The name of this entry point
+        :param Distribution distro: The distribution in which the entry point was found
+        :rtype: EntryPoint
+        :raises BadEntryPoint: if *epstr* can't be parsed as an entry point.
+        &quot;&quot;&quot;
+        m = entry_point_pattern.match(epstr)
+        if m:
+            mod, obj, extras = m.group('modulename', 'objectname', 'extras')
+            if extras is not None:
+                extras = re.split(',\s*', extras)
+            return cls(name, mod, obj, extras, distro)
+        else:
+            raise BadEntryPoint(epstr)
+
+class Distribution(object):
+    def __init__(self, name, version):
+        self.name = name
+        self.version = version
+    
+    def __repr__(self):
+        return &quot;Distribution(%r, %r)&quot; % (self.name, self.version)
+
+
+def iter_files_distros(path=None, repeated_distro='first'):
+    if path is None:
+        path = sys.path
+
+    # Distributions found earlier in path will shadow those with the same name
+    # found later. If these distributions used different module names, it may
+    # actually be possible to import both, but in most cases this shadowing
+    # will be correct.
+    distro_names_seen = set()
+
+    for folder in path:
+        if folder.rstrip('/\\').endswith('.egg'):
+            # Gah, eggs
+            egg_name = osp.basename(folder)
+            if '-' in egg_name:
+                distro = Distribution(*egg_name.split('-')[:2])
+
+                if (repeated_distro == 'first') \
+                        and (distro.name in distro_names_seen):
+                    continue
+                distro_names_seen.add(distro.name)
+            else:
+                distro = None
+            
+            if osp.isdir(folder):
+                ep_path = osp.join(folder, 'EGG-INFO', 'entry_points.txt')
+                if osp.isfile(ep_path):
+                    cp = configparser.ConfigParser()
+                    cp.read(ep_path)
+                    yield cp, distro
+
+            elif zipfile.is_zipfile(folder):
+                z = zipfile.ZipFile(folder)
+                try:
+                    info = z.getinfo('EGG-INFO/entry_points.txt')
+                except KeyError:
+                    continue
+                cp = configparser.ConfigParser()
+                with z.open(info) as f:
+                    fu = io.TextIOWrapper(f)
+                    cp.read_file(fu,
+                        source=osp.join(folder, 'EGG-INFO', 'entry_points.txt'))
+                yield cp, distro
+            
+        for path in itertools.chain(
+            glob.iglob(osp.join(folder, '*.dist-info', 'entry_points.txt')),
+            glob.iglob(osp.join(folder, '*.egg-info', 'entry_points.txt'))
+        ):
+            distro_name_version = osp.splitext(osp.basename(osp.dirname(path)))[0]
+            if '-' in distro_name_version:
+                distro = Distribution(*distro_name_version.split('-', 1))
+
+                if (repeated_distro == 'first') \
+                        and (distro.name in distro_names_seen):
+                    continue
+                distro_names_seen.add(distro.name)
+            else:
+                distro = None
+            cp = configparser.ConfigParser()
+            cp.read(path)
+            yield cp, distro
+
+def get_single(group, name, path=None):
+    &quot;&quot;&quot;Find a single entry point.
+
+    Returns an :class:`EntryPoint` object, or raises :exc:`NoSuchEntryPoint`
+    if no match is found.
+    &quot;&quot;&quot;
+    for config, distro in iter_files_distros(path=path):
+        if (group in config) and (name in config[group]):
+            epstr = config[group][name]
+            with BadEntryPoint.err_to_warnings():
+                return EntryPoint.from_string(epstr, name, distro)
+
+    raise NoSuchEntryPoint(group, name)
+
+def get_group_named(group, path=None):
+    &quot;&quot;&quot;Find a group of entry points with unique names.
+
+    Returns a dictionary of names to :class:`EntryPoint` objects.
+    &quot;&quot;&quot;
+    result = {}
+    for ep in get_group_all(group, path=path):
+        if ep.name not in result:
+            result[ep.name] = ep
+    return result
+
+def get_group_all(group, path=None):
+    &quot;&quot;&quot;Find all entry points in a group.
+
+    Returns a list of :class:`EntryPoint` objects.
+    &quot;&quot;&quot;
+    result = []
+    for config, distro in iter_files_distros(path=path):
+        if group in config:
+            for name, epstr in config[group].items():
+                with BadEntryPoint.err_to_warnings():
+                    result.append(EntryPoint.from_string(epstr, name, distro))
+
+    return result
+
+if __name__ == '__main__':
+    import pprint
+    pprint.pprint(get_group_all('console_scripts'))
</ins></span></pre></div>
<a id="trunkdportspythonpyentrypointsfilessetuppy"></a>
<div class="addfile"><h4>Added: trunk/dports/python/py-entrypoints/files/setup.py (0 => 147824)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/dports/python/py-entrypoints/files/setup.py                                (rev 0)
+++ trunk/dports/python/py-entrypoints/files/setup.py        2016-04-17 00:00:55 UTC (rev 147824)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+from distutils.core import setup
+
+setup(
+    name='entrypoints',
+    version='0.2',
+    description='Discover and load entry points from installed packages.',
+    author='Thomas Kluyver',
+    author_email='thomas@kluyver.me.uk',
+    url='https://github.com/takluyver/entrypoints',
+    py_modules=['entrypoints'],
+)
</ins></span></pre>
</div>
</div>

</body>
</html>