From f795173b51a6679f3999a888a933364c5fbc6e35 Mon Sep 17 00:00:00 2001 From: Alok Singh <8325708+alok@users.noreply.github.com> Date: Sun, 20 May 2018 16:15:06 -0700 Subject: [PATCH] Use flake8-comprehensions (#1976) * Add flake8 to Travis * Add flake8-comprehensions [flake8 plugin](https://github.com/adamchainz/flake8-comprehensions) that checks for useless constructions. * Use generators instead of lists where appropriate A lot of the builtins can take in generators instead of lists. This commit applies `flake8-comprehensions` to find them. * Fix lint error * Fix some string formatting The rest can be fixed in another PR * Fix compound literals syntax This should probably be merged after #1963. * dict() -> {} * Use dict literal syntax dict(...) -> {...} * Rewrite nested dicts * Fix hanging indent * Add missing import * Add missing quote * fmt * Add missing whitespace * rm duplicate pip install This is already installed in another file. * Fix indent * move `merge_dicts` into utils * Bring up to date with `master` * Add automatic syntax upgrade * rm pyupgrade In case users want to still use it on their own, the upgrade-syn.sh script was left in the `.travis` dir. --- .travis/install-dependencies.sh | 2 +- .travis/upgrade-syn.sh | 27 +++++ examples/cython/cython_main.py | 2 +- examples/resnet/resnet_main.py | 2 +- examples/streaming/streaming.py | 2 +- python/ray/actor.py | 4 +- python/ray/autoscaler/aws/config.py | 10 +- python/ray/autoscaler/aws/node_provider.py | 2 +- python/ray/dataframe/concat.py | 8 +- python/ray/dataframe/dataframe.py | 44 ++++--- python/ray/dataframe/io.py | 109 +++++++++--------- python/ray/dataframe/test/test_dataframe.py | 2 +- python/ray/dataframe/utils.py | 4 +- .../experimental/array/distributed/core.py | 2 +- python/ray/experimental/state.py | 14 +-- python/ray/experimental/tfutils.py | 9 +- python/ray/experimental/ui.py | 9 +- python/ray/global_scheduler/test/test.py | 17 +-- python/ray/monitor.py | 2 +- python/ray/rllib/a3c/tfpolicy.py | 4 +- python/ray/rllib/ddpg/apex.py | 47 ++++---- python/ray/rllib/ddpg/ddpg.py | 81 ++++++------- python/ray/rllib/dqn/apex.py | 48 ++++---- python/ray/rllib/dqn/dqn.py | 71 ++++++------ python/ray/rllib/es/es.py | 33 +++--- python/ray/rllib/es/policies.py | 6 +- python/ray/rllib/models/catalog.py | 8 +- python/ray/rllib/optimizers/replay_buffer.py | 2 +- python/ray/signature.py | 4 +- python/ray/test/test_utils.py | 2 +- python/ray/tune/hyperband.py | 2 +- python/ray/tune/median_stopping_rule.py | 2 +- python/ray/tune/test/tune_server_test.py | 5 +- python/ray/utils.py | 7 ++ test/actor_test.py | 2 +- test/runtest.py | 4 +- test/tensorflow_test.py | 4 +- 37 files changed, 330 insertions(+), 273 deletions(-) create mode 100755 .travis/upgrade-syn.sh diff --git a/.travis/install-dependencies.sh b/.travis/install-dependencies.sh index 245f43e5337c5..aee57448eadf6 100755 --- a/.travis/install-dependencies.sh +++ b/.travis/install-dependencies.sh @@ -77,7 +77,7 @@ elif [[ "$LINT" == "1" ]]; then bash miniconda.sh -b -p $HOME/miniconda export PATH="$HOME/miniconda/bin:$PATH" # Install Python linting tools. - pip install -q flake8 + pip install -q flake8 flake8-comprehensions elif [[ "$LINUX_WHEELS" == "1" ]]; then sudo apt-get install docker sudo usermod -a -G docker travis diff --git a/.travis/upgrade-syn.sh b/.travis/upgrade-syn.sh new file mode 100755 index 0000000000000..8bfaacd3912ed --- /dev/null +++ b/.travis/upgrade-syn.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# Cause the script to exit if a single command fails +set -eo pipefail + +# this stops git rev-parse from failing if we run this from the .git directory +builtin cd "$(dirname "${BASH_SOURCE:-$0}")" + +ROOT="$(git rev-parse --show-toplevel)" +builtin cd "$ROOT" + +find \ + python test \ + -name '*.py' -type f \ + -not -path 'python/ray/cloudpickle/*' \ + -not -path 'python/ray/dataframe/*' \ + -exec python -m pyupgrade {} + + +if ! git diff --quiet; then + echo 'Reformatted staged files. Please review and stage the changes.' + echo 'Files updated:' + echo + + git --no-pager diff --name-only + + exit 1 +fi diff --git a/examples/cython/cython_main.py b/examples/cython/cython_main.py index f01e937f8db99..1d8b9baf4b6c3 100644 --- a/examples/cython/cython_main.py +++ b/examples/cython/cython_main.py @@ -26,7 +26,7 @@ def run_func(func, *args, **kwargs): return result -@click.group(context_settings=dict(help_option_names=["-h", "--help"])) +@click.group(context_settings={'help_option_names': ['-h', '--help']}) def cli(): """Working with Cython actors and functions in Ray""" diff --git a/examples/resnet/resnet_main.py b/examples/resnet/resnet_main.py index 5175b6de374b5..0e052966e695d 100644 --- a/examples/resnet/resnet_main.py +++ b/examples/resnet/resnet_main.py @@ -220,7 +220,7 @@ def train(): while True: all_weights = ray.get([actor.compute_steps.remote(weight_id) for actor in train_actors]) - mean_weights = {k: (sum([weights[k] for weights in all_weights]) / + mean_weights = {k: (sum(weights[k] for weights in all_weights) / num_gpus) for k in all_weights[0]} weight_id = ray.put(mean_weights) diff --git a/examples/streaming/streaming.py b/examples/streaming/streaming.py index 92184ef9dc618..b4153af3d95c4 100644 --- a/examples/streaming/streaming.py +++ b/examples/streaming/streaming.py @@ -92,7 +92,7 @@ def next(self): article_index = 0 while True: print("article index = {}".format(article_index)) - wordcounts = dict() + wordcounts = {} counts = ray.get([reducer.next_reduce_result.remote(article_index) for reducer in reducers]) for count in counts: diff --git a/python/ray/actor.py b/python/ray/actor.py index 9264a4fd053b6..ea29780024fa6 100644 --- a/python/ray/actor.py +++ b/python/ray/actor.py @@ -491,8 +491,8 @@ def pred(x): # Extract the signatures of each of the methods. This will be used # to catch some errors if the methods are called with inappropriate # arguments. - self._method_signatures = dict() - self._actor_method_num_return_vals = dict() + self._method_signatures = {} + self._actor_method_num_return_vals = {} for method_name, method in self._actor_methods: # Print a warning message if the method signature is not # supported. We don't raise an exception because if the actor diff --git a/python/ray/autoscaler/aws/config.py b/python/ray/autoscaler/aws/config.py index 0c9715b10df28..97d3337839a05 100644 --- a/python/ray/autoscaler/aws/config.py +++ b/python/ray/autoscaler/aws/config.py @@ -145,10 +145,8 @@ def _configure_key_pair(config): def _configure_subnet(config): ec2 = _resource("ec2", config) subnets = sorted( - [ - s for s in ec2.subnets.all() - if s.state == "available" and s.map_public_ip_on_launch - ], + (s for s in ec2.subnets.all() + if s.state == "available" and s.map_public_ip_on_launch), reverse=True, # sort from Z-A key=lambda subnet: subnet.availability_zone) if not subnets: @@ -293,11 +291,11 @@ def _get_key(key_name, config): def _client(name, config): - boto_config = Config(retries=dict(max_attempts=BOTO_MAX_RETRIES)) + boto_config = Config(retries={'max_attempts': BOTO_MAX_RETRIES}) return boto3.client(name, config["provider"]["region"], config=boto_config) def _resource(name, config): - boto_config = Config(retries=dict(max_attempts=BOTO_MAX_RETRIES)) + boto_config = Config(retries={'max_attempts': BOTO_MAX_RETRIES}) return boto3.resource( name, config["provider"]["region"], config=boto_config) diff --git a/python/ray/autoscaler/aws/node_provider.py b/python/ray/autoscaler/aws/node_provider.py index cec58fa8f39e1..9a887df7a55f4 100644 --- a/python/ray/autoscaler/aws/node_provider.py +++ b/python/ray/autoscaler/aws/node_provider.py @@ -13,7 +13,7 @@ class AWSNodeProvider(NodeProvider): def __init__(self, provider_config, cluster_name): NodeProvider.__init__(self, provider_config, cluster_name) - config = Config(retries=dict(max_attempts=BOTO_MAX_RETRIES)) + config = Config(retries={'max_attempts': BOTO_MAX_RETRIES}) self.ec2 = boto3.resource( "ec2", region_name=provider_config["region"], config=config) diff --git a/python/ray/dataframe/concat.py b/python/ray/dataframe/concat.py index 952e326edc1ff..0206be64354d3 100644 --- a/python/ray/dataframe/concat.py +++ b/python/ray/dataframe/concat.py @@ -38,8 +38,8 @@ def concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False, "and ray.dataframe.DataFrame objs are " "valid", type(type_check)) - all_series = all([isinstance(obj, pandas.Series) - for obj in objs]) + all_series = all(isinstance(obj, pandas.Series) + for obj in objs) if all_series: return pandas.concat(objs, axis, join, join_axes, ignore_index, keys, levels, names, @@ -47,8 +47,8 @@ def concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False, if isinstance(objs, dict): raise NotImplementedError( - "Obj as dicts not implemented. To contribute to " - "Pandas on Ray, please visit github.com/ray-project/ray.") + "Obj as dicts not implemented. To contribute to " + "Pandas on Ray, please visit github.com/ray-project/ray.") axis = pandas.DataFrame()._get_axis_number(axis) diff --git a/python/ray/dataframe/dataframe.py b/python/ray/dataframe/dataframe.py index ba660a06ea95c..2526822b50d5e 100644 --- a/python/ray/dataframe/dataframe.py +++ b/python/ray/dataframe/dataframe.py @@ -668,7 +668,7 @@ def groupby(self, by=None, axis=0, level=None, as_index=True, sort=True, mismatch = len(by) != len(self) if axis == 0 \ else len(by) != len(self.columns) - if all([obj in self for obj in by]) and mismatch: + if all(obj in self for obj in by) and mismatch: raise NotImplementedError( "Groupby with lists of columns not yet supported.") elif mismatch: @@ -2194,7 +2194,7 @@ def idxmax(self, axis=0, skipna=True): A Series with the index for each maximum value for the axis specified. """ - if not all([d != np.dtype('O') for d in self.dtypes]): + if not all(d != np.dtype('O') for d in self.dtypes): raise TypeError( "reduction operation 'argmax' not allowed for this dtype") @@ -2216,7 +2216,7 @@ def idxmin(self, axis=0, skipna=True): A Series with the index for each minimum value for the axis specified. """ - if not all([d != np.dtype('O') for d in self.dtypes]): + if not all(d != np.dtype('O') for d in self.dtypes): raise TypeError( "reduction operation 'argmax' not allowed for this dtype") @@ -3196,9 +3196,9 @@ def quantile_helper(df, base_object): """ # This if call prevents ValueErrors with object only partitions if (numeric_only and - all([dtype == np.dtype('O') or - is_timedelta64_dtype(dtype) - for dtype in df.dtypes])): + all(dtype == np.dtype('O') or + is_timedelta64_dtype(dtype) + for dtype in df.dtypes)): return base_object else: return df.quantile(q=q, axis=axis, numeric_only=numeric_only, @@ -4224,16 +4224,28 @@ def to_csv(self, path_or_buf=None, sep=",", na_rep="", float_format=None, tupleize_cols=None, date_format=None, doublequote=True, escapechar=None, decimal="."): - kwargs = dict( - path_or_buf=path_or_buf, sep=sep, na_rep=na_rep, - float_format=float_format, columns=columns, header=header, - index=index, index_label=index_label, mode=mode, - encoding=encoding, compression=compression, quoting=quoting, - quotechar=quotechar, line_terminator=line_terminator, - chunksize=chunksize, tupleize_cols=tupleize_cols, - date_format=date_format, doublequote=doublequote, - escapechar=escapechar, decimal=decimal - ) + kwargs = { + 'path_or_buf': path_or_buf, + 'sep': sep, + 'na_rep': na_rep, + 'float_format': float_format, + 'columns': columns, + 'header': header, + 'index': index, + 'index_label': index_label, + 'mode': mode, + 'encoding': encoding, + 'compression': compression, + 'quoting': quoting, + 'quotechar': quotechar, + 'line_terminator': line_terminator, + 'chunksize': chunksize, + 'tupleize_cols': tupleize_cols, + 'date_format': date_format, + 'doublequote': doublequote, + 'escapechar': escapechar, + 'decimal': decimal + } if compression is not None: warnings.warn("Defaulting to Pandas implementation", diff --git a/python/ray/dataframe/io.py b/python/ray/dataframe/io.py index f29505bef6a45..5ce1edde6053e 100644 --- a/python/ray/dataframe/io.py +++ b/python/ray/dataframe/io.py @@ -208,60 +208,61 @@ def read_csv(filepath_or_buffer, kwargs: Keyword arguments in pandas::from_csv """ - kwargs = dict( - sep=sep, - delimiter=delimiter, - header=header, - names=names, - index_col=index_col, - usecols=usecols, - squeeze=squeeze, - prefix=prefix, - mangle_dupe_cols=mangle_dupe_cols, - dtype=dtype, - engine=engine, - converters=converters, - true_values=true_values, - false_values=false_values, - skipinitialspace=skipinitialspace, - skiprows=skiprows, - nrows=nrows, - na_values=na_values, - keep_default_na=keep_default_na, - na_filter=na_filter, - verbose=verbose, - skip_blank_lines=skip_blank_lines, - parse_dates=parse_dates, - infer_datetime_format=infer_datetime_format, - keep_date_col=keep_date_col, - date_parser=date_parser, - dayfirst=dayfirst, - iterator=iterator, - chunksize=chunksize, - compression=compression, - thousands=thousands, - decimal=decimal, - lineterminator=lineterminator, - quotechar=quotechar, - quoting=quoting, - escapechar=escapechar, - comment=comment, - encoding=encoding, - dialect=dialect, - tupleize_cols=tupleize_cols, - error_bad_lines=error_bad_lines, - warn_bad_lines=warn_bad_lines, - skipfooter=skipfooter, - skip_footer=skip_footer, - doublequote=doublequote, - delim_whitespace=delim_whitespace, - as_recarray=as_recarray, - compact_ints=compact_ints, - use_unsigned=use_unsigned, - low_memory=low_memory, - buffer_lines=buffer_lines, - memory_map=memory_map, - float_precision=float_precision) + kwargs = { + 'sep': sep, + 'delimiter': delimiter, + 'header': header, + 'names': names, + 'index_col': index_col, + 'usecols': usecols, + 'squeeze': squeeze, + 'prefix': prefix, + 'mangle_dupe_cols': mangle_dupe_cols, + 'dtype': dtype, + 'engine': engine, + 'converters': converters, + 'true_values': true_values, + 'false_values': false_values, + 'skipinitialspace': skipinitialspace, + 'skiprows': skiprows, + 'nrows': nrows, + 'na_values': na_values, + 'keep_default_na': keep_default_na, + 'na_filter': na_filter, + 'verbose': verbose, + 'skip_blank_lines': skip_blank_lines, + 'parse_dates': parse_dates, + 'infer_datetime_format': infer_datetime_format, + 'keep_date_col': keep_date_col, + 'date_parser': date_parser, + 'dayfirst': dayfirst, + 'iterator': iterator, + 'chunksize': chunksize, + 'compression': compression, + 'thousands': thousands, + 'decimal': decimal, + 'lineterminator': lineterminator, + 'quotechar': quotechar, + 'quoting': quoting, + 'escapechar': escapechar, + 'comment': comment, + 'encoding': encoding, + 'dialect': dialect, + 'tupleize_cols': tupleize_cols, + 'error_bad_lines': error_bad_lines, + 'warn_bad_lines': warn_bad_lines, + 'skipfooter': skipfooter, + 'skip_footer': skip_footer, + 'doublequote': doublequote, + 'delim_whitespace': delim_whitespace, + 'as_recarray': as_recarray, + 'compact_ints': compact_ints, + 'use_unsigned': use_unsigned, + 'low_memory': low_memory, + 'buffer_lines': buffer_lines, + 'memory_map': memory_map, + 'float_precision': float_precision, + } # Default to Pandas read_csv for non-serializable objects if not isinstance(filepath_or_buffer, str) or \ diff --git a/python/ray/dataframe/test/test_dataframe.py b/python/ray/dataframe/test/test_dataframe.py index 0054e265cdae7..c6b7f7fa1eaee 100644 --- a/python/ray/dataframe/test/test_dataframe.py +++ b/python/ray/dataframe/test/test_dataframe.py @@ -1783,7 +1783,7 @@ def test_fillna_dtype_conversion(num_partitions=2): ) # equiv of replace - df = pd.DataFrame(dict(A=[1, np.nan], B=[1., 2.])) + df = pd.DataFrame({'A': [1, np.nan], 'B': [1., 2.]}) ray_df = from_pandas(df, num_partitions) for v in ['', 1, np.nan, 1.0]: assert ray_df_equals_pandas( diff --git a/python/ray/dataframe/utils.py b/python/ray/dataframe/utils.py index bd9679af2a008..f19dd497f5ccc 100644 --- a/python/ray/dataframe/utils.py +++ b/python/ray/dataframe/utils.py @@ -9,7 +9,7 @@ from . import get_npartitions -_NAN_BLOCKS = dict() +_NAN_BLOCKS = {} def _get_nan_block_id(n_row=1, n_col=1, transpose=False): @@ -225,7 +225,7 @@ def _map_partitions(func, partitions, *argslists): return [_deploy_func.remote(func, part, argslists[0]) for part in partitions] else: - assert(all([len(args) == len(partitions) for args in argslists])) + assert(all(len(args) == len(partitions) for args in argslists)) return [_deploy_func.remote(func, *args) for args in zip(partitions, *argslists)] diff --git a/python/ray/experimental/array/distributed/core.py b/python/ray/experimental/array/distributed/core.py index 59a5e024c8f0d..2923c0b2ebd84 100644 --- a/python/ray/experimental/array/distributed/core.py +++ b/python/ray/experimental/array/distributed/core.py @@ -241,7 +241,7 @@ def subblocks(a, *ranges): result = DistArray(shape) for index in np.ndindex(*result.num_blocks): result.objectids[index] = a.objectids[tuple( - [ranges[i][index[i]] for i in range(a.ndim)])] + ranges[i][index[i]] for i in range(a.ndim))] return result diff --git a/python/ray/experimental/state.py b/python/ray/experimental/state.py index f5e020ba1553e..9e0643a990bc4 100644 --- a/python/ray/experimental/state.py +++ b/python/ray/experimental/state.py @@ -360,7 +360,7 @@ def client_table(self): """ self._check_connected() db_client_keys = self.redis_client.keys(DB_CLIENT_PREFIX + "*") - node_info = dict() + node_info = {} for key in db_client_keys: client_info = self.redis_client.hgetall(key) node_ip_address = decode(client_info[b"node_ip_address"]) @@ -403,7 +403,7 @@ def log_files(self): """ relevant_files = self.redis_client.keys("LOGFILE*") - ip_filename_file = dict() + ip_filename_file = {} for filename in relevant_files: filename = filename.decode("ascii") @@ -417,7 +417,7 @@ def log_files(self): file_str.append(y) if ip_addr not in ip_filename_file: - ip_filename_file[ip_addr] = dict() + ip_filename_file[ip_addr] = {} ip_filename_file[ip_addr][filename] = file_str @@ -445,7 +445,7 @@ def task_profiles(self, num_tasks, start=None, end=None, fwd=True): list of profiling information for tasks where the events have no task ID. """ - task_info = dict() + task_info = {} event_log_sets = self.redis_client.keys("event_log*") # The heap is used to maintain the set of x tasks that occurred the @@ -498,7 +498,7 @@ def task_profiles(self, num_tasks, start=None, end=None, fwd=True): for event in event_dict: if "task_id" in event[3]: task_id = event[3]["task_id"] - task_info[task_id] = dict() + task_info[task_id] = {} task_info[task_id]["score"] = score # Add task to (min/max) heap by its start point. # if fwd, we want to delete the largest elements, so -score @@ -901,7 +901,7 @@ def local_schedulers(self): def workers(self): """Get a dictionary mapping worker ID to worker information.""" worker_keys = self.redis_client.keys("Worker*") - workers_data = dict() + workers_data = {} for worker_key in worker_keys: worker_info = self.redis_client.hgetall(worker_key) @@ -927,7 +927,7 @@ def workers(self): def actors(self): actor_keys = self.redis_client.keys("Actor:*") - actor_info = dict() + actor_info = {} for key in actor_keys: info = self.redis_client.hgetall(key) actor_id = key[len("Actor:"):] diff --git a/python/ray/experimental/tfutils.py b/python/ray/experimental/tfutils.py index fc33900b8a27d..f52a9468229c2 100644 --- a/python/ray/experimental/tfutils.py +++ b/python/ray/experimental/tfutils.py @@ -84,8 +84,8 @@ def __init__(self, loss, sess=None, input_variables=None): for v in variable_list: self.variables[v.op.node_def.name] = v - self.placeholders = dict() - self.assignment_nodes = dict() + self.placeholders = {} + self.assignment_nodes = {} # Create new placeholders to put in custom weights. for k, var in self.variables.items(): @@ -109,9 +109,8 @@ def get_flat_size(self): Returns: The length of all flattened variables concatenated. """ - return sum([ - np.prod(v.get_shape().as_list()) for v in self.variables.values() - ]) + return sum( + np.prod(v.get_shape().as_list()) for v in self.variables.values()) def _check_sess(self): """Checks if the session is set, and if not throw an error message.""" diff --git a/python/ray/experimental/ui.py b/python/ray/experimental/ui.py index 1e6996cd303fb..da4ee9e57c838 100644 --- a/python/ray/experimental/ui.py +++ b/python/ray/experimental/ui.py @@ -580,8 +580,11 @@ def plot_utilization(): y_range=[0, 1]) # Create the data source that the plot will pull from - time_series_source = ColumnDataSource( - data=dict(left=[], right=[], top=[])) + time_series_source = ColumnDataSource(data={ + 'left': [], + 'right': [], + 'top': [] + }) # Plot the rectangles representing the distribution time_series_fig.quad( @@ -731,7 +734,7 @@ def heat_map_update(abs_earliest, abs_latest, abs_num_tasks, tasks): earliest = time.time() latest = 0 - node_to_tasks = dict() + node_to_tasks = {} # Determine which task has the earlest start time out of the ones # passed into the update function for task_id, data in tasks.items(): diff --git a/python/ray/global_scheduler/test/test.py b/python/ray/global_scheduler/test/test.py index a05b7a9c7a3cd..dc1aa5e2bebb1 100644 --- a/python/ray/global_scheduler/test/test.py +++ b/python/ray/global_scheduler/test/test.py @@ -285,13 +285,10 @@ def integration_many_tasks_helper(self, timesync=True): for task_entry in task_entries.values() ] self.assertTrue( - all([ - status in [ - state.TASK_STATUS_WAITING, - state.TASK_STATUS_SCHEDULED, - state.TASK_STATUS_QUEUED - ] for status in task_statuses - ])) + all(status in [ + state.TASK_STATUS_WAITING, state.TASK_STATUS_SCHEDULED, + state.TASK_STATUS_QUEUED + ] for status in task_statuses)) num_tasks_done = task_statuses.count(state.TASK_STATUS_QUEUED) num_tasks_scheduled = task_statuses.count( state.TASK_STATUS_SCHEDULED) @@ -302,10 +299,8 @@ def integration_many_tasks_helper(self, timesync=True): "tasks queued = {}, retries left = {}".format( len(task_entries), num_tasks_waiting, num_tasks_scheduled, num_tasks_done, num_retries)) - if all([ - status == state.TASK_STATUS_QUEUED - for status in task_statuses - ]): + if all(status == state.TASK_STATUS_QUEUED + for status in task_statuses): # We're done, so pass. break num_retries -= 1 diff --git a/python/ray/monitor.py b/python/ray/monitor.py index c628a279ae058..52b6b20cde19b 100644 --- a/python/ray/monitor.py +++ b/python/ray/monitor.py @@ -97,7 +97,7 @@ def __init__(self, redis_address, redis_port, autoscaling_config): self.dead_plasma_managers = set() # Keep a mapping from local scheduler client ID to IP address to use # for updating the load metrics. - self.local_scheduler_id_to_ip_map = dict() + self.local_scheduler_id_to_ip_map = {} self.load_metrics = LoadMetrics() if autoscaling_config: self.autoscaler = StandardAutoscaler(autoscaling_config, diff --git a/python/ray/rllib/a3c/tfpolicy.py b/python/ray/rllib/a3c/tfpolicy.py index 4816a7fefb545..1fbb46bdfe784 100644 --- a/python/ray/rllib/a3c/tfpolicy.py +++ b/python/ray/rllib/a3c/tfpolicy.py @@ -21,8 +21,8 @@ def __init__(self, registry, ob_space, action_space, config, with self.g.as_default(), tf.device(worker_device): with tf.variable_scope(name): self._setup_graph(ob_space, action_space) - assert all([hasattr(self, attr) - for attr in ["vf", "logits", "x", "var_list"]]) + assert all(hasattr(self, attr) + for attr in ["vf", "logits", "x", "var_list"]) print("Setting up loss") self.setup_loss(action_space) self.setup_gradients() diff --git a/python/ray/rllib/ddpg/apex.py b/python/ray/rllib/ddpg/apex.py index c670198c35710..d3402e61bc061 100644 --- a/python/ray/rllib/ddpg/apex.py +++ b/python/ray/rllib/ddpg/apex.py @@ -3,29 +3,32 @@ from __future__ import print_function from ray.rllib.ddpg.ddpg import DDPGAgent, DEFAULT_CONFIG as DDPG_CONFIG +from ray.utils import merge_dicts -APEX_DDPG_DEFAULT_CONFIG = dict(DDPG_CONFIG, - **dict( - optimizer_class="ApexOptimizer", - optimizer_config=dict( - DDPG_CONFIG["optimizer_config"], - **dict( - max_weight_sync_delay=400, - num_replay_buffer_shards=4, - debug=False, - )), - n_step=3, - num_workers=32, - buffer_size=2000000, - learning_starts=50000, - train_batch_size=512, - sample_batch_size=50, - max_weight_sync_delay=400, - target_network_update_freq=500000, - timesteps_per_iteration=25000, - per_worker_exploration=True, - worker_side_prioritization=True, - )) +APEX_DDPG_DEFAULT_CONFIG = merge_dicts( + DDPG_CONFIG, + { + 'optimizer_class': 'ApexOptimizer', + 'optimizer_config': + merge_dicts( + DDPG_CONFIG['optimizer_config'], { + 'max_weight_sync_delay': 400, + 'num_replay_buffer_shards': 4, + 'debug': False + }), + 'n_step': 3, + 'num_workers': 32, + 'buffer_size': 2000000, + 'learning_starts': 50000, + 'train_batch_size': 512, + 'sample_batch_size': 50, + 'max_weight_sync_delay': 400, + 'target_network_update_freq': 500000, + 'timesteps_per_iteration': 25000, + 'per_worker_exploration': True, + 'worker_side_prioritization': True, + }, +) class ApexDDPGAgent(DDPGAgent): diff --git a/python/ray/rllib/ddpg/ddpg.py b/python/ray/rllib/ddpg/ddpg.py index ae5e65e5bc3bd..25fda8321e207 100644 --- a/python/ray/rllib/ddpg/ddpg.py +++ b/python/ray/rllib/ddpg/ddpg.py @@ -20,89 +20,89 @@ "train_batch_size", "learning_starts", "clip_rewards" ] -DEFAULT_CONFIG = dict( +DEFAULT_CONFIG = { # === Model === # Hidden layer sizes of the policy networks - actor_hiddens=[64, 64], + 'actor_hiddens': [64, 64], # Hidden layer sizes of the policy networks - critic_hiddens=[64, 64], + 'critic_hiddens': [64, 64], # N-step Q learning - n_step=1, + 'n_step': 1, # Config options to pass to the model constructor - model={}, + 'model': {}, # Discount factor for the MDP - gamma=0.99, + 'gamma': 0.99, # Arguments to pass to the env creator - env_config={}, + 'env_config': {}, # === Exploration === # Max num timesteps for annealing schedules. Exploration is annealed from # 1.0 to exploration_fraction over this number of timesteps scaled by # exploration_fraction - schedule_max_timesteps=100000, + 'schedule_max_timesteps': 100000, # Number of env steps to optimize for before returning - timesteps_per_iteration=1000, + 'timesteps_per_iteration': 1000, # Fraction of entire training period over which the exploration rate is # annealed - exploration_fraction=0.1, + 'exploration_fraction': 0.1, # Final value of random action probability - exploration_final_eps=0.02, + 'exploration_final_eps': 0.02, # OU-noise scale - noise_scale=0.1, + 'noise_scale': 0.1, # theta - exploration_theta=0.15, + 'exploration_theta': 0.15, # sigma - exploration_sigma=0.2, + 'exploration_sigma': 0.2, # Update the target network every `target_network_update_freq` steps. - target_network_update_freq=0, + 'target_network_update_freq': 0, # Update the target by \tau * policy + (1-\tau) * target_policy - tau=0.002, + 'tau': 0.002, # Whether to start with random actions instead of noops. - random_starts=True, + 'random_starts': True, # === Replay buffer === # Size of the replay buffer. Note that if async_updates is set, then # each worker will have a replay buffer of this size. - buffer_size=50000, + 'buffer_size': 50000, # If True prioritized replay buffer will be used. - prioritized_replay=True, + 'prioritized_replay': True, # Alpha parameter for prioritized replay buffer. - prioritized_replay_alpha=0.6, + 'prioritized_replay_alpha': 0.6, # Beta parameter for sampling from prioritized replay buffer. - prioritized_replay_beta=0.4, + 'prioritized_replay_beta': 0.4, # Epsilon to add to the TD errors when updating priorities. - prioritized_replay_eps=1e-6, + 'prioritized_replay_eps': 1e-6, # Whether to clip rewards to [-1, 1] prior to adding to the replay buffer. - clip_rewards=True, + 'clip_rewards': True, # === Optimization === # Learning rate for adam optimizer - actor_lr=1e-4, - critic_lr=1e-3, + 'actor_lr': 1e-4, + 'critic_lr': 1e-3, # If True, use huber loss instead of squared loss for critic network # Conventionally, no need to clip gradients if using a huber loss - use_huber=False, + 'use_huber': False, # Threshold of a huber loss - huber_threshold=1.0, + 'huber_threshold': 1.0, # Weights for L2 regularization - l2_reg=1e-6, + 'l2_reg': 1e-6, # If not None, clip gradients during optimization at this value - grad_norm_clipping=None, + 'grad_norm_clipping': None, # How many steps of the model to sample before learning starts. - learning_starts=1500, + 'learning_starts': 1500, # Update the replay buffer with this many samples at once. Note that this # setting applies per-worker if num_workers > 1. - sample_batch_size=1, + 'sample_batch_size': 1, # Size of a batched sampled from replay buffer for training. Note that # if async_updates is set, then each worker returns gradients for a # batch of this size. - train_batch_size=256, + 'train_batch_size': 256, # Smooth the current average reward over this many previous episodes. - smoothing_num_episodes=100, + 'smoothing_num_episodes': 100, # === Tensorflow === # Arguments to pass to tensorflow - tf_session_args={ + 'tf_session_args': { "device_count": { "CPU": 2 }, @@ -119,17 +119,18 @@ # Number of workers for collecting samples with. This only makes sense # to increase if your environment is particularly slow to sample, or if # you're using the Async or Ape-X optimizers. - num_workers=0, + 'num_workers': 0, # Whether to allocate GPUs for workers (if > 0). - num_gpus_per_worker=0, + 'num_gpus_per_worker': 0, # Optimizer class to use. - optimizer_class="LocalSyncReplayOptimizer", + 'optimizer_class': "LocalSyncReplayOptimizer", # Config to pass to the optimizer. - optimizer_config=dict(), + 'optimizer_config': {}, # Whether to use a distribution of epsilons across workers for exploration. - per_worker_exploration=False, + 'per_worker_exploration': False, # Whether to compute priorities on workers. - worker_side_prioritization=False) + 'worker_side_prioritization': False +} class DDPGAgent(Agent): diff --git a/python/ray/rllib/dqn/apex.py b/python/ray/rllib/dqn/apex.py index b44fb85b46639..6de53203770c1 100644 --- a/python/ray/rllib/dqn/apex.py +++ b/python/ray/rllib/dqn/apex.py @@ -4,27 +4,33 @@ from ray.rllib.dqn.dqn import DQNAgent, DEFAULT_CONFIG as DQN_CONFIG from ray.tune.trial import Resources - -APEX_DEFAULT_CONFIG = dict(DQN_CONFIG, **dict( - optimizer_class="ApexOptimizer", - optimizer_config=dict(DQN_CONFIG["optimizer_config"], **dict( - max_weight_sync_delay=400, - num_replay_buffer_shards=4, - debug=False, - )), - n_step=3, - gpu=True, - num_workers=32, - buffer_size=2000000, - learning_starts=50000, - train_batch_size=512, - sample_batch_size=50, - max_weight_sync_delay=400, - target_network_update_freq=500000, - timesteps_per_iteration=25000, - per_worker_exploration=True, - worker_side_prioritization=True, -)) +from ray.utils import merge_dicts + +APEX_DEFAULT_CONFIG = merge_dicts( + DQN_CONFIG, + { + 'optimizer_class': 'ApexOptimizer', + 'optimizer_config': + merge_dicts( + DQN_CONFIG['optimizer_config'], { + 'max_weight_sync_delay': 400, + 'num_replay_buffer_shards': 4, + 'debug': False + }), + 'n_step': 3, + 'gpu': True, + 'num_workers': 32, + 'buffer_size': 2000000, + 'learning_starts': 50000, + 'train_batch_size': 512, + 'sample_batch_size': 50, + 'max_weight_sync_delay': 400, + 'target_network_update_freq': 500000, + 'timesteps_per_iteration': 25000, + 'per_worker_exploration': True, + 'worker_side_prioritization': True, + }, +) class ApexAgent(DQNAgent): diff --git a/python/ray/rllib/dqn/dqn.py b/python/ray/rllib/dqn/dqn.py index 9a0da4e807042..0bf99cf1ff2a7 100644 --- a/python/ray/rllib/dqn/dqn.py +++ b/python/ray/rllib/dqn/dqn.py @@ -21,75 +21,75 @@ "prioritized_replay_beta", "prioritized_replay_eps", "sample_batch_size", "train_batch_size", "learning_starts", "clip_rewards"] -DEFAULT_CONFIG = dict( +DEFAULT_CONFIG = { # === Model === # Whether to use dueling dqn - dueling=True, + 'dueling': True, # Whether to use double dqn - double_q=True, + 'double_q': True, # Hidden layer sizes of the state and action value networks - hiddens=[256], + 'hiddens': [256], # N-step Q learning - n_step=1, + 'n_step': 1, # Config options to pass to the model constructor - model={}, + 'model': {}, # Discount factor for the MDP - gamma=0.99, + 'gamma': 0.99, # Arguments to pass to the env creator - env_config={}, + 'env_config': {}, # === Exploration === # Max num timesteps for annealing schedules. Exploration is annealed from # 1.0 to exploration_fraction over this number of timesteps scaled by # exploration_fraction - schedule_max_timesteps=100000, + 'schedule_max_timesteps': 100000, # Number of env steps to optimize for before returning - timesteps_per_iteration=1000, + 'timesteps_per_iteration': 1000, # Fraction of entire training period over which the exploration rate is # annealed - exploration_fraction=0.1, + 'exploration_fraction': 0.1, # Final value of random action probability - exploration_final_eps=0.02, + 'exploration_final_eps': 0.02, # Update the target network every `target_network_update_freq` steps. - target_network_update_freq=500, + 'target_network_update_freq': 500, # Whether to start with random actions instead of noops. - random_starts=True, + 'random_starts': True, # === Replay buffer === # Size of the replay buffer. Note that if async_updates is set, then # each worker will have a replay buffer of this size. - buffer_size=50000, + 'buffer_size': 50000, # If True prioritized replay buffer will be used. - prioritized_replay=True, + 'prioritized_replay': True, # Alpha parameter for prioritized replay buffer. - prioritized_replay_alpha=0.6, + 'prioritized_replay_alpha': 0.6, # Beta parameter for sampling from prioritized replay buffer. - prioritized_replay_beta=0.4, + 'prioritized_replay_beta': 0.4, # Epsilon to add to the TD errors when updating priorities. - prioritized_replay_eps=1e-6, + 'prioritized_replay_eps': 1e-6, # Whether to clip rewards to [-1, 1] prior to adding to the replay buffer. - clip_rewards=True, + 'clip_rewards': True, # === Optimization === # Learning rate for adam optimizer - lr=5e-4, + 'lr': 5e-4, # If not None, clip gradients during optimization at this value - grad_norm_clipping=40, + 'grad_norm_clipping': 40, # How many steps of the model to sample before learning starts. - learning_starts=1000, + 'learning_starts': 1000, # Update the replay buffer with this many samples at once. Note that # this setting applies per-worker if num_workers > 1. - sample_batch_size=4, + 'sample_batch_size': 4, # Size of a batched sampled from replay buffer for training. Note that # if async_updates is set, then each worker returns gradients for a # batch of this size. - train_batch_size=32, + 'train_batch_size': 32, # Smooth the current average reward over this many previous episodes. - smoothing_num_episodes=100, + 'smoothing_num_episodes': 100, # === Tensorflow === # Arguments to pass to tensorflow - tf_session_args={ + 'tf_session_args': { "device_count": {"CPU": 2}, "log_device_placement": False, "allow_soft_placement": True, @@ -102,23 +102,24 @@ # === Parallelism === # Whether to use a GPU for local optimization. - gpu=False, + 'gpu': False, # Number of workers for collecting samples with. This only makes sense # to increase if your environment is particularly slow to sample, or if # you're using the Async or Ape-X optimizers. - num_workers=0, + 'num_workers': 0, # Whether to allocate GPUs for workers (if > 0). - num_gpus_per_worker=0, + 'num_gpus_per_worker': 0, # Whether to allocate CPUs for workers (if > 0). - num_cpus_per_worker=1, + 'num_cpus_per_worker': 1, # Optimizer class to use. - optimizer_class="LocalSyncReplayOptimizer", + 'optimizer_class': "LocalSyncReplayOptimizer", # Config to pass to the optimizer. - optimizer_config=dict(), + 'optimizer_config': {}, # Whether to use a distribution of epsilons across workers for exploration. - per_worker_exploration=False, + 'per_worker_exploration': False, # Whether to compute priorities on workers. - worker_side_prioritization=False) + 'worker_side_prioritization': False +} class DQNAgent(Agent): diff --git a/python/ray/rllib/es/es.py b/python/ray/rllib/es/es.py index f5ea4fa373ed2..23b7268efafbf 100644 --- a/python/ray/rllib/es/es.py +++ b/python/ray/rllib/es/es.py @@ -27,18 +27,19 @@ ]) -DEFAULT_CONFIG = dict( - l2_coeff=0.005, - noise_stdev=0.02, - episodes_per_batch=1000, - timesteps_per_batch=10000, - eval_prob=0.003, - return_proc_mode="centered_rank", - num_workers=10, - stepsize=0.01, - observation_filter="MeanStdFilter", - noise_size=250000000, - env_config={}) +DEFAULT_CONFIG = { + 'l2_coeff': 0.005, + 'noise_stdev': 0.02, + 'episodes_per_batch': 1000, + 'timesteps_per_batch': 10000, + 'eval_prob': 0.003, + 'return_proc_mode': "centered_rank", + 'num_workers': 10, + 'stepsize': 0.01, + 'observation_filter': "MeanStdFilter", + 'noise_size': 250000000, + 'env_config': {}, +} @ray.remote @@ -192,10 +193,10 @@ def _collect_results(self, theta_id, min_episodes, min_timesteps): # Update the number of episodes and the number of timesteps # keeping in mind that result.noisy_lengths is a list of lists, # where the inner lists have length 2. - num_episodes += sum([len(pair) for pair - in result.noisy_lengths]) - num_timesteps += sum([sum(pair) for pair - in result.noisy_lengths]) + num_episodes += sum(len(pair) for pair + in result.noisy_lengths) + num_timesteps += sum(sum(pair) for pair + in result.noisy_lengths) return results, num_episodes, num_timesteps def _train(self): diff --git a/python/ray/rllib/es/policies.py b/python/ray/rllib/es/policies.py index 36a404c4882c1..a1746673bd1c3 100644 --- a/python/ray/rllib/es/policies.py +++ b/python/ray/rllib/es/policies.py @@ -59,9 +59,9 @@ def __init__(self, registry, sess, action_space, preprocessor, self.variables = ray.experimental.TensorFlowVariables( model.outputs, self.sess) - self.num_params = sum([np.prod(variable.shape.as_list()) - for _, variable - in self.variables.variables.items()]) + self.num_params = sum(np.prod(variable.shape.as_list()) + for _, variable + in self.variables.variables.items()) self.sess.run(tf.global_variables_initializer()) def compute(self, observation, add_noise=False, update=True): diff --git a/python/ray/rllib/models/catalog.py b/python/ray/rllib/models/catalog.py index 8a423d3098506..532c138ba92e8 100644 --- a/python/ray/rllib/models/catalog.py +++ b/python/ray/rllib/models/catalog.py @@ -123,7 +123,7 @@ def get_action_placeholder(action_space): " not supported".format(action_space)) @staticmethod - def get_model(registry, inputs, num_outputs, options=dict()): + def get_model(registry, inputs, num_outputs, options={}): """Returns a suitable model conforming to given input and output specs. Args: @@ -156,7 +156,7 @@ def get_model(registry, inputs, num_outputs, options=dict()): return FullyConnectedNetwork(inputs, num_outputs, options) @staticmethod - def get_torch_model(registry, input_shape, num_outputs, options=dict()): + def get_torch_model(registry, input_shape, num_outputs, options={}): """Returns a PyTorch suitable model. This is currently only supported in A3C. @@ -188,7 +188,7 @@ def get_torch_model(registry, input_shape, num_outputs, options=dict()): return PyTorchFCNet(input_shape[0], num_outputs, options) @staticmethod - def get_preprocessor(registry, env, options=dict()): + def get_preprocessor(registry, env, options={}): """Returns a suitable processor for the given environment. Args: @@ -215,7 +215,7 @@ def get_preprocessor(registry, env, options=dict()): return preprocessor(env.observation_space, options) @staticmethod - def get_preprocessor_as_wrapper(registry, env, options=dict()): + def get_preprocessor_as_wrapper(registry, env, options={}): """Returns a preprocessor as a gym observation wrapper. Args: diff --git a/python/ray/rllib/optimizers/replay_buffer.py b/python/ray/rllib/optimizers/replay_buffer.py index d38014ba26ee2..a1e3744142675 100644 --- a/python/ray/rllib/optimizers/replay_buffer.py +++ b/python/ray/rllib/optimizers/replay_buffer.py @@ -44,7 +44,7 @@ def add(self, obs_t, action, reward, obs_tp1, done, weight): if self._next_idx >= len(self._storage): self._storage.append(data) - self._est_size_bytes += sum([sys.getsizeof(d) for d in data]) + self._est_size_bytes += sum(sys.getsizeof(d) for d in data) else: self._storage[self._next_idx] = data if self._next_idx + 1 >= self._maxsize: diff --git a/python/ray/signature.py b/python/ray/signature.py index 5c6da17664357..9bd9a881a5c59 100644 --- a/python/ray/signature.py +++ b/python/ray/signature.py @@ -54,7 +54,7 @@ def get_signature_params(func): "__code__", "__annotations__", "__defaults__", "__kwdefaults__" ] - if all([hasattr(func, attr) for attr in attrs]): + if all(hasattr(func, attr) for attr in attrs): original_func = func def func(): @@ -63,7 +63,7 @@ def func(): for attr in attrs: setattr(func, attr, getattr(original_func, attr)) else: - raise TypeError("{0!r} is not a Python function we can process" + raise TypeError("{!r} is not a Python function we can process" .format(func)) return list(funcsigs.signature(func).parameters.items()) diff --git a/python/ray/test/test_utils.py b/python/ray/test/test_utils.py index 177a72519ec87..204f20c6a1e8d 100644 --- a/python/ray/test/test_utils.py +++ b/python/ray/test/test_utils.py @@ -95,7 +95,7 @@ def _wait_for_event(event_name, redis_address, extra_buffer=0): redis_client = redis.StrictRedis(host=redis_host, port=int(redis_port)) while True: event_infos = redis_client.lrange(EVENT_KEY, 0, -1) - events = dict() + events = {} for event_info in event_infos: name, data = json.loads(event_info) if name in events: diff --git a/python/ray/tune/hyperband.py b/python/ray/tune/hyperband.py index 45a716a3f9824..f9d4a08909d7e 100644 --- a/python/ray/tune/hyperband.py +++ b/python/ray/tune/hyperband.py @@ -397,5 +397,5 @@ def __repr__(self): ]) counts = collections.Counter([t.status for t in self._all_trials]) trial_statuses = ", ".join( - sorted(["{}: {}".format(k, v) for k, v in counts.items()])) + sorted("{}: {}".format(k, v) for k, v in counts.items())) return "Bracket({}): {{{}}} ".format(status, trial_statuses) diff --git a/python/ray/tune/median_stopping_rule.py b/python/ray/tune/median_stopping_rule.py index 5d75e62b05a67..56f3e6dda11b5 100644 --- a/python/ray/tune/median_stopping_rule.py +++ b/python/ray/tune/median_stopping_rule.py @@ -113,4 +113,4 @@ def _running_result(self, trial, t_max=float('inf')): def _best_result(self, trial): results = self._results[trial] - return max([getattr(r, self._reward_attr) for r in results]) + return max(getattr(r, self._reward_attr) for r in results) diff --git a/python/ray/tune/test/tune_server_test.py b/python/ray/tune/test/tune_server_test.py index f80e90bc481c7..395db08d013fe 100644 --- a/python/ray/tune/test/tune_server_test.py +++ b/python/ray/tune/test/tune_server_test.py @@ -63,7 +63,10 @@ def testAddTrial(self): "stop": { "training_iteration": 3 }, - "trial_resources": dict(cpu=1, gpu=1), + "trial_resources": { + 'cpu': 1, + 'gpu': 1 + }, } client.add_trial("test", spec) runner.step() diff --git a/python/ray/utils.py b/python/ray/utils.py index b8e993d5a738e..f4d669ac66bd4 100644 --- a/python/ray/utils.py +++ b/python/ray/utils.py @@ -208,3 +208,10 @@ def resources_from_resource_arguments(default_num_cpus, default_num_gpus, resources["GPU"] = default_num_gpus return resources + + +def merge_dicts(d1, d2): + """Merge two dicts and return a new dict that's their union.""" + d = d1.copy() + d.update(d2) + return d diff --git a/test/actor_test.py b/test/actor_test.py index 3d99c6349e275..594a82f67b7c2 100644 --- a/test/actor_test.py +++ b/test/actor_test.py @@ -753,7 +753,7 @@ def get_location(self): counts = [locations.count(name) for name in names] print("Counts are {}.".format(counts)) if (len(names) == num_local_schedulers - and all([count >= minimum_count for count in counts])): + and all(count >= minimum_count for count in counts)): break attempts += 1 self.assertLess(attempts, num_attempts) diff --git a/test/runtest.py b/test/runtest.py index 9e407c72329b2..beb2ed0c32e08 100644 --- a/test/runtest.py +++ b/test/runtest.py @@ -1829,7 +1829,7 @@ def attempt_to_load_balance(self, counts = [locations.count(name) for name in names] print("Counts are {}.".format(counts)) if (len(names) == num_local_schedulers - and all([count >= minimum_count for count in counts])): + and all(count >= minimum_count for count in counts)): break attempts += 1 self.assertLess(attempts, num_attempts) @@ -1924,7 +1924,7 @@ def testGlobalStateAPI(self): resources = {"CPU": 5, "GPU": 3, "CustomResource": 1} assert ray.global_state.cluster_resources() == resources - self.assertEqual(ray.global_state.object_table(), dict()) + self.assertEqual(ray.global_state.object_table(), {}) ID_SIZE = 20 diff --git a/test/tensorflow_test.py b/test/tensorflow_test.py index a7518c69d1e76..192f355e9bf9e 100644 --- a/test/tensorflow_test.py +++ b/test/tensorflow_test.py @@ -252,8 +252,8 @@ def testRemoteTrainingLoss(self): for _ in range(2) ]) mean_grads = [ - sum([gradients[i] - for gradients in gradients_list]) / len(gradients_list) + sum(gradients[i] + for gradients in gradients_list) / len(gradients_list) for i in range(len(gradients_list[0])) ] feed_dict = {