Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add messaging and tests around the new Anaconda TOS #14

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ or:

CLI interface for `conda-mirror.py`

```
```shell
usage: conda-mirror [-h] [--upstream-channel UPSTREAM_CHANNEL]
[--target-directory TARGET_DIRECTORY]
[--temp-directory TEMP_DIRECTORY] [--platform PLATFORM]
Expand All @@ -42,7 +42,7 @@ optional arguments:
--upstream-channel UPSTREAM_CHANNEL
The target channel to mirror. Can be a channel on
anaconda.org like "conda-forge" or a full qualified
channel like "https://repo.continuum.io/pkgs/free/"
channel like "https://repo.anaconda.com/pkgs/free/"
--target-directory TARGET_DIRECTORY
The place where packages should be mirrored to
--temp-directory TEMP_DIRECTORY
Expand Down Expand Up @@ -196,7 +196,7 @@ plugins: xonsh-0.5.2, ordering-0.4
collected 4 items

test/test_conda_mirror.py::test_match PASSED
test/test_conda_mirror.py::test_cli[https://repo.continuum.io/pkgs/free-linux-64] PASSED
test/test_conda_mirror.py::test_cli[https://repo.anaconda.com/pkgs/free-linux-64] PASSED
test/test_conda_mirror.py::test_cli[conda-forge-linux-64] PASSED
test/test_conda_mirror.py::test_handling_bad_package PASSED

Expand Down
66 changes: 59 additions & 7 deletions conda_mirror/conda_mirror.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
import multiprocessing
import os
import pdb
import random
import shutil
import sys
import tarfile
import tempfile
import textwrap
import time
import random
from pprint import pformat

import requests
Expand Down Expand Up @@ -50,7 +51,7 @@ def _maybe_split_channel(channel):
channel : str
The name-only channel. If the channel input param is something like
"conda-forge", then "conda-forge" will be returned. If the channel
input param is something like "https://repo.continuum.io/pkgs/free/"
input param is something like "https://repo.anaconda.com/pkgs/free/"

"""
# strip trailing slashes
Expand All @@ -74,9 +75,17 @@ def _maybe_split_channel(channel):
def _match(all_packages, key_glob_dict):
"""

Parameters
----------
all_packages : iterable
platform = 'linux-64'
channel = 'conda-forge'
target_directory = tmpdir.mkdir(platform)
temp_directory = tmpdir.mkdir(join(platform, 'temp'))
ret = conda_mirror.main(
upstream_channel=channel,
platform=platform,
target_directory=target_directory.strpath,
temp_directory=temp_directory.strpath,
dry_run=True
)
Iterable of package metadata dicts from repodata.json
key_glob_dict : iterable of kv pairs
Iterable of (key, glob_value) dicts
Expand Down Expand Up @@ -133,7 +142,7 @@ def _make_arg_parser():
'--upstream-channel',
help=('The target channel to mirror. Can be a channel on anaconda.org '
'like "conda-forge" or a full qualified channel like '
'"https://repo.continuum.io/pkgs/free/"'),
'"https://repo.anaconda.com/pkgs/free/"'),
)
ap.add_argument(
'--target-directory',
Expand Down Expand Up @@ -233,6 +242,20 @@ def _make_arg_parser():
default=100,
dest="max_retries",
)
ap.add_argument(
'--Anaconda-business-customer',
help=("Use this flag if you have an existing commercial relationship with Anaconda"),
action="store_true",
default=False,
dest='Anaconda_business_customer'
)
ap.add_argument(
'--not-a-commercial-entity',
help=("Use this flag if you have are a nonprofit or otherwise not a commercial entity"),
action="store_true",
default=False,
dest='not_a_commercial_entity'
)
return ap


Expand Down Expand Up @@ -327,6 +350,35 @@ def pdb_hook(exctype, value, traceback):
else:
url = '{}:{}'.format(scheme, url[0])
proxies = {scheme: url}

Anaconda_business_customer = args.Anaconda_business_customer
not_a_commercial_entity = args.not_a_commercial_entity
# if you are trying to mirror repo.anaconda.com and you are a commercial entity or
# you do not have a commercial relationship with anaconda, then:
anaconda_channel = ('anaconda.com' in args.upstream_channel or
'continuum.io' in args.upstream_channel)
if anaconda_channel and not (not_a_commercial_entity or Anaconda_business_customer):
message = textwrap.dedent("""
Will not mirror repo.anaconda.com until you acknowledge that
(a) you are not a commercial entity
(add `not_a_commercial_entity: True` to your mirror config or
pass --not-a-commercial-entity on the CLI)
(b) you have a commercial relationship with anaconda
(add `Anaconda_business_customer: True` to your mirror config or
pass --Anaconda-business-customer on the CLI).
Please see the Anaconda Terms of Service at https://know.anaconda.com/TOS.html
for more information. Or reach out to [email protected] for commercial interest.
We, as the conda-mirror maintainers, encourage you to financially support Anaconda
if you find value from the packages they provide at repo.anaconda.com. We do not support
knowingly breaking their terms of service. We cannot prevent you from breaking their
terms of service, but we can at least force you to acknowledge that you are breaking
their terms of service if you are a commercial entity and you do not have a business
relationship with them. If you are a non-profit, scientific / research lab then you may
disregard this message as we are confident that Anaconda wants you to continue doing
the work you're doing.""")
logger.error(message)
raise RuntimeError(message)

return {
'upstream_channel': args.upstream_channel,
'target_directory': args.target_directory,
Expand Down Expand Up @@ -666,7 +718,7 @@ def main(upstream_channel, target_directory, temp_directory, platform,
upstream_channel : str
The anaconda.org channel that you want to mirror locally
e.g., "conda-forge" or
the defaults channel at "https://repo.continuum.io/pkgs/free"
the defaults channel at "https://repo.anaconda.com/pkgs/free"
target_directory : str
The path on disk to produce a local mirror of the upstream channel.
Note that this is the directory that contains the platform
Expand Down
42 changes: 37 additions & 5 deletions test/test_conda_mirror.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import bz2
import copy
import itertools
import json
import os
import sys
Expand Down Expand Up @@ -47,14 +46,14 @@ def _get_smallest_packages(packages, num=1):


@pytest.mark.parametrize(
'channel,platform',
itertools.product([anaconda_channel, 'conda-forge'], ['linux-64']))
@pytest.mark.parametrize('num_threads', [0, 1, 4])
'channel,platform,num_threads',
((anaconda_channel, 'linux-64', 0),
('conda-forge', 'linux-64', 1)))
def test_cli(tmpdir, channel, platform, repodata, num_threads):
info, packages = repodata[channel]
smallest_package, = _get_smallest_packages(packages)
# drop the html stuff. get just the channel

# drop the html stuff. get just the channel
f2 = tmpdir.mkdir(channel.rsplit('/', 1)[-1])
f2.mkdir(platform)
f1 = tmpdir.mkdir('conf').join('conf.yaml')
Expand All @@ -79,6 +78,8 @@ def test_cli(tmpdir, channel, platform, repodata, num_threads):
target_directory=f2.strpath,
platform=platform,
num_threads=num_threads)
if 'anaconda.com' in channel or 'continuum.io' in channel:
cli_args += " --not-a-commercial-entity"
old_argv = copy.deepcopy(sys.argv)
sys.argv = cli_args.split(' ')
# Write a package that does not exist in the upstream repodata into the
Expand Down Expand Up @@ -175,3 +176,34 @@ def test_dry_run_dumb(tmpdir):
dry_run=True
)
assert len(ret['to-mirror']) > 1, "We should have a great deal of packages slated to download"


@pytest.mark.parametrize(
'channel', ('https://repo.anaconda.com/pkgs/main',
'https://repo.continuum.io/pkgs./main',
'conda-forge',
'bioconda'))
def test_TOS(tmpdir, channel):
platform = 'linux-64'
# drop the html stuff. get just the channel
f2 = tmpdir.mkdir(channel.rsplit('/', 1)[-1])
f2.mkdir(platform)

cli_args = ("conda-mirror"
" --config example-conf.yaml"
" --upstream-channel {channel}"
" --target-directory {target_directory}"
" --platform {platform}"
" -vvv"
).format(channel=channel,
target_directory=f2.strpath,
platform=platform)
old_argv = copy.deepcopy(sys.argv)
sys.argv = cli_args.split(' ')
should_raise = 'anaconda.com' in channel or 'continuum.io' in channel
if should_raise:
with pytest.raises(RuntimeError):
conda_mirror._parse_and_format_args()
else:
conda_mirror._parse_and_format_args()
sys.argv = old_argv