<div dir="ltr"><span style="font-size:12.8px">> Here's an example I've just run into that involves a == dependency on</span><br style="font-size:12.8px"><span style="font-size:12.8px">a public package: I have a library that needs to access some C API</span><br style="font-size:12.8px"><span style="font-size:12.8px">calls on Windows, but not on other platforms. The natural way to do</span><br style="font-size:12.8px"><span style="font-size:12.8px">this is to split out the CFFI code into its own package,</span><br style="font-size:12.8px"><span style="font-size:12.8px">_mylib_windows_helper or whatever, that has zero public interface, and</span><br style="font-size:12.8px"><span style="font-size:12.8px">have mylib v1.2.3 require "_mylib_windows_helper==1.2.3; os_name ==</span><br style="font-size:12.8px"><span style="font-size:12.8px">'nt'". </span><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">You have a public library, that, depending on the platform, depends on a public (helper) library that has no public interface? That doesn't sound good to me. If you don't want to implement a public interface then it should just be included in the main library because it is in the end a requirement of the library. It's a pity you can't have a universal wheel but so be it. Choosing to depend on an exact version of a package that has no public interfance is in my opinion the wrong solution.<br></span><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">As I stated before, though perhaps not explicitly, I cannot think of *any* good reason that one uses == in `install_requires`. Something like `>= 1.7, < 1.8` should be sufficient. In the CFFI case that should be sufficient unless you change your function signatures in a maintenance release (which is bad). And in case of a metapackage like </span><span style="font-size:12.8px">PyObjC this should also be sufficient because it will downgrade dependencies when downgrading the metapackage while still giving you the latest maintenance releases of the dependencies.</span></div></div><div><br></div><div><span style="font-size:12.8px">Regarding 'application', 'library', and 'metapackage'. In Nixpkgs we distinguish Python libraries and applications. Applications are available for 1 version of the interpreter, whereas libraries are available for all (supported) interpreter versions. It's nice if it were more explicit on say PyPI whether a package is a library or an application. There are difficult cases though, e.g., `ipython`. Is that an application or a library? As user I would argue that it is an application, however, it should be available for each version of the interpreter and that's why we branded it a library.</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">Metapackages. `jupyter` is a metapackage. We had to put it with the rest of the Python libraries for the same reason as we put `ipython` there. From a</span><span style="font-size:12.8px"> distributions' point of view I don't see why you would want to have them mentioned separately. </span></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Feb 23, 2017 at 12:49 PM, Nathaniel Smith <span dir="ltr"><<a href="mailto:njs@pobox.com" target="_blank">njs@pobox.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Thu, Feb 23, 2017 at 12:44 AM, Nick Coghlan <<a href="mailto:ncoghlan@gmail.com">ncoghlan@gmail.com</a>> wrote:<br>
> On 23 February 2017 at 18:37, Paul Moore <<a href="mailto:p.f.moore@gmail.com">p.f.moore@gmail.com</a>> wrote:<br>
>><br>
>> On 23 February 2017 at 08:18, Nick Coghlan <<a href="mailto:ncoghlan@gmail.com">ncoghlan@gmail.com</a>> wrote:<br>
>> > I'm not a huge fan of having simple boolean toggles in metadata<br>
>> > definitions<br>
>> > (hence the more elaborate idea of two different kinds of dependency<br>
>> > declaration), but this may be a case where that's a good way to go,<br>
>> > since it<br>
>> > would mean that services and tools that care can check it (with a<br>
>> > recommendation in the spec saying that public index servers SHOULD check<br>
>> > it), while those that don't care would continue to have a single unified<br>
>> > set<br>
>> > of dependency declarations to work with.<br>
>><br>
>> While boolean metadata may not be ideal in the general case, I think<br>
>> it makes sense here. If you want to make it more acceptable, maybe<br>
>> make it Package-Type, with values "application" or "library".<br>
><br>
><br>
> That gets us back into the world of defining what the various package types<br>
> mean, and I really don't want to go there :)<br>
><br>
> Instead, I'm thinking in terms of a purely capability based field:<br>
> "allow_pinned_dependencies", with the default being "False", but actually<br>
> checking the field also only being a SHOULD for public index servers and a<br>
> MAY for everything else.<br>
><br>
> That would be enough for downstream tooling to pick up and say "I should<br>
> treat this as a multi-component module rather than as an individual<br>
> standalone component", *without* having to inflict the task of understanding<br>
> the complexities of multi-tier distribution systems onto all component<br>
> publishers :)<br>
<br>
</div></div>I'm still not sure I understand what you're trying to do, but this<br>
feels like you're trying to have it both ways... if you don't want to<br>
define what the different package types mean, and it's purely a<br>
capability-based field, then surely that means that downstream tooling<br>
*can't* make assumptions about what kind of package type it is based<br>
on the field? ISTM that from the point of view of downstream tooling,<br>
"allow_pinned_dependencies" carries literally no information, because<br>
all it means is "this package is on a public server and its<br>
Requires-Dist field has an == in it", which are things we already<br>
know. I can see how this would help your goal of educating uploaders<br>
about good package hygiene, but not how it helps downstream<br>
distributors.<br>
<br>
(Here's an example I've just run into that involves a == dependency on<br>
a public package: I have a library that needs to access some C API<br>
calls on Windows, but not on other platforms. The natural way to do<br>
this is to split out the CFFI code into its own package,<br>
_mylib_windows_helper or whatever, that has zero public interface, and<br>
have mylib v1.2.3 require "_mylib_windows_helper==1.2.3; os_name ==<br>
'nt'". That way I can distribute one pure-Python wheel + one binary<br>
wheel and everything just works. But there's no sense in which this is<br>
an "integrated application" or anything, it's just a single library<br>
that usually ships in one .whl but sometimes ships in 2 .whls.)<br>
<br>
((In actual fact I'm currently not building the package this way<br>
because setuptools makes it extremely painful to actually maintain<br>
that setup. Really I need the ability to build two wheels out of a<br>
single source package. Since we don't have that, I'm instead using<br>
CFFI's slow and semi-deprecated ABI mode, which lets me call C<br>
functions from a pure Python package. But what I described above is<br>
really the "right" solution, it's just tooling limitations that make<br>
it painful.))<br>
<span class="im HOEnZb"><br>
-n<br>
<br>
--<br>
Nathaniel J. Smith -- <a href="https://vorpus.org" rel="noreferrer" target="_blank">https://vorpus.org</a><br>
</span><div class="HOEnZb"><div class="h5">______________________________<wbr>_________________<br>
Distutils-SIG maillist  -  <a href="mailto:Distutils-SIG@python.org">Distutils-SIG@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/distutils-sig" rel="noreferrer" target="_blank">https://mail.python.org/<wbr>mailman/listinfo/distutils-sig</a><br>
</div></div></blockquote></div><br></div>