<commit_before>from collections import namedtuple
from numbers import Number
from frozendict import frozendict
from itertools import permutations, islice
from os import environ
import googlemaps
from pyrules2 import when

__author__ = 'nhc'

# Read Google Maps API key from environment, and create a client object if the key was there
try:
    key = environ['GOOGLE_MAPS_API_KEY']
    _client_object = googlemaps.Client(key=key)

    def _client_():
        return _client_object
except KeyError:
    def _client_():
        raise Exception('''To use Google Maps with pyrules, put your
Google Maps API key in the environment variable "GOOGLE_MAPS_API_KEY"''')


'''Used as a value in place() below.
Indicates that the named cost is set to 0 when the place is reached.'''
RESET = object()

'''
Example use: reroute(when(my_var=driving_roundtrip(*MY_PLACES)))
Result is an expression generating scenarios where my_var is mapped
to alternative routes to *MY_PLACES.
Guarantee: If applied recursively, all possible alternatives will be generated.
'''
reroute = when(f=lambda x: x.alternatives())


def limit(**item_limits):
    """
    Creates an Expression to filter scenarios based on numeric bounds.
    Example limit(x=2, y=3)(when(x=1, y=3) | when(x=3, y=0) | when(x=-1, y=4))
     will generate only one Scenario, with {x:1, y:3}.
    :param item_limits: One or more limit on the form some_var=30.
    The returned Expression will remove scenarios where some_var maps to
    values larger than 30.
    :return: An Expression which will filter away scenarios in which
    one or more limit is broken, leaving the remaining unchanged.
    """
    def filter_fun(value):
        bounds_ok = [getattr(value, cost_name) <= lim for cost_name, lim in item_limits.items()]
        # Yield either 0 or 1 results
        if all(bounds_ok):
            yield value
    return when(_=filter_fun)


def driving_roundtrip(*places):
    """
    :param places: A sequence of Places,
    e.g. (place('New York'), place('Chicago'), place('Los Angeles'))
    :return: An immutable object representing the roundtrip visiting
    the given places in sequence, then returning to the first place,
    e.g. New York -> Chicago -> Los Angeles -> New York
    All distances and durations will be based on driving.
    """
    roundtrip_list = list(places) + [places[0]]
    places_tuple = tuple(p if isinstance(p, Place) else Place(p) for p in roundtrip_list)
    return Route(places=places_tuple, trip_costs=frozendict(google_maps_matrix(places_tuple)))


def place(address, **kwargs):
    return Place(address, **kwargs)


class Place(object):
    def __init__(self, address, **kwargs):
        """
        :param address: A Google Maps compatible string describing the
        location of the place.
        :param kwargs: Any number of named costs associated with this place,
        e.g. tolls_usd=30, stopover_time=5000
        :return: An immutable object representing the place.
        """
        assert isinstance(address, basestring)
        self.address = address
        for value in kwargs.itervalues():
            assert value is RESET or isinstance(value, Number)
        self.costs = frozendict(kwargs)

    def __str__(self):
        return self.address


class Route(namedtuple('Route', ['places', 'trip_costs'])):
    def distance(self):
        """
        :return: The total distance of this Roundtrip, in meters.
        """
        return sum([self.trip_costs['distance'][trip] for trip in self.legs()])
<commit_msg>Make Place a namedtuple subclass<commit_after>from collections import namedtuple
from numbers import Number
from frozendict import frozendict
from itertools import permutations, islice
from os import environ
import googlemaps
from pyrules2 import when

__author__ = 'nhc'

# Read Google Maps API key from environment, and create a client object if the key was there
try:
    key = environ['GOOGLE_MAPS_API_KEY']
    _client_object = googlemaps.Client(key=key)

    def _client_():
        return _client_object
except KeyError:
    def _client_():
        raise Exception('''To use Google Maps with pyrules, put your
Google Maps API key in the environment variable "GOOGLE_MAPS_API_KEY"''')


'''Used as a value in place() below.
Indicates that the named cost is set to 0 when the place is reached.'''
RESET = object()

'''
Example use: reroute(when(my_var=driving_roundtrip(*MY_PLACES)))
Result is an expression generating scenarios where my_var is mapped
to alternative routes to *MY_PLACES.
Guarantee: If applied recursively, all possible alternatives will be generated.
'''
reroute = when(f=lambda x: x.alternatives())


def limit(**item_limits):
    """
    Creates an Expression to filter scenarios based on numeric bounds.
    Example limit(x=2, y=3)(when(x=1, y=3) | when(x=3, y=0) | when(x=-1, y=4))
     will generate only one Scenario, with {x:1, y:3}.
    :param item_limits: One or more limit on the form some_var=30.
    The returned Expression will remove scenarios where some_var maps to
    values larger than 30.
    :return: An Expression which will filter away scenarios in which
    one or more limit is broken, leaving the remaining unchanged.
    """
    def filter_fun(value):
        bounds_ok = [getattr(value, cost_name) <= lim for cost_name, lim in item_limits.items()]
        # Yield either 0 or 1 results
        if all(bounds_ok):
            yield value
    return when(_=filter_fun)


def driving_roundtrip(*places):
    """
    :param places: A sequence of Places,
    e.g. (place('New York'), place('Chicago'), place('Los Angeles'))
    :return: An immutable object representing the roundtrip visiting
    the given places in sequence, then returning to the first place,
    e.g. New York -> Chicago -> Los Angeles -> New York
    All distances and durations will be based on driving.
    """
    roundtrip_list = list(places) + [places[0]]
    places_tuple = tuple(p if isinstance(p, Place) else Place(p) for p in roundtrip_list)
    return Route(places=places_tuple, trip_costs=frozendict(google_maps_matrix(places_tuple)))


def place(address, **kwargs):
    return Place.create(address, **kwargs)


class Place(namedtuple('Place', ['address', 'costs'])):
    @staticmethod
    def create(address, **kwargs):
        """
        :param address: A Google Maps compatible string describing the
        location of the place.
        :param kwargs: Any number of named costs associated with this place,
        e.g. tolls_usd=30, stopover_time=5000
        :return: An immutable object representing the place.
        """
        assert isinstance(address, basestring)
        for value in kwargs.itervalues():
            assert value is RESET or isinstance(value, Number)
        return Place(address, frozendict(kwargs))

    def __str__(self):
        return self.address


class Route(namedtuple('Route', ['places', 'trip_costs'])):
    def distance(self):
        """
        :return: The total distance of this Roundtrip, in meters.
        """
        return sum([self.trip_costs['distance'][trip] for trip in self.legs()])

{'fraction_non_alphanumeric': 0.09370589895568728, 'fraction_numerical': 0.007056167090036692, 'mean_word_length': 3.557556270096463, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1059874', 'n_tokens_mistral': 2091, 'n_tokens_neox': 2001, 'n_words': 771}