<commit_before>try:
    import json
except ImportError:
    import simplejson as json

from .base import MarathonResource
from .constraint import MarathonConstraint
from .task import MarathonTask


class MarathonApp(MarathonResource):
    """Marathon Application resource.

    :param str cmd: cmd
    :param constraints: placement constraints
    :type constraints: list[:class:`marathon.models.constraint.MarathonConstraint`] or list[tuple]
    :param dict container: container
    :param float cpus: cpus required per instance
    :param dict env: env vars
    :param str executor: executor
    :param str id: app id
    :param int instances: instances
    :param float mem: memory (in MB) required per instance
    :param list[int] ports: ports
    :param list[str] uris: uris
    """

    UPDATE_OK_ATTRIBUTES = ['cmd', 'constraints', 'container', 'cpus', 'env', 'executor', 'mem', 'ports', 'uris']
    """List of attributes which may be updated/changed after app creation"""

    CREATE_ONLY_ATTRIBUTES = ['id']
    """List of attributes that should only be passed on creation"""

    READ_ONLY_ATTRIBUTES = []
    """List of read-only attributes"""

    def __init__(self, cmd=None, constraints=None, container=None, cpus=None, env=None, executor=None,
                 health_checks=None, id=None, instances=None, mem=None, ports=None, tasks=None, uris=None):
        self.cmd = cmd
        self.constraints = constraints or []
        self.container = container
        self.cpus = cpus
        self.env = env
        self.executor = executor
        self.health_checks = health_checks
        self.id = id
        self.instances = instances
        self.mem = mem
        self.ports = ports
        self.tasks = tasks or []
        self.uris = uris

    @classmethod
    def json_decode(cls, obj):
        """Construct a MarathonApp from a parsed response.

        :param dict attributes: object attributes from parsed response

        :rtype: :class:`MarathonApp`
        """
        return cls(
            cmd=obj.get('cmd'),
            constraints=[MarathonConstraint.json_decode(c) for c in obj.get('constraints', [])],
            container=obj.get('container'),
            cpus=obj.get('cpus'),
            env=obj.get('env'),
            executor=obj.get('executor'),
            health_checks=obj.get('healthChecks'),
            id=obj.get('id'),
            instances=obj.get('instances'),
            mem=obj.get('mem'),
            ports=obj.get('ports'),
            tasks=[MarathonTask.json_decode(t) for t in obj.get('tasks', [])],
            uris=obj.get('uris')
        )

    def json_encode(self):<commit_msg>Fix bug whereby a random port is allocated on app creation if "ports" is not passed<commit_after>try:
    import json
except ImportError:
    import simplejson as json

from .base import MarathonResource
from .constraint import MarathonConstraint
from .task import MarathonTask


class MarathonApp(MarathonResource):
    """Marathon Application resource.

    :param str cmd: cmd
    :param constraints: placement constraints
    :type constraints: list[:class:`marathon.models.constraint.MarathonConstraint`] or list[tuple]
    :param dict container: container
    :param float cpus: cpus required per instance
    :param dict env: env vars
    :param str executor: executor
    :param str id: app id
    :param int instances: instances
    :param float mem: memory (in MB) required per instance
    :param list[int] ports: ports
    :param list[str] uris: uris
    """

    UPDATE_OK_ATTRIBUTES = ['cmd', 'constraints', 'container', 'cpus', 'env', 'executor', 'mem', 'ports', 'uris']
    """List of attributes which may be updated/changed after app creation"""

    CREATE_ONLY_ATTRIBUTES = ['id']
    """List of attributes that should only be passed on creation"""

    READ_ONLY_ATTRIBUTES = []
    """List of read-only attributes"""

    def __init__(self, cmd=None, constraints=None, container=None, cpus=None, env=None, executor=None,
                 health_checks=None, id=None, instances=None, mem=None, ports=None, tasks=None, uris=None):
        self.cmd = cmd
        self.constraints = constraints or []
        self.container = container
        self.cpus = cpus
        self.env = env
        self.executor = executor
        self.health_checks = health_checks
        self.id = id
        self.instances = instances
        self.mem = mem
        self.ports = ports or []
        self.tasks = tasks or []
        self.uris = uris

    @classmethod
    def json_decode(cls, obj):
        """Construct a MarathonApp from a parsed response.

        :param dict attributes: object attributes from parsed response

        :rtype: :class:`MarathonApp`
        """
        return cls(
            cmd=obj.get('cmd'),
            constraints=[MarathonConstraint.json_decode(c) for c in obj.get('constraints', [])],
            container=obj.get('container'),
            cpus=obj.get('cpus'),
            env=obj.get('env'),
            executor=obj.get('executor'),
            health_checks=obj.get('healthChecks'),
            id=obj.get('id'),
            instances=obj.get('instances'),
            mem=obj.get('mem'),
            ports=obj.get('ports'),
            tasks=[MarathonTask.json_decode(t) for t in obj.get('tasks', [])],
            uris=obj.get('uris')
        )

    def json_encode(self):
{'fraction_non_alphanumeric': 0.11483967188665176, 'fraction_numerical': 0.0, 'mean_word_length': 2.7153739612188366, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '6053952', 'n_tokens_mistral': 1535, 'n_tokens_neox': 1493, 'n_words': 437}