<commit_before># Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import json

from dashboard.common import histogram_helpers
from dashboard.pinpoint.models.quest import execution
from dashboard.pinpoint.models.quest import quest
from dashboard.services import isolate
from tracing.value import histogram_set
from tracing.value.diagnostics import diagnostic_ref
from tracing.value.diagnostics import reserved_infos

class ReadValueError(Exception):

  pass

class ReadHistogramsJsonValue(quest.Quest):

  def __init__(self, results_filename, hist_name=None,
               tir_label=None, story=None, statistic=None):
    self._results_filename = results_filename
    self._hist_name = hist_name
    self._tir_label = tir_label
    self._story = story
    self._statistic = statistic

  def __eq__(self, other):
    return (isinstance(other, type(self)) and
            self._results_filename == other._results_filename and
            self._hist_name == other._hist_name and
            self._tir_label == other._tir_label and
            self._story == other._story and
            self._statistic == other._statistic)

  def __str__(self):
    return 'Values'

  def Start(self, change, isolate_server=None, isolate_hash=None):
    del change

    # TODO(dtu): Remove after data migration.
    # isolate_server and isolate_hash are required arguments.
    assert isolate_hash
    if not isolate_server:
      isolate_server = 'https://isolateserver.appspot.com'

    return _ReadHistogramsJsonValueExecution(
        self._results_filename, self._hist_name, self._tir_label,
        self._story, self._statistic, isolate_server, isolate_hash)

  @classmethod
  def FromDict(cls, arguments):
    benchmark = arguments.get('benchmark')
    if not benchmark:
      raise TypeError('Missing "benchmark" argument.')
    if arguments.get('target') == 'performance_test_suite':
      path_separator = '\\' if _IsWindows(arguments) else '/'
      results_filename = benchmark + path_separator + 'perf_results.json'
    else:
      # TODO: Remove this hack when all builders build performance_test_suite.
      results_filename = 'chartjson-output.json'

    chart = arguments.get('chart')
    tir_label = arguments.get('tir_label')
    trace = arguments.get('trace')
    statistic = arguments.get('statistic')

    return cls(results_filename, chart, tir_label, trace, statistic)

class _ReadHistogramsJsonValueExecution(execution.Execution):

  def __init__(self, results_filename, hist_name, tir_label,
               story, statistic, isolate_server, isolate_hash):
    super(_ReadHistogramsJsonValueExecution, self).__init__()
    self._results_filename = results_filename
    self._hist_name = hist_name
    self._tir_label = tir_label
    self._story = story
    self._statistic = statistic
    self._isolate_server = isolate_server
    self._isolate_hash = isolate_hash

    self._trace_urls = []

  def _AsDict(self):
    return [{
        'key': 'trace',
        'value': trace_url['name'],
        'url': trace_url['url'],
    } for trace_url in self._trace_urls]

  def _Poll(self):
    # TODO(dtu): Remove after data migration.
    if not hasattr(self, '_isolate_server'):
      self._isolate_server = 'https://isolateserver.appspot.com'
    if not hasattr(self, '_results_filename'):
      self._results_filename = 'chartjson-output.json'
    histogram_dicts = _RetrieveOutputJson(
        self._isolate_server, self._isolate_hash, self._results_filename)
    histograms = histogram_set.HistogramSet()
    histograms.ImportDicts(histogram_dicts)
    histograms.ResolveRelatedHistograms()

    matching_histograms = histograms.GetHistogramsNamed(self._hist_name)

    # Get and cache any trace URLs.
    unique_trace_urls = set()
    for hist in histograms:
      trace_urls = hist.diagnostics.get(reserved_infos.TRACE_URLS.name)
      # TODO(simonhatch): Remove this sometime after May 2018. We had a
      # brief period where the histograms generated by tests had invalid
      # trace_urls diagnostics. If the diagnostic we get back is just a ref,
      # then skip.
      # https://github.com/catapult-project/catapult/issues/4243
      if trace_urls and not isinstance(
          trace_urls, diagnostic_ref.DiagnosticRef):
        unique_trace_urls.update(trace_urls)

    sorted_urls = sorted(unique_trace_urls)
    self._trace_urls = [
        {'name': t.split('/')[-1], 'url': t} for t in sorted_urls]

    # Filter the histograms by tir_label and story. Getting either the
    # tir_label or the story from a histogram involves pulling out and
    # examining various diagnostics associated with the histogram.
    tir_label = self._tir_label or ''

    matching_histograms = [
        h for h in matching_histograms
        if tir_label == histogram_helpers.GetTIRLabelFromHistogram(h)]

    # If no story is supplied, we're looking for a summary metric so just match
    # on name and tir_label. This is equivalent to the chartjson condition that
    # if no story is specified, look for "summary".
    if self._story:
      matching_histograms = [
          h for h in matching_histograms
          if self._story == _GetStoryFromHistogram(h)]

    # Have to pull out either the raw sample values, or the statistic
    result_values = []
    for h in matching_histograms:
      result_values.extend(self._GetValuesOrStatistic(h))

    if not result_values and self._hist_name:
      conditions = {'histogram': self._hist_name}
      if tir_label:
        conditions['tir_label'] = tir_label
      if self._story:
        conditions['story'] = self._story
      raise ReadValueError('Could not find values matching: %s' % conditions)

    self._Complete(result_values=tuple(result_values))

  def _GetValuesOrStatistic(self, hist):
    if not self._statistic:
      return hist.sample_values

    if not hist.sample_values:
      return []

    # TODO(simonhatch): Use Histogram.getStatisticScalar when it's ported from
    # js.
    if self._statistic == 'avg':
      return [hist.running.mean]
    elif self._statistic == 'min':
      return [hist.running.min]
    elif self._statistic == 'max':
      return [hist.running.max]
    elif self._statistic == 'sum':
      return [hist.running.sum]
    elif self._statistic == 'std':
      return [hist.running.stddev]
    elif self._statistic == 'count':
      return [hist.running.count]
    raise ReadValueError('Unknown statistic type: %s' % self._statistic)

class ReadGraphJsonValue(quest.Quest):

  def __init__(self, chart, trace):
    self._chart = chart
    self._trace = trace

  def __eq__(self, other):
    return (isinstance(other, type(self)) and
            self._chart == other._chart and
            self._trace == other._trace)

  def __str__(self):
    return 'Values'

  def Start(self, change, isolate_server=None, isolate_hash=None):
    del change

    # TODO(dtu): Remove after data migration.
    # isolate_server and isolate_hash are required arguments.
    assert isolate_hash
    if not isolate_server:
      isolate_server = 'https://isolateserver.appspot.com'

    return _ReadGraphJsonValueExecution(
        self._chart, self._trace, isolate_server, isolate_hash)

  @classmethod
  def FromDict(cls, arguments):
    chart = arguments.get('chart')
    trace = arguments.get('trace')
    if not (chart or trace):
      return None
    if chart and not trace:
      raise TypeError('"chart" specified but no "trace" given.')
    if trace and not chart:
      raise TypeError('"trace" specified but no "chart" given.')
    return cls(chart, trace)

class _ReadGraphJsonValueExecution(execution.Execution):

  def __init__(self, chart, trace, isolate_server, isolate_hash):
    super(_ReadGraphJsonValueExecution, self).__init__()
    self._chart = chart
    self._trace = trace
    self._isolate_server = isolate_server
    self._isolate_hash = isolate_hash

  def _AsDict(self):
    # TODO(dtu): Remove after data migration.
    if not hasattr(self, '_isolate_server'):
      self._isolate_server = 'https://isolateserver.appspot.com'
    return {'isolate_server': self._isolate_server}

  def _Poll(self):
    # TODO(dtu): Remove after data migration.
    if not hasattr(self, '_isolate_server'):
      self._isolate_server = 'https://isolateserver.appspot.com'
    graphjson = _RetrieveOutputJson(
        self._isolate_server, self._isolate_hash, 'chartjson-output.json')

    if self._chart not in graphjson:
      raise ReadValueError('The chart "%s" is not in the results.' %
                           self._chart)
    if self._trace not in graphjson[self._chart]['traces']:
      raise ReadValueError('The trace "%s" is not in the results.' %
                           self._trace)
    result_value = float(graphjson[self._chart]['traces'][self._trace][0])

    self._Complete(result_values=(result_value,))

def _IsWindows(arguments):
  for dimension in arguments.get('dimensions', []):
    if dimension['key'] == 'os' and dimension['value'].startswith('Win'):
      return True
  return False

def _RetrieveOutputJson(isolate_server, isolate_hash, filename):
  output_files = json.loads(isolate.Retrieve(
      isolate_server, isolate_hash))['files']

  if filename not in output_files:
    raise ReadValueError("The test didn't produce %s." % filename)
  output_json_isolate_hash = output_files[filename]['h']
  return json.loads(isolate.Retrieve(isolate_server, output_json_isolate_hash))

def _GetStoryFromHistogram(hist):
  stories = hist.diagnostics.get(reserved_infos.STORIES.name)
  if stories and len(stories) == 1:
    return list(stories)[0]
  return None
<commit_msg>[pinpoint] Use ntpath.join instead of manual joining.<commit_after># Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import json
import ntpath
import posixpath

from dashboard.common import histogram_helpers
from dashboard.pinpoint.models.quest import execution
from dashboard.pinpoint.models.quest import quest
from dashboard.services import isolate
from tracing.value import histogram_set
from tracing.value.diagnostics import diagnostic_ref
from tracing.value.diagnostics import reserved_infos

class ReadValueError(Exception):

  pass

class ReadHistogramsJsonValue(quest.Quest):

  def __init__(self, results_filename, hist_name=None,
               tir_label=None, story=None, statistic=None):
    self._results_filename = results_filename
    self._hist_name = hist_name
    self._tir_label = tir_label
    self._story = story
    self._statistic = statistic

  def __eq__(self, other):
    return (isinstance(other, type(self)) and
            self._results_filename == other._results_filename and
            self._hist_name == other._hist_name and
            self._tir_label == other._tir_label and
            self._story == other._story and
            self._statistic == other._statistic)

  def __str__(self):
    return 'Values'

  def Start(self, change, isolate_server=None, isolate_hash=None):
    del change

    # TODO(dtu): Remove after data migration.
    # isolate_server and isolate_hash are required arguments.
    assert isolate_hash
    if not isolate_server:
      isolate_server = 'https://isolateserver.appspot.com'

    return _ReadHistogramsJsonValueExecution(
        self._results_filename, self._hist_name, self._tir_label,
        self._story, self._statistic, isolate_server, isolate_hash)

  @classmethod
  def FromDict(cls, arguments):
    benchmark = arguments.get('benchmark')
    if not benchmark:
      raise TypeError('Missing "benchmark" argument.')
    if arguments.get('target') == 'performance_test_suite':
      if _IsWindows(arguments):
        results_filename = ntpath.join(benchmark, 'perf_results.json')
      else:
        results_filename = posixpath.join(benchmark, 'perf_results.json')
    else:
      # TODO: Remove this hack when all builders build performance_test_suite.
      results_filename = 'chartjson-output.json'

    chart = arguments.get('chart')
    tir_label = arguments.get('tir_label')
    trace = arguments.get('trace')
    statistic = arguments.get('statistic')

    return cls(results_filename, chart, tir_label, trace, statistic)

class _ReadHistogramsJsonValueExecution(execution.Execution):

  def __init__(self, results_filename, hist_name, tir_label,
               story, statistic, isolate_server, isolate_hash):
    super(_ReadHistogramsJsonValueExecution, self).__init__()
    self._results_filename = results_filename
    self._hist_name = hist_name
    self._tir_label = tir_label
    self._story = story
    self._statistic = statistic
    self._isolate_server = isolate_server
    self._isolate_hash = isolate_hash

    self._trace_urls = []

  def _AsDict(self):
    return [{
        'key': 'trace',
        'value': trace_url['name'],
        'url': trace_url['url'],
    } for trace_url in self._trace_urls]

  def _Poll(self):
    # TODO(dtu): Remove after data migration.
    if not hasattr(self, '_isolate_server'):
      self._isolate_server = 'https://isolateserver.appspot.com'
    if not hasattr(self, '_results_filename'):
      self._results_filename = 'chartjson-output.json'
    histogram_dicts = _RetrieveOutputJson(
        self._isolate_server, self._isolate_hash, self._results_filename)
    histograms = histogram_set.HistogramSet()
    histograms.ImportDicts(histogram_dicts)
    histograms.ResolveRelatedHistograms()

    matching_histograms = histograms.GetHistogramsNamed(self._hist_name)

    # Get and cache any trace URLs.
    unique_trace_urls = set()
    for hist in histograms:
      trace_urls = hist.diagnostics.get(reserved_infos.TRACE_URLS.name)
      # TODO(simonhatch): Remove this sometime after May 2018. We had a
      # brief period where the histograms generated by tests had invalid
      # trace_urls diagnostics. If the diagnostic we get back is just a ref,
      # then skip.
      # https://github.com/catapult-project/catapult/issues/4243
      if trace_urls and not isinstance(
          trace_urls, diagnostic_ref.DiagnosticRef):
        unique_trace_urls.update(trace_urls)

    sorted_urls = sorted(unique_trace_urls)
    self._trace_urls = [
        {'name': t.split('/')[-1], 'url': t} for t in sorted_urls]

    # Filter the histograms by tir_label and story. Getting either the
    # tir_label or the story from a histogram involves pulling out and
    # examining various diagnostics associated with the histogram.
    tir_label = self._tir_label or ''

    matching_histograms = [
        h for h in matching_histograms
        if tir_label == histogram_helpers.GetTIRLabelFromHistogram(h)]

    # If no story is supplied, we're looking for a summary metric so just match
    # on name and tir_label. This is equivalent to the chartjson condition that
    # if no story is specified, look for "summary".
    if self._story:
      matching_histograms = [
          h for h in matching_histograms
          if self._story == _GetStoryFromHistogram(h)]

    # Have to pull out either the raw sample values, or the statistic
    result_values = []
    for h in matching_histograms:
      result_values.extend(self._GetValuesOrStatistic(h))

    if not result_values and self._hist_name:
      conditions = {'histogram': self._hist_name}
      if tir_label:
        conditions['tir_label'] = tir_label
      if self._story:
        conditions['story'] = self._story
      raise ReadValueError('Could not find values matching: %s' % conditions)

    self._Complete(result_values=tuple(result_values))

  def _GetValuesOrStatistic(self, hist):
    if not self._statistic:
      return hist.sample_values

    if not hist.sample_values:
      return []

    # TODO(simonhatch): Use Histogram.getStatisticScalar when it's ported from
    # js.
    if self._statistic == 'avg':
      return [hist.running.mean]
    elif self._statistic == 'min':
      return [hist.running.min]
    elif self._statistic == 'max':
      return [hist.running.max]
    elif self._statistic == 'sum':
      return [hist.running.sum]
    elif self._statistic == 'std':
      return [hist.running.stddev]
    elif self._statistic == 'count':
      return [hist.running.count]
    raise ReadValueError('Unknown statistic type: %s' % self._statistic)

class ReadGraphJsonValue(quest.Quest):

  def __init__(self, chart, trace):
    self._chart = chart
    self._trace = trace

  def __eq__(self, other):
    return (isinstance(other, type(self)) and
            self._chart == other._chart and
            self._trace == other._trace)

  def __str__(self):
    return 'Values'

  def Start(self, change, isolate_server=None, isolate_hash=None):
    del change

    # TODO(dtu): Remove after data migration.
    # isolate_server and isolate_hash are required arguments.
    assert isolate_hash
    if not isolate_server:
      isolate_server = 'https://isolateserver.appspot.com'

    return _ReadGraphJsonValueExecution(
        self._chart, self._trace, isolate_server, isolate_hash)

  @classmethod
  def FromDict(cls, arguments):
    chart = arguments.get('chart')
    trace = arguments.get('trace')
    if not (chart or trace):
      return None
    if chart and not trace:
      raise TypeError('"chart" specified but no "trace" given.')
    if trace and not chart:
      raise TypeError('"trace" specified but no "chart" given.')
    return cls(chart, trace)

class _ReadGraphJsonValueExecution(execution.Execution):

  def __init__(self, chart, trace, isolate_server, isolate_hash):
    super(_ReadGraphJsonValueExecution, self).__init__()
    self._chart = chart
    self._trace = trace
    self._isolate_server = isolate_server
    self._isolate_hash = isolate_hash

  def _AsDict(self):
    # TODO(dtu): Remove after data migration.
    if not hasattr(self, '_isolate_server'):
      self._isolate_server = 'https://isolateserver.appspot.com'
    return {'isolate_server': self._isolate_server}

  def _Poll(self):
    # TODO(dtu): Remove after data migration.
    if not hasattr(self, '_isolate_server'):
      self._isolate_server = 'https://isolateserver.appspot.com'
    graphjson = _RetrieveOutputJson(
        self._isolate_server, self._isolate_hash, 'chartjson-output.json')

    if self._chart not in graphjson:
      raise ReadValueError('The chart "%s" is not in the results.' %
                           self._chart)
    if self._trace not in graphjson[self._chart]['traces']:
      raise ReadValueError('The trace "%s" is not in the results.' %
                           self._trace)
    result_value = float(graphjson[self._chart]['traces'][self._trace][0])

    self._Complete(result_values=(result_value,))

def _IsWindows(arguments):
  for dimension in arguments.get('dimensions', []):
    if dimension['key'] == 'os' and dimension['value'].startswith('Win'):
      return True
  return False

def _RetrieveOutputJson(isolate_server, isolate_hash, filename):
  output_files = json.loads(isolate.Retrieve(
      isolate_server, isolate_hash))['files']

  if filename not in output_files:
    raise ReadValueError("The test didn't produce %s." % filename)
  output_json_isolate_hash = output_files[filename]['h']
  return json.loads(isolate.Retrieve(isolate_server, output_json_isolate_hash))

def _GetStoryFromHistogram(hist):
  stories = hist.diagnostics.get(reserved_infos.STORIES.name)
  if stories and len(stories) == 1:
    return list(stories)[0]
  return None
<|endoftext|>


<commit_before># (C) Datadog, Inc. 2018-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)
import os
from collections import deque
from copy import deepcopy

import toml
from atomicwrites import atomic_write
from platformdirs import user_data_dir

from ..fs import ensure_parent_dir_exists, file_exists, read_file

APP_DIR = user_data_dir('dd-checks-dev', False)
CONFIG_FILE = os.path.join(APP_DIR, 'config.toml')

SECRET_KEYS = {
    'dd_api_key',
    'dd_app_key',
    'orgs.*.api_key',
    'orgs.*.app_key',
    'github.token',
    'pypi.pass',
    'trello.key',
    'trello.token',
}

DEFAULT_CONFIG = {
    'repo': 'core',
    'agent': 'master',
    'org': 'default',
    'color': bool(int(os.environ['DDEV_COLOR'])) if 'DDEV_COLOR' in os.environ else None,
    'dd_api_key': os.getenv('DD_API_KEY'),
    'dd_app_key': os.getenv('DD_APP_KEY'),
    'github': {'user': '', 'token': ''},
    'pypi': {'user': '', 'pass': ''},
    'trello': {'key': '', 'token': ''},
    'repos': {
        'core': os.path.join('~', 'dd', 'integrations-core'),
        'extras': os.path.join('~', 'dd', 'integrations-extras'),
        'agent': os.path.join('~', 'dd', 'datadog-agent'),
        'marketplace': os.path.join('~', 'dd', 'marketplace'),
        'integrations': os.path.join('~', 'dd', 'integrations'),
    },
    'agents': {
        'master': {'docker': 'datadog/agent-dev:master', 'local': 'latest'},
        '7': {'docker': 'datadog/agent:7', 'local': '7'},
        '6': {'docker': 'datadog/agent:6', 'local': '6'},
    },
    'orgs': {
        'default': {
            'api_key': os.getenv('DD_API_KEY'),
            'app_key': os.getenv('DD_APP_KEY'),
            'site': os.getenv('DD_SITE'),
            'dd_url': os.getenv('DD_DD_URL'),
            'log_url': os.getenv('DD_LOGS_CONFIG_DD_URL'),
        }
    },
}

def config_file_exists():
    return file_exists(CONFIG_FILE)

def copy_default_config():
    return deepcopy(DEFAULT_CONFIG)

def save_config(config):
    ensure_parent_dir_exists(CONFIG_FILE)
    with atomic_write(CONFIG_FILE, mode='wb', overwrite=True) as f:
        f.write(toml.dumps(config).encode('utf-8'))

def load_config():
    config = copy_default_config()

    try:
        config.update(toml.loads(read_config_file()))
    except FileNotFoundError:
        pass

    return config

def read_config_file():
    return read_file(CONFIG_FILE)

def read_config_file_scrubbed():
    return toml.dumps(scrub_secrets(load_config()))

def restore_config():
    config = copy_default_config()
    save_config(config)
    return config

def update_config():
    config = copy_default_config()
    config.update(load_config())

    save_config(config)
    return config

def scrub_secrets(config):
    for secret_key in SECRET_KEYS:
        branch = config
        paths = deque(secret_key.split('.'))

        while paths:
            path = paths.popleft()
            if not hasattr(branch, 'get'):
                break

            if path in branch:
                if not paths:
                    old_value = branch[path]
                    if isinstance(old_value, str):
                        branch[path] = '*' * len(old_value)
                else:
                    branch = branch[path]
            else:
                break

    for data in config.get('orgs', {}).values():
        api_key = data.get('api_key')
        if api_key:
            data['api_key'] = '*' * len(api_key)

        app_key = data.get('app_key')
        if app_key:
            data['app_key'] = '*' * len(app_key)

    return config
<commit_msg>Fixed `validate manifest` command by providing default config for `dd_url` setting (#13057)<commit_after># (C) Datadog, Inc. 2018-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)
import os
from collections import deque
from copy import deepcopy

import toml
from atomicwrites import atomic_write
from platformdirs import user_data_dir

from ..fs import ensure_parent_dir_exists, file_exists, read_file

APP_DIR = user_data_dir('dd-checks-dev', False)
CONFIG_FILE = os.path.join(APP_DIR, 'config.toml')

SECRET_KEYS = {
    'dd_api_key',
    'dd_app_key',
    'orgs.*.api_key',
    'orgs.*.app_key',
    'github.token',
    'pypi.pass',
    'trello.key',
    'trello.token',
}

DEFAULT_CONFIG = {
    'repo': 'core',
    'agent': 'master',
    'org': 'default',
    'color': bool(int(os.environ['DDEV_COLOR'])) if 'DDEV_COLOR' in os.environ else None,
    'dd_api_key': os.getenv('DD_API_KEY'),
    'dd_app_key': os.getenv('DD_APP_KEY'),
    'github': {'user': '', 'token': ''},
    'pypi': {'user': '', 'pass': ''},
    'trello': {'key': '', 'token': ''},
    'repos': {
        'core': os.path.join('~', 'dd', 'integrations-core'),
        'extras': os.path.join('~', 'dd', 'integrations-extras'),
        'agent': os.path.join('~', 'dd', 'datadog-agent'),
        'marketplace': os.path.join('~', 'dd', 'marketplace'),
        'integrations': os.path.join('~', 'dd', 'integrations'),
    },
    'agents': {
        'master': {'docker': 'datadog/agent-dev:master', 'local': 'latest'},
        '7': {'docker': 'datadog/agent:7', 'local': '7'},
        '6': {'docker': 'datadog/agent:6', 'local': '6'},
    },
    'orgs': {
        'default': {
            'api_key': os.getenv('DD_API_KEY'),
            'app_key': os.getenv('DD_APP_KEY'),
            'site': os.getenv('DD_SITE'),
            'dd_url': os.getenv('DD_DD_URL', 'https://app.datadoghq.com'),
            'log_url': os.getenv('DD_LOGS_CONFIG_DD_URL'),
        }
    },
}

def config_file_exists():
    return file_exists(CONFIG_FILE)

def copy_default_config():
    return deepcopy(DEFAULT_CONFIG)

def save_config(config):
    ensure_parent_dir_exists(CONFIG_FILE)
    with atomic_write(CONFIG_FILE, mode='wb', overwrite=True) as f:
        f.write(toml.dumps(config).encode('utf-8'))

def load_config():
    config = copy_default_config()

    try:
        config.update(toml.loads(read_config_file()))
    except FileNotFoundError:
        pass

    return config

def read_config_file():
    return read_file(CONFIG_FILE)

def read_config_file_scrubbed():
    return toml.dumps(scrub_secrets(load_config()))

def restore_config():
    config = copy_default_config()
    save_config(config)
    return config

def update_config():
    config = copy_default_config()
    config.update(load_config())

    save_config(config)
    return config

def scrub_secrets(config):
    for secret_key in SECRET_KEYS:
        branch = config
        paths = deque(secret_key.split('.'))

        while paths:
            path = paths.popleft()
            if not hasattr(branch, 'get'):
                break

            if path in branch:
                if not paths:
                    old_value = branch[path]
                    if isinstance(old_value, str):
                        branch[path] = '*' * len(old_value)
                else:
                    branch = branch[path]
            else:
                break

    for data in config.get('orgs', {}).values():
        api_key = data.get('api_key')
        if api_key:
            data['api_key'] = '*' * len(api_key)

        app_key = data.get('app_key')
        if app_key:
            data['app_key'] = '*' * len(app_key)

    return config
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Copyright 2013-2017 Yannick Vaucher (Camptocamp SA)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import json
from odoo import api, fields, models

class PostlogisticsLicense(models.Model):
    _name = 'postlogistics.license'
    _description = 'PostLogistics Franking License'

    _order = 'sequence'

    name = fields.Char(string='Description',
                       translate=True,
                       required=True)
    number = fields.Char(string='Number',
                         required=True)
    company_id = fields.Many2one(comodel_name='res.company',
                                 string='Company',
                                 required=True,
                                 default=lambda self: self.env.user.company_id)
    sequence = fields.Integer(
        string='Sequence',
        help="Gives the sequence on company to define priority on license "
             "when multiple licenses are available for the same group of "
             "service."
    )

class PostlogisticsServiceGroup(models.Model):
    _name = 'postlogistics.service.group'
    _description = 'PostLogistics Service Group'

    name = fields.Char(string='Description', translate=True, required=True)
    group_extid = fields.Integer(string='Group ID', required=True)
    postlogistics_license_ids = fields.Many2many(
        comodel_name='postlogistics.license',
        relation='postlogistics_license_service_groups_rel',
        column1='license_id',
        column2='group_id',
        string='PostLogistics Franking License')

    _sql_constraints = [
        ('group_extid_uniq', 'unique(group_extid)',
         "A service group ID must be unique.")
    ]

POSTLOGISTIC_TYPES = [
    ('label_layout', 'Label Layout'),
    ('output_format', 'Output Format'),
    ('resolution', 'Output Resolution'),
    ('basic', 'Basic Service'),
    ('additional', 'Additional Service'),
    ('delivery', 'Delivery Instructions')
]

class DeliveryCarrierTemplateOption(models.Model):
    """ Set name translatable and add service group """
    _inherit = 'delivery.carrier.template.option'

    name = fields.Char(translate=True)
    postlogistics_service_group_id = fields.Many2one(
        comodel_name='postlogistics.service.group',
        string='PostLogistics Service Group',
    )
    postlogistics_type = fields.Selection(
        selection=POSTLOGISTIC_TYPES,
        string="PostLogistics option type",
    )
    # relation tables to manage compatiblity between basic services
    # and other services
    postlogistics_basic_service_ids = fields.Many2many(
        comodel_name='delivery.carrier.template.option',
        relation='postlogistics_compatibility_service_rel',
        column1='service_id',
        column2='basic_service_id',
        string="Basic Services",
        domain=[('postlogistics_type', '=', 'basic')],
        help="List of basic service for which this service is compatible",
    )
    postlogistics_additonial_service_ids = fields.Many2many(
        comodel_name='delivery.carrier.template.option',
        relation='postlogistics_compatibility_service_rel',
        column1='basic_service_id',
        column2='service_id',
        string="Compatible Additional Services",
        domain=[('postlogistics_type', '=', 'additional')],
    )
    postlogistics_delivery_instruction_ids = fields.Many2many(
        comodel_name='delivery.carrier.template.option',
        relation='postlogistics_compatibility_service_rel',
        column1='basic_service_id',
        column2='service_id',
        string="Compatible Delivery Instructions",
        domain=[('postlogistics_type', '=', 'delivery')],
    )

class DeliveryCarrierOption(models.Model):
    """ Set name translatable and add service group """
    _inherit = 'delivery.carrier.option'

    name = fields.Char(translate=True)

    tmpl_option_id_domain = fields.Char(
        compute='_compute_tmpl_option_id_domain'
    )

    @api.depends('carrier_id.allowed_options_domain')
    def _compute_tmpl_option_id_domain(self):
        """ Gets the domain from related delivery.carrier
            (be it from cache or context) """
        for option in self:
            domain = self.env.context.get('default_tmpl_option_id_domain')
            option.tmpl_option_id_domain = (
                option.carrier_id.allowed_options_domain or domain or '[]')

class DeliveryCarrier(models.Model):
    """ Add service group """
    _inherit = 'delivery.carrier'

    delivery_type = fields.Selection(selection_add=[('postlogistics',
                                                     'Post logistics')])

    @api.depends('delivery_type',
                 'available_option_ids',
                 'available_option_ids.tmpl_option_id',
                 'available_option_ids.postlogistics_type',
                 )
    def _compute_basic_service_ids(self):
        """ Search in all options for PostLogistics basic services if set """
        for carrier in self:
            if carrier.delivery_type != 'postlogistics':
                continue

            options = carrier.available_option_ids.filtered(
                lambda option: option.postlogistics_type == 'basic'
            ).mapped('tmpl_option_id')

            if not options:
                continue
            self.postlogistics_basic_service_ids = options

    @api.depends('delivery_type',
                 'postlogistics_service_group_id',
                 'postlogistics_basic_service_ids',
                 'postlogistics_basic_service_ids',
                 'available_option_ids',
                 'available_option_ids.postlogistics_type',
                 )
    def _compute_allowed_options_domain(self):
        """ Return a domain of possible options

        We do this to ensure the user first select a basic service. And
        then he adds additional services.

        """
        option_template_obj = self.env['delivery.carrier.template.option']

        for carrier in self:
            allowed = option_template_obj.browse()
            domain = []
            if carrier.delivery_type != 'postlogistics':
                domain.append(('partner_id', '=', False))
            else:
                service_group = carrier.postlogistics_service_group_id
                if service_group:
                    basic_services = carrier.postlogistics_basic_service_ids
                    services = option_template_obj.search(
                        [('postlogistics_service_group_id', '=',
                          service_group.id)]
                    )
                    allowed |= services
                    if basic_services:
                        related_services = option_template_obj.search(
                            [('postlogistics_basic_service_ids', 'in',
                              basic_services.ids)]
                        )
                        allowed |= related_services

                # Allows to set multiple optional single option in order to
                # let the user select them
                single_option_types = [
                    'label_layout',
                    'output_format',
                    'resolution',
                ]
                selected_single_options = [
                    opt.tmpl_option_id.postlogistics_type
                    for opt in carrier.available_option_ids
                    if opt.postlogistics_type in single_option_types and
                    opt.mandatory]
                if selected_single_options != single_option_types:
                    services = option_template_obj.search(
                        [('postlogistics_type', 'in', single_option_types),
                         ('postlogistics_type', 'not in',
                          selected_single_options)],
                    )
                    allowed |= services
                partner = self.env.ref('delivery_carrier_label_postlogistics'
                                       '.partner_postlogistics')
                domain.append(('partner_id', '=', partner.id)),
                domain.append(('id', 'in', allowed.ids))

            carrier.allowed_options_domain = json.dumps(domain)

    postlogistics_license_id = fields.Many2one(
        comodel_name='postlogistics.license',
        string='PostLogistics Franking License',
    )
    postlogistics_service_group_id = fields.Many2one(
        comodel_name='postlogistics.service.group',
        string='PostLogistics Service Group',
        help="Service group defines the available options for "
             "this delivery method.",
    )
    postlogistics_basic_service_ids = fields.One2many(
        comodel_name='delivery.carrier.template.option',
        compute='_compute_basic_service_ids',
        string='PostLogistics Service Group',
        help="Basic Service defines the available "
             "additional options for this delivery method",
    )

    allowed_options_domain = fields.Char(
        compute="_compute_allowed_options_domain",
        store=False,
    )
<commit_msg>Define postlogistics_ methods<commit_after># -*- coding: utf-8 -*-
# Copyright 2013-2017 Yannick Vaucher (Camptocamp SA)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
import json
from odoo import api, fields, models
from odoo.exceptions import UserError

_logger = logging.getLogger(__name__)

class PostlogisticsLicense(models.Model):
    _name = 'postlogistics.license'
    _description = 'PostLogistics Franking License'

    _order = 'sequence'

    name = fields.Char(string='Description',
                       translate=True,
                       required=True)
    number = fields.Char(string='Number',
                         required=True)
    company_id = fields.Many2one(comodel_name='res.company',
                                 string='Company',
                                 required=True,
                                 default=lambda self: self.env.user.company_id)
    sequence = fields.Integer(
        string='Sequence',
        help="Gives the sequence on company to define priority on license "
             "when multiple licenses are available for the same group of "
             "service."
    )

class PostlogisticsServiceGroup(models.Model):
    _name = 'postlogistics.service.group'
    _description = 'PostLogistics Service Group'

    name = fields.Char(string='Description', translate=True, required=True)
    group_extid = fields.Integer(string='Group ID', required=True)
    postlogistics_license_ids = fields.Many2many(
        comodel_name='postlogistics.license',
        relation='postlogistics_license_service_groups_rel',
        column1='license_id',
        column2='group_id',
        string='PostLogistics Franking License')

    _sql_constraints = [
        ('group_extid_uniq', 'unique(group_extid)',
         "A service group ID must be unique.")
    ]

POSTLOGISTIC_TYPES = [
    ('label_layout', 'Label Layout'),
    ('output_format', 'Output Format'),
    ('resolution', 'Output Resolution'),
    ('basic', 'Basic Service'),
    ('additional', 'Additional Service'),
    ('delivery', 'Delivery Instructions')
]

class DeliveryCarrierTemplateOption(models.Model):
    """ Set name translatable and add service group """
    _inherit = 'delivery.carrier.template.option'

    name = fields.Char(translate=True)
    postlogistics_service_group_id = fields.Many2one(
        comodel_name='postlogistics.service.group',
        string='PostLogistics Service Group',
    )
    postlogistics_type = fields.Selection(
        selection=POSTLOGISTIC_TYPES,
        string="PostLogistics option type",
    )
    # relation tables to manage compatiblity between basic services
    # and other services
    postlogistics_basic_service_ids = fields.Many2many(
        comodel_name='delivery.carrier.template.option',
        relation='postlogistics_compatibility_service_rel',
        column1='service_id',
        column2='basic_service_id',
        string="Basic Services",
        domain=[('postlogistics_type', '=', 'basic')],
        help="List of basic service for which this service is compatible",
    )
    postlogistics_additonial_service_ids = fields.Many2many(
        comodel_name='delivery.carrier.template.option',
        relation='postlogistics_compatibility_service_rel',
        column1='basic_service_id',
        column2='service_id',
        string="Compatible Additional Services",
        domain=[('postlogistics_type', '=', 'additional')],
    )
    postlogistics_delivery_instruction_ids = fields.Many2many(
        comodel_name='delivery.carrier.template.option',
        relation='postlogistics_compatibility_service_rel',
        column1='basic_service_id',
        column2='service_id',
        string="Compatible Delivery Instructions",
        domain=[('postlogistics_type', '=', 'delivery')],
    )

class DeliveryCarrierOption(models.Model):
    """ Set name translatable and add service group """
    _inherit = 'delivery.carrier.option'

    name = fields.Char(translate=True)

    tmpl_option_id_domain = fields.Char(
        compute='_compute_tmpl_option_id_domain'
    )

    @api.depends('carrier_id.allowed_options_domain')
    def _compute_tmpl_option_id_domain(self):
        """ Gets the domain from related delivery.carrier
            (be it from cache or context) """
        for option in self:
            domain = self.env.context.get('default_tmpl_option_id_domain')
            option.tmpl_option_id_domain = (
                option.carrier_id.allowed_options_domain or domain or '[]')

class DeliveryCarrier(models.Model):
    """ Add service group """
    _inherit = 'delivery.carrier'

    delivery_type = fields.Selection(selection_add=[('postlogistics',
                                                     'Post logistics')])

    @api.depends('delivery_type',
                 'available_option_ids',
                 'available_option_ids.tmpl_option_id',
                 'available_option_ids.postlogistics_type',
                 )
    def _compute_basic_service_ids(self):
        """ Search in all options for PostLogistics basic services if set """
        for carrier in self:
            if carrier.delivery_type != 'postlogistics':
                continue

            options = carrier.available_option_ids.filtered(
                lambda option: option.postlogistics_type == 'basic'
            ).mapped('tmpl_option_id')

            if not options:
                continue
            self.postlogistics_basic_service_ids = options

    @api.depends('delivery_type',
                 'postlogistics_service_group_id',
                 'postlogistics_basic_service_ids',
                 'postlogistics_basic_service_ids',
                 'available_option_ids',
                 'available_option_ids.postlogistics_type',
                 )
    def _compute_allowed_options_domain(self):
        """ Return a domain of possible options

        We do this to ensure the user first select a basic service. And
        then he adds additional services.

        """
        option_template_obj = self.env['delivery.carrier.template.option']

        for carrier in self:
            allowed = option_template_obj.browse()
            domain = []
            if carrier.delivery_type != 'postlogistics':
                domain.append(('partner_id', '=', False))
            else:
                service_group = carrier.postlogistics_service_group_id
                if service_group:
                    basic_services = carrier.postlogistics_basic_service_ids
                    services = option_template_obj.search(
                        [('postlogistics_service_group_id', '=',
                          service_group.id)]
                    )
                    allowed |= services
                    if basic_services:
                        related_services = option_template_obj.search(
                            [('postlogistics_basic_service_ids', 'in',
                              basic_services.ids)]
                        )
                        allowed |= related_services

                # Allows to set multiple optional single option in order to
                # let the user select them
                single_option_types = [
                    'label_layout',
                    'output_format',
                    'resolution',
                ]
                selected_single_options = [
                    opt.tmpl_option_id.postlogistics_type
                    for opt in carrier.available_option_ids
                    if opt.postlogistics_type in single_option_types and
                    opt.mandatory]
                if selected_single_options != single_option_types:
                    services = option_template_obj.search(
                        [('postlogistics_type', 'in', single_option_types),
                         ('postlogistics_type', 'not in',
                          selected_single_options)],
                    )
                    allowed |= services
                partner = self.env.ref('delivery_carrier_label_postlogistics'
                                       '.partner_postlogistics')
                domain.append(('partner_id', '=', partner.id)),
                domain.append(('id', 'in', allowed.ids))

            carrier.allowed_options_domain = json.dumps(domain)

    postlogistics_license_id = fields.Many2one(
        comodel_name='postlogistics.license',
        string='PostLogistics Franking License',
    )
    postlogistics_service_group_id = fields.Many2one(
        comodel_name='postlogistics.service.group',
        string='PostLogistics Service Group',
        help="Service group defines the available options for "
             "this delivery method.",
    )
    postlogistics_basic_service_ids = fields.One2many(
        comodel_name='delivery.carrier.template.option',
        compute='_compute_basic_service_ids',
        string='PostLogistics Service Group',
        help="Basic Service defines the available "
             "additional options for this delivery method",
    )

    allowed_options_domain = fields.Char(
        compute="_compute_allowed_options_domain",
        store=False,
    )

    @api.multi
    def postlogistics_get_shipping_price_from_so(self, order):
        self.ensure_one()
        try:
            computed_price = self.get_price_available(order)
            self.available = True
        except UserError as e:
            # No suitable delivery method found, probably configuration error
            _logger.info("Carrier %s: %s", self.name, e.name)
            computed_price = 0.0

        return [computed_price * (1.0 + (float(self.margin) / 100.0))]

    @api.multi
    def postlogistics_send_shipping(self, pickings):
        return [{'exact_price': False, 'tracking_number': False}]

    @api.multi
    def postlogistics_get_tracking_link(self, pickings):
        return False

    @api.multi
    def postlogistics_cancel_shipment(self, pickings):
        return False
<|endoftext|>


<commit_before>from django.db.backends.postgresql_psycopg2.introspection import DatabaseIntrospection
from django.contrib.gis.gdal import OGRGeomType

class GeoIntrospectionError(Exception):
    pass

class PostGISIntrospection(DatabaseIntrospection):
    # Reverse dictionary for PostGIS geometry types not populated until
    # introspection is actually performed.
    postgis_types_reverse = {}

    ignored_tables = DatabaseIntrospection.ignored_tables + [
        'geography_columns',
        'geometry_columns',
        'raster_columns',
        'spatial_ref_sys',
        'raster_overviews',
    ]

    def get_postgis_types(self):
        """
        Returns a dictionary with keys that are the PostgreSQL object
        identification integers for the PostGIS geometry and/or
        geography types (if supported).
        """
        field_types = [('geometry', 'GeometryField')]
        if self.connection.ops.geography:
            # The value for the geography type is actually a tuple
            # to pass in the `geography=True` keyword to the field
            # definition.
            field_types.append(('geography', ('GeometryField', {'geography' : True})))
        postgis_types = {}

        # The OID integers associated with the geometry type may
        # be different across versions; hence, this is why we have
        # to query the PostgreSQL pg_type table corresponding to the
        # PostGIS custom data types.
        oid_sql = 'SELECT "oid" FROM "pg_type" WHERE "typname" = %s'
        cursor = self.connection.cursor()
        try:
            for field_type in field_types:
                cursor.execute(oid_sql, (field_type[0],))
                for result in cursor.fetchall():
                    postgis_types[result[0]] = field_type[1]
        finally:
            cursor.close()

        return postgis_types

    def get_field_type(self, data_type, description):
        if not self.postgis_types_reverse:
            # If the PostGIS types reverse dictionary is not populated, do so
            # now.  In order to prevent unnecessary requests upon connection
            # initialization, the `data_types_reverse` dictionary is not updated
            # with the PostGIS custom types until introspection is actually
            # performed -- in other words, when this function is called.
            self.postgis_types_reverse = self.get_postgis_types()
            self.data_types_reverse.update(self.postgis_types_reverse)
        return super(PostGISIntrospection, self).get_field_type(data_type, description)

    def get_geometry_type(self, table_name, geo_col):
        """
        The geometry type OID used by PostGIS does not indicate the particular
        type of field that a geometry column is (e.g., whether it's a
        PointField or a PolygonField).  Thus, this routine queries the PostGIS
        metadata tables to determine the geometry type,
        """
        cursor = self.connection.cursor()
        try:
            try:
                # First seeing if this geometry column is in the `geometry_columns`
                cursor.execute('SELECT "coord_dimension", "srid", "type" '
                               'FROM "geometry_columns" '
                               'WHERE "f_table_name"=%s AND "f_geometry_column"=%s',
                               (table_name, geo_col))
                row = cursor.fetchone()
                if not row:
                    raise GeoIntrospectionError
            except GeoIntrospectionError:
                if self.connection.ops.geography:
                    cursor.execute('SELECT "coord_dimension", "srid", "type" '
                                   'FROM "geography_columns" '
                                   'WHERE "f_table_name"=%s AND "f_geography_column"=%s',
                                   (table_name, geo_col))
                    row = cursor.fetchone()

            if not row:
                raise Exception('Could not find a geometry or geography column for "%s"."%s"' %
                                (table_name, geo_col))

            # OGRGeomType does not require GDAL and makes it easy to convert
            # from OGC geom type name to Django field.
            field_type = OGRGeomType(row[2]).django

            # Getting any GeometryField keyword arguments that are not the default.
            dim = row[0]
            srid = row[1]
            field_params = {}
            if srid != 4326:
                field_params['srid'] = srid
            if dim != 2:
                field_params['dim'] = dim
        finally:
            cursor.close()

        return field_type, field_params
<commit_msg>Fixed a flake8 warning<commit_after>from django.db.backends.postgresql_psycopg2.introspection import DatabaseIntrospection
from django.contrib.gis.gdal import OGRGeomType

class GeoIntrospectionError(Exception):
    pass

class PostGISIntrospection(DatabaseIntrospection):
    # Reverse dictionary for PostGIS geometry types not populated until
    # introspection is actually performed.
    postgis_types_reverse = {}

    ignored_tables = DatabaseIntrospection.ignored_tables + [
        'geography_columns',
        'geometry_columns',
        'raster_columns',
        'spatial_ref_sys',
        'raster_overviews',
    ]

    def get_postgis_types(self):
        """
        Returns a dictionary with keys that are the PostgreSQL object
        identification integers for the PostGIS geometry and/or
        geography types (if supported).
        """
        field_types = [('geometry', 'GeometryField')]
        if self.connection.ops.geography:
            # The value for the geography type is actually a tuple
            # to pass in the `geography=True` keyword to the field
            # definition.
            field_types.append(('geography', ('GeometryField', {'geography': True})))
        postgis_types = {}

        # The OID integers associated with the geometry type may
        # be different across versions; hence, this is why we have
        # to query the PostgreSQL pg_type table corresponding to the
        # PostGIS custom data types.
        oid_sql = 'SELECT "oid" FROM "pg_type" WHERE "typname" = %s'
        cursor = self.connection.cursor()
        try:
            for field_type in field_types:
                cursor.execute(oid_sql, (field_type[0],))
                for result in cursor.fetchall():
                    postgis_types[result[0]] = field_type[1]
        finally:
            cursor.close()

        return postgis_types

    def get_field_type(self, data_type, description):
        if not self.postgis_types_reverse:
            # If the PostGIS types reverse dictionary is not populated, do so
            # now.  In order to prevent unnecessary requests upon connection
            # initialization, the `data_types_reverse` dictionary is not updated
            # with the PostGIS custom types until introspection is actually
            # performed -- in other words, when this function is called.
            self.postgis_types_reverse = self.get_postgis_types()
            self.data_types_reverse.update(self.postgis_types_reverse)
        return super(PostGISIntrospection, self).get_field_type(data_type, description)

    def get_geometry_type(self, table_name, geo_col):
        """
        The geometry type OID used by PostGIS does not indicate the particular
        type of field that a geometry column is (e.g., whether it's a
        PointField or a PolygonField).  Thus, this routine queries the PostGIS
        metadata tables to determine the geometry type,
        """
        cursor = self.connection.cursor()
        try:
            try:
                # First seeing if this geometry column is in the `geometry_columns`
                cursor.execute('SELECT "coord_dimension", "srid", "type" '
                               'FROM "geometry_columns" '
                               'WHERE "f_table_name"=%s AND "f_geometry_column"=%s',
                               (table_name, geo_col))
                row = cursor.fetchone()
                if not row:
                    raise GeoIntrospectionError
            except GeoIntrospectionError:
                if self.connection.ops.geography:
                    cursor.execute('SELECT "coord_dimension", "srid", "type" '
                                   'FROM "geography_columns" '
                                   'WHERE "f_table_name"=%s AND "f_geography_column"=%s',
                                   (table_name, geo_col))
                    row = cursor.fetchone()

            if not row:
                raise Exception('Could not find a geometry or geography column for "%s"."%s"' %
                                (table_name, geo_col))

            # OGRGeomType does not require GDAL and makes it easy to convert
            # from OGC geom type name to Django field.
            field_type = OGRGeomType(row[2]).django

            # Getting any GeometryField keyword arguments that are not the default.
            dim = row[0]
            srid = row[1]
            field_params = {}
            if srid != 4326:
                field_params['srid'] = srid
            if dim != 2:
                field_params['dim'] = dim
        finally:
            cursor.close()

        return field_type, field_params
<|endoftext|>


<commit_before>from django.core.management.base import BaseCommand, CommandError
from optparse import make_option
import os
import sys

def null_technical_500_response(request, exc_type, exc_value, tb):
    raise exc_type, exc_value, tb

class Command(BaseCommand):
    option_list = BaseCommand.option_list + (
        make_option('--noreload', action='store_false', dest='use_reloader', default=True,
            help='Tells Django to NOT use the auto-reloader.'),
        make_option('--adminmedia', dest='admin_media_path', default='',
            help='Specifies the directory from which to serve admin media.'),
    )
    help = "Starts a lightweight Web server for development."
    args = '[optional port number, or ipaddr:port]'

    # Validation is called explicitly each time the server is reloaded.
    requires_model_validation = False

    def handle(self, addrport='', *args, **options):
        import django
        from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
        from django.core.handlers.wsgi import WSGIHandler
        try:
            from werkzeug import run_simple, DebuggedApplication
        except:
            raise CommandError("Werkzeug is required to use runserver_plus.  Please visit http://werkzeug.pocoo.org/download")

        # usurp django's handler
        from django.views import debug
        debug.technical_500_response = null_technical_500_response

        if args:
            raise CommandError('Usage is runserver %s' % self.args)
        if not addrport:
            addr = ''
            port = '8000'
        else:
            try:
                addr, port = addrport.split(':')
            except ValueError:
                addr, port = '', addrport
        if not addr:
            addr = '127.0.0.1'

        if not port.isdigit():
            raise CommandError("%r is not a valid port number." % port)

        use_reloader = options.get('use_reloader', True)
        admin_media_path = options.get('admin_media_path', '')
        shutdown_message = options.get('shutdown_message', '')
        quit_command = (sys.platform == 'win32') and 'CTRL-BREAK' or 'CONTROL-C'

        def inner_run():
            from django.conf import settings
            print "Validating models..."
            self.validate(display_num_errors=True)
            print "\nDjango version %s, using settings %r" % (django.get_version(), settings.SETTINGS_MODULE)
            print "Development server is running at http://%s:%s/" % (addr, port)
            print "Using the Werkzeug debugger (http://werkzeug.pocoo.org/)"
            print "Quit the server with %s." % quit_command
            path = admin_media_path or django.__path__[0] + '/contrib/admin/media'
            handler = AdminMediaHandler(WSGIHandler(), path)
            run_simple(addr, int(port), DebuggedApplication(handler, True),
                       use_reloader=use_reloader, use_debugger=True)
        inner_run()
<commit_msg>added browser option to runserver_plus that uses Python's webrowser module to open the location of the server automatically<commit_after>from django.core.management.base import BaseCommand, CommandError
from optparse import make_option
import os
import sys

def null_technical_500_response(request, exc_type, exc_value, tb):
    raise exc_type, exc_value, tb

class Command(BaseCommand):
    option_list = BaseCommand.option_list + (
        make_option('--noreload', action='store_false', dest='use_reloader', default=True,
            help='Tells Django to NOT use the auto-reloader.'),
        make_option('--browser', action='store_true', dest='open_browser',
            help='Tells Django to open a browser.'),
        make_option('--adminmedia', dest='admin_media_path', default='',
            help='Specifies the directory from which to serve admin media.'),
    )
    help = "Starts a lightweight Web server for development."
    args = '[optional port number, or ipaddr:port]'

    # Validation is called explicitly each time the server is reloaded.
    requires_model_validation = False

    def handle(self, addrport='', *args, **options):
        import django
        from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
        from django.core.handlers.wsgi import WSGIHandler
        try:
            from werkzeug import run_simple, DebuggedApplication
        except:
            raise CommandError("Werkzeug is required to use runserver_plus.  Please visit http://werkzeug.pocoo.org/download")

        # usurp django's handler
        from django.views import debug
        debug.technical_500_response = null_technical_500_response

        if args:
            raise CommandError('Usage is runserver %s' % self.args)
        if not addrport:
            addr = ''
            port = '8000'
        else:
            try:
                addr, port = addrport.split(':')
            except ValueError:
                addr, port = '', addrport
        if not addr:
            addr = '127.0.0.1'

        if not port.isdigit():
            raise CommandError("%r is not a valid port number." % port)

        use_reloader = options.get('use_reloader', True)
        open_browser = options.get('open_browser', False)
        admin_media_path = options.get('admin_media_path', '')
        shutdown_message = options.get('shutdown_message', '')
        quit_command = (sys.platform == 'win32') and 'CTRL-BREAK' or 'CONTROL-C'

        def inner_run():
            from django.conf import settings
            print "Validating models..."
            self.validate(display_num_errors=True)
            print "\nDjango version %s, using settings %r" % (django.get_version(), settings.SETTINGS_MODULE)
            print "Development server is running at http://%s:%s/" % (addr, port)
            print "Using the Werkzeug debugger (http://werkzeug.pocoo.org/)"
            print "Quit the server with %s." % quit_command
            path = admin_media_path or django.__path__[0] + '/contrib/admin/media'
            handler = AdminMediaHandler(WSGIHandler(), path)
            if open_browser:
                import webbrowser
                url = "http://%s:%s/" % (addr, port)
                webbrowser.open(url)
            run_simple(addr, int(port), DebuggedApplication(handler, True),
                       use_reloader=use_reloader, use_debugger=True)
        inner_run()
<|endoftext|>


<commit_before>import numpy
from scipy.sparse import coo_matrix
from scipy.ndimage.measurements import label
from scipy.misc import comb as nchoosek

def pixel_wise_boundary_precision_recall(aseg, gt):
    gt = (1-gt.astype(numpy.bool)).astype(numpy.uint8)
    aseg = (1-aseg.astype(numpy.bool)).astype(numpy.uint8)
    tp = float((gt * aseg).sum())
    fp = (aseg * (1-gt)).sum()
    fn = (gt * (1-aseg)).sum()
    return tp/(tp+fp), tp/(tp+fn)

def edit_distance(aseg, gt, ws=None):
    if ws is None:
        return edit_distance_to_bps(aseg, gt)
    import agglo
    return edit_distance_to_bps(aseg, agglo.best_possible_segmentation(ws, gt))

def edit_distance_to_bps(aseg, bps):
    aseg = relabel_from_one(aseg)
    bps = relabel_from_one(bps)
    r = contingency_table(aseg, bps).astype(numpy.bool)
    if (bps==0).any(): r[:,0] = 0
    if (aseg==0).any(): r[0,:] = 0
    false_splits = (r.sum(axis=0)-1)[1:].sum()
    false_merges = (r.sum(axis=1)-1)[1:].sum()
    return (false_merges, false_splits)

def relabel_from_one(a):
    labels = numpy.unique(a)
    labels = labels[labels!=0]
    if labels.max() == len(labels):
        return a
    b = a.copy()
    for i, label in enumerate(labels):
        b[a==label] = i+1
    return b

def contingency_table(seg, gt, ignore_seg=[0], ignore_gt=[0], norm=True):
    """Return the contingency table for all regions in matched segmentations."""
    gtr = gt.ravel()
    segr = seg.ravel()
    ij = numpy.zeros((2,len(gtr)))
    ij[0,:] = segr
    ij[1,:] = gtr
    cont = coo_matrix((numpy.ones((len(gtr))), ij)).toarray()
    cont[:, ignore_gt] = 0
    cont[ignore_seg,:] = 0
    if norm:
        cont /= float(cont.sum())
    return cont

def xlogx(x, out=None):
    """Compute x * log_2(x) with 0 log(0) defined to be 0."""
    nz = x.nonzero()
    if out is None:
        y = x.copy()
    else:
        y = out
    y[nz] *= numpy.log2(y[nz])
    return y

def vi(X, Y, cont=None, weights=numpy.ones(2), ignore_seg=[], ignore_gt=[]):
    """Return the variation of information metric."""
    return numpy.dot(weights, split_vi(X,Y,cont, ignore_seg, ignore_gt))

def vi_by_threshold(ucm, gt, ignore_seg=[], ignore_gt=[], npoints=None):
    ts = numpy.unique(ucm)[1:]
    if npoints is None:
        npoints = len(ts)
    if len(ts) > 2*npoints:
        ts = ts[numpy.arange(1, len(ts), len(ts)/npoints)]
    result = numpy.zeros((2,len(ts)))
    for i, t in enumerate(ts):
        seg = label(ucm<t)[0]
        result[:,i] = split_vi(seg, gt, None, ignore_seg, ignore_gt)
    return ts, result

def rand_by_threshold(ucm, gt, npoints=None):
    ts = numpy.unique(ucm)[1:]
    if npoints is None:
        npoints = len(ts)
    if len(ts) > 2*npoints:
        ts = ts[numpy.arange(1, len(ts), len(ts)/npoints)]
    result = numpy.zeros((2,len(ts)))
    for i, t in enumerate(ts):
        seg = label(ucm<t)[0]
        result[0,i] = rand_index(seg, gt, None)
        result[1,i] = adj_rand_index(seg, gt, None)
    return ts, result

def vi_tables(X, Y, cont=None, ignore_seg=[], ignore_gt=[]):
    """Return probability tables used for calculating VI."""
    if cont is None:
        pxy = contingency_table(X, Y, ignore_seg, ignore_gt)
    else:
        cont[:, ignore_gt] = 0
        cont[ignore_seg,:] = 0
        pxy = cont/float(cont.sum())

    # Calculate probabilities
    px = pxy.sum(axis=1)
    py = pxy.sum(axis=0)
    # Remove zero rows/cols
    nzx = px.nonzero()[0]
    nzy = py.nonzero()[0]
    nzpx = px[nzx]
    nzpy = py[nzy]
    nzpxy = pxy[nzx,:][:,nzy]

    # Calculate log conditional probabilities and entropies
    ax = numpy.newaxis
    lpygx = numpy.zeros(numpy.shape(px))
    lpygx[nzx] = xlogx(nzpxy / nzpx[:,ax]).sum(axis=1)
                        # \sum_x{p_{y|x} \log{p_{y|x}}}
    hygx = -(px*lpygx) # \sum_x{p_x H(Y|X=x)} = H(Y|X)

    lpxgy = numpy.zeros(numpy.shape(py))
    lpxgy[nzy] = xlogx(nzpxy / nzpy[ax,:]).sum(axis=0)
    hxgy = -(py*lpxgy)

    return pxy, px, py, hxgy, hygx, lpygx, lpxgy

def split_vi(X,Y,cont=None, ignore_seg_labels=[], ignore_gt_labels=[]):
    """Return the symmetric conditional entropies associated with the VI.

    The variation of information is defined as VI(X,Y) = H(X|Y) + H(Y|X).
    If Y is the ground-truth segmentation, then H(Y|X) can be interpreted
    as the amount of under-segmentation of Y and H(X|Y) is then the amount
    of over-segmentation.  In other words, a perfect over-segmentation
    will have H(Y|X)=0 and a perfect under-segmentation will have H(X|Y)=0.
    """
    pxy,px,py,hxgy,hygx,lpygx,lpxgy = vi_tables(X,Y,cont,ignore_seg_labels,
                                                         ignore_gt_labels)
    # false merges, false splits
    return numpy.array([hygx.sum(), hxgy.sum()])

def split_components(idx, contingency, num_elems=4, axis=0):
    """Return the indices of the bodies most overlapping with body idx.

    Arguments:
        - idx: the body id being examined.
        - contingency: the normalized contingency table.
        - num_elems: the number of overlapping bodies desired.
        - axis: the axis along which to perform the calculations.
    Value:
        A list of tuples of (body_idx, overlap_int, overlap_ext).
    """
    if axis == 1:
        contingency = contingency.T
    cc = contingency / contingency.sum(axis=1)[:,numpy.newaxis]
    cct = contingency / contingency.sum(axis=0)[numpy.newaxis,:]
    idxs = (-cc[idx]).argsort()[:num_elems]
    probs = cc[idx][idxs]
    probst = cct[idx][idxs]
    return zip(idxs, probs, probst)

def rand_values(cont_table):
    """Calculate values for rand indices."""
    n = cont_table.sum()
    sum1 = (cont_table*cont_table).sum()
    sum2 = (cont_table.sum(axis=1)**2).sum()
    sum3 = (cont_table.sum(axis=0)**2).sum()
    a = (sum1 - n)/2.0;
    b = (sum2 - sum1)/2
    c = (sum3 - sum1)/2
    d = (sum1 + n**2 - sum2 - sum3)/2
    return a, b, c, d

def rand_index(seg, gt, cont=None):
    """Return the unadjusted Rand index."""
    if cont is None:
        cont = contingency_table(seg, gt, norm=False)
    a, b, c, d = rand_values(cont)
    return (a+d)/(a+b+c+d)

def adj_rand_index(seg, gt, cont=None):
    """Return the adjusted Rand index."""
    if cont is None:
        cont = contingency_table(seg, gt, norm=False)
    a, b, c, d = rand_values(cont)
    nk = a+b+c+d
    return (nk*(a+d) - ((a+b)*(a+c) + (c+d)*(b+d)))/(
        nk**2 - ((a+b)*(a+c) + (c+d)*(b+d)))

def fm_index(seg, gt, cont=None):
    """ Return the Fowlkes-Mallows index. """
    if cont is None:
        cont = contingency_table(seg, gt)
    a, b, c, d = rand_values(cont)
    return a/(numpy.sqrt((a+b)*(a+c)))

<commit_msg>Add multiprocessing support to evaluate.<commit_after>import numpy
import multiprocessing
from scipy.sparse import coo_matrix
from scipy.ndimage.measurements import label
from scipy.misc import comb as nchoosek

def pixel_wise_boundary_precision_recall(aseg, gt):
    gt = (1-gt.astype(numpy.bool)).astype(numpy.uint8)
    aseg = (1-aseg.astype(numpy.bool)).astype(numpy.uint8)
    tp = float((gt * aseg).sum())
    fp = (aseg * (1-gt)).sum()
    fn = (gt * (1-aseg)).sum()
    return tp/(tp+fp), tp/(tp+fn)

def edit_distance(aseg, gt, ws=None):
    if ws is None:
        return edit_distance_to_bps(aseg, gt)
    import agglo
    return edit_distance_to_bps(aseg, agglo.best_possible_segmentation(ws, gt))

def edit_distance_to_bps(aseg, bps):
    aseg = relabel_from_one(aseg)
    bps = relabel_from_one(bps)
    r = contingency_table(aseg, bps).astype(numpy.bool)
    if (bps==0).any(): r[:,0] = 0
    if (aseg==0).any(): r[0,:] = 0
    false_splits = (r.sum(axis=0)-1)[1:].sum()
    false_merges = (r.sum(axis=1)-1)[1:].sum()
    return (false_merges, false_splits)

def relabel_from_one(a):
    labels = numpy.unique(a)
    labels = labels[labels!=0]
    if labels.max() == len(labels):
        return a
    b = a.copy()
    for i, label in enumerate(labels):
        b[a==label] = i+1
    return b

def contingency_table(seg, gt, ignore_seg=[0], ignore_gt=[0], norm=True):
    """Return the contingency table for all regions in matched segmentations."""
    gtr = gt.ravel()
    segr = seg.ravel()
    ij = numpy.zeros((2,len(gtr)))
    ij[0,:] = segr
    ij[1,:] = gtr
    cont = coo_matrix((numpy.ones((len(gtr))), ij)).toarray()
    cont[:, ignore_gt] = 0
    cont[ignore_seg,:] = 0
    if norm:
        cont /= float(cont.sum())
    return cont

def xlogx(x, out=None):
    """Compute x * log_2(x) with 0 log(0) defined to be 0."""
    nz = x.nonzero()
    if out is None:
        y = x.copy()
    else:
        y = out
    y[nz] *= numpy.log2(y[nz])
    return y

def vi(X, Y, cont=None, weights=numpy.ones(2), ignore_seg=[], ignore_gt=[]):
    """Return the variation of information metric."""
    return numpy.dot(weights, split_vi(X,Y,cont, ignore_seg, ignore_gt))

def split_vi_threshold(tup):
    """Compute VI with tuple input (to support multiprocessing).
    Tuple elements:
        - the UCM for the candidate segmentation,
        - the gold standard,
        - list of ignored labels in the segmentation,
        - list of ignored labels in the gold standard,
        - threshold to use for the UCM.
    Value:
        - array of length 2 containing the undersegmentation and
        oversegmentation parts of the VI.
    """
    ucm, gt, ignore_seg, ignore_gt, t = tup
    return split_vi(label(ucm<t)[0], gt, None, ignore_seg, ignore_gt)

def vi_by_threshold(ucm, gt, ignore_seg=[], ignore_gt=[], npoints=None):
    ts = numpy.unique(ucm)[1:]
    if npoints is None:
        npoints = len(ts)
    if len(ts) > 2*npoints:
        ts = ts[numpy.arange(1, len(ts), len(ts)/npoints)]
    p = multiprocessing.Pool()
    result = p.map(split_vi_threshold,
        [(ucm, gt, ignore_seg, ignore_gt, t) for t in ts])
    return numpy.concatenate(
                            (ts[numpy.newaxis, :], numpy.array(result).T),
                            axis=0)

def rand_by_threshold(ucm, gt, npoints=None):
    ts = numpy.unique(ucm)[1:]
    if npoints is None:
        npoints = len(ts)
    if len(ts) > 2*npoints:
        ts = ts[numpy.arange(1, len(ts), len(ts)/npoints)]
    result = numpy.zeros((2,len(ts)))
    for i, t in enumerate(ts):
        seg = label(ucm<t)[0]
        result[0,i] = rand_index(seg, gt, None)
        result[1,i] = adj_rand_index(seg, gt, None)
    return ts, result

def vi_tables(X, Y, cont=None, ignore_seg=[], ignore_gt=[]):
    """Return probability tables used for calculating VI."""
    if cont is None:
        pxy = contingency_table(X, Y, ignore_seg, ignore_gt)
    else:
        cont[:, ignore_gt] = 0
        cont[ignore_seg,:] = 0
        pxy = cont/float(cont.sum())

    # Calculate probabilities
    px = pxy.sum(axis=1)
    py = pxy.sum(axis=0)
    # Remove zero rows/cols
    nzx = px.nonzero()[0]
    nzy = py.nonzero()[0]
    nzpx = px[nzx]
    nzpy = py[nzy]
    nzpxy = pxy[nzx,:][:,nzy]

    # Calculate log conditional probabilities and entropies
    ax = numpy.newaxis
    lpygx = numpy.zeros(numpy.shape(px))
    lpygx[nzx] = xlogx(nzpxy / nzpx[:,ax]).sum(axis=1)
                        # \sum_x{p_{y|x} \log{p_{y|x}}}
    hygx = -(px*lpygx) # \sum_x{p_x H(Y|X=x)} = H(Y|X)

    lpxgy = numpy.zeros(numpy.shape(py))
    lpxgy[nzy] = xlogx(nzpxy / nzpy[ax,:]).sum(axis=0)
    hxgy = -(py*lpxgy)

    return pxy, px, py, hxgy, hygx, lpygx, lpxgy

def split_vi(X,Y,cont=None, ignore_seg_labels=[], ignore_gt_labels=[]):
    """Return the symmetric conditional entropies associated with the VI.

    The variation of information is defined as VI(X,Y) = H(X|Y) + H(Y|X).
    If Y is the ground-truth segmentation, then H(Y|X) can be interpreted
    as the amount of under-segmentation of Y and H(X|Y) is then the amount
    of over-segmentation.  In other words, a perfect over-segmentation
    will have H(Y|X)=0 and a perfect under-segmentation will have H(X|Y)=0.
    """
    pxy,px,py,hxgy,hygx,lpygx,lpxgy = vi_tables(X,Y,cont,ignore_seg_labels,
                                                         ignore_gt_labels)
    # false merges, false splits
    return numpy.array([hygx.sum(), hxgy.sum()])

def split_components(idx, contingency, num_elems=4, axis=0):
    """Return the indices of the bodies most overlapping with body idx.

    Arguments:
        - idx: the body id being examined.
        - contingency: the normalized contingency table.
        - num_elems: the number of overlapping bodies desired.
        - axis: the axis along which to perform the calculations.
    Value:
        A list of tuples of (body_idx, overlap_int, overlap_ext).
    """
    if axis == 1:
        contingency = contingency.T
    cc = contingency / contingency.sum(axis=1)[:,numpy.newaxis]
    cct = contingency / contingency.sum(axis=0)[numpy.newaxis,:]
    idxs = (-cc[idx]).argsort()[:num_elems]
    probs = cc[idx][idxs]
    probst = cct[idx][idxs]
    return zip(idxs, probs, probst)

def rand_values(cont_table):
    """Calculate values for rand indices."""
    n = cont_table.sum()
    sum1 = (cont_table*cont_table).sum()
    sum2 = (cont_table.sum(axis=1)**2).sum()
    sum3 = (cont_table.sum(axis=0)**2).sum()
    a = (sum1 - n)/2.0;
    b = (sum2 - sum1)/2
    c = (sum3 - sum1)/2
    d = (sum1 + n**2 - sum2 - sum3)/2
    return a, b, c, d

def rand_index(seg, gt, cont=None):
    """Return the unadjusted Rand index."""
    if cont is None:
        cont = contingency_table(seg, gt, norm=False)
    a, b, c, d = rand_values(cont)
    return (a+d)/(a+b+c+d)

def adj_rand_index(seg, gt, cont=None):
    """Return the adjusted Rand index."""
    if cont is None:
        cont = contingency_table(seg, gt, norm=False)
    a, b, c, d = rand_values(cont)
    nk = a+b+c+d
    return (nk*(a+d) - ((a+b)*(a+c) + (c+d)*(b+d)))/(
        nk**2 - ((a+b)*(a+c) + (c+d)*(b+d)))

def fm_index(seg, gt, cont=None):
    """ Return the Fowlkes-Mallows index. """
    if cont is None:
        cont = contingency_table(seg, gt)
    a, b, c, d = rand_values(cont)
    return a/(numpy.sqrt((a+b)*(a+c)))

<|endoftext|>


<commit_before>#!/usr/bin/env python
from app import app
app.run(debug = False)
<commit_msg>fix production runp.py script<commit_after>#!/usr/bin/env python
from app import app
app.run(host= '0.0.0.0', debug = False)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
    sale.py

    :copyright: (c) 2014 by Openlabs Technologies & Consulting (P) Limited
    :license: BSD, see LICENSE for more details.
"""
from decimal import Decimal

from trytond.model import fields, ModelView
from trytond.pool import PoolMeta, Pool
from trytond.pyson import Eval

__all__ = ['SaleLine', 'Sale']
__metaclass__ = PoolMeta

class SaleLine:
    "SaleLine"
    __name__ = 'sale.line'

    gift_card = fields.One2One(
        'gift_card.gift_card-sale.line', "sale_line", "gift_card", "Gift Card"
    )
    message = fields.Text(
        "Message", states={'invisible': Eval('type') != 'gift_card'}
    )

    @classmethod
    def __setup__(cls):
        super(SaleLine, cls).__setup__()

        if ('gift_card', 'Gift Card') not in cls.type.selection:
            cls.type.selection.append(('gift_card', 'Gift Card'))

        cls.amount.states['invisible'] = \
            cls.amount.states['invisible'] & ~(Eval('type') == 'gift_card')

        cls.unit_price.states['invisible'] = \
            cls.unit_price.states['invisible'] & ~(Eval('type') == 'gift_card')

        cls.quantity.states['invisible'] = \
            cls.quantity.states['invisible'] & ~(Eval('type') == 'gift_card')

    def get_amount(self, name):
        """
        Calculate amount for gift card line
        """
        rv = super(SaleLine, self).get_amount(name)
        if self.type == 'gift_card':
            return self.sale.currency.round(
                Decimal(str(self.quantity)) * self.unit_price)
        return rv

    def get_invoice_line(self, invoice_type):
        """
        Pick up liability account from gift card configuration for invoices
        """
        GiftCardConfiguration = Pool().get('gift_card.configuration')

        rv = super(SaleLine, self).get_invoice_line(invoice_type)
        invoice_lines = []
        for invoice_line in rv:
            if invoice_line.type == 'gift_card':
                liability_account = GiftCardConfiguration(1).liability_account
                if not liability_account:
                    self.raise_user_error(
                        "Liability Account is missing from Gift Card "
                        "Configuration"
                    )
                invoice_line.account = liability_account
                invoice_line.unit_price = self.unit_price
                invoice_line.quantity = self.quantity
            invoice_lines.append(invoice_line)
        return invoice_lines

    @fields.depends(
        'type', 'quantity', 'unit_price', 'unit',
        '_parent_sale.currency'
    )
    def on_change_with_amount(self):
        if self.type == 'gift_card':
            currency = self.sale.currency if self.sale else None
            amount = Decimal(str(self.quantity or '0.0')) * \
                (self.unit_price or Decimal('0.0'))
            if currency:
                return currency.round(amount)
            return amount
        return Decimal('0.0')

class Sale:
    "Sale"
    __name__ = 'sale.sale'

    @classmethod
    @ModelView.button
    def process(cls, sales):
        """
        Create gift card on processing sale
        """
        GiftCard = Pool().get('gift_card.gift_card')

        rv = super(Sale, cls).process(sales)

        for sale in sales:
            for line in sale.lines:
                if line.type == 'gift_card':

                    # Create gift card for sale line
                    gift_card, = GiftCard.create([{
                        'amount': line.amount,
                        'sale_line': line.id,
                        'message': line.message
                    }])

                    GiftCard.activate([gift_card])

        return rv

    @classmethod
    def get_amount(cls, sales, names):
        """
        Add amount of gift card line to total amount of sale
        """
        rv = super(Sale, cls).get_amount(sales, names)
        for sale in sales:
            for line in filter(lambda l: l.type == 'gift_card', sale.lines):
                if 'total_amount' in rv:
                    rv['total_amount'][sale.id] += line.amount
                if 'untaxed_amount' in rv:
                    rv['untaxed_amount'][sale.id] += line.amount

        return rv
<commit_msg>Fix on change to call super<commit_after># -*- coding: utf-8 -*-
"""
    sale.py

    :copyright: (c) 2014 by Openlabs Technologies & Consulting (P) Limited
    :license: BSD, see LICENSE for more details.
"""
from decimal import Decimal

from trytond.model import fields, ModelView
from trytond.pool import PoolMeta, Pool
from trytond.pyson import Eval

__all__ = ['SaleLine', 'Sale']
__metaclass__ = PoolMeta

class SaleLine:
    "SaleLine"
    __name__ = 'sale.line'

    gift_card = fields.One2One(
        'gift_card.gift_card-sale.line', "sale_line", "gift_card", "Gift Card"
    )
    message = fields.Text(
        "Message", states={'invisible': Eval('type') != 'gift_card'}
    )

    @classmethod
    def __setup__(cls):
        super(SaleLine, cls).__setup__()

        if ('gift_card', 'Gift Card') not in cls.type.selection:
            cls.type.selection.append(('gift_card', 'Gift Card'))

        cls.amount.states['invisible'] = \
            cls.amount.states['invisible'] & ~(Eval('type') == 'gift_card')

        cls.unit_price.states['invisible'] = \
            cls.unit_price.states['invisible'] & ~(Eval('type') == 'gift_card')

        cls.quantity.states['invisible'] = \
            cls.quantity.states['invisible'] & ~(Eval('type') == 'gift_card')

    def get_amount(self, name):
        """
        Calculate amount for gift card line
        """
        rv = super(SaleLine, self).get_amount(name)
        if self.type == 'gift_card':
            return self.sale.currency.round(
                Decimal(str(self.quantity)) * self.unit_price)
        return rv

    def get_invoice_line(self, invoice_type):
        """
        Pick up liability account from gift card configuration for invoices
        """
        GiftCardConfiguration = Pool().get('gift_card.configuration')

        rv = super(SaleLine, self).get_invoice_line(invoice_type)
        invoice_lines = []
        for invoice_line in rv:
            if invoice_line.type == 'gift_card':
                liability_account = GiftCardConfiguration(1).liability_account
                if not liability_account:
                    self.raise_user_error(
                        "Liability Account is missing from Gift Card "
                        "Configuration"
                    )
                invoice_line.account = liability_account
                invoice_line.unit_price = self.unit_price
                invoice_line.quantity = self.quantity
            invoice_lines.append(invoice_line)
        return invoice_lines

    @fields.depends(
        'type', 'quantity', 'unit_price', 'unit',
        '_parent_sale.currency'
    )
    def on_change_with_amount(self):
        if self.type == 'gift_card':
            currency = self.sale.currency if self.sale else None
            amount = Decimal(str(self.quantity or '0.0')) * \
                (self.unit_price or Decimal('0.0'))
            if currency:
                return currency.round(amount)
            return amount
        return super(SaleLine, self).on_change_with_amount()

class Sale:
    "Sale"
    __name__ = 'sale.sale'

    @classmethod
    @ModelView.button
    def process(cls, sales):
        """
        Create gift card on processing sale
        """
        GiftCard = Pool().get('gift_card.gift_card')

        rv = super(Sale, cls).process(sales)

        for sale in sales:
            for line in sale.lines:
                if line.type == 'gift_card':

                    # Create gift card for sale line
                    gift_card, = GiftCard.create([{
                        'amount': line.amount,
                        'sale_line': line.id,
                        'message': line.message
                    }])

                    GiftCard.activate([gift_card])

        return rv

    @classmethod
    def get_amount(cls, sales, names):
        """
        Add amount of gift card line to total amount of sale
        """
        rv = super(Sale, cls).get_amount(sales, names)
        for sale in sales:
            for line in filter(lambda l: l.type == 'gift_card', sale.lines):
                if 'total_amount' in rv:
                    rv['total_amount'][sale.id] += line.amount
                if 'untaxed_amount' in rv:
                    rv['untaxed_amount'][sale.id] += line.amount

        return rv
<|endoftext|>


<commit_before># THIS IS A XChat/HexChat PLUGIN #
# MAKE SURE TO NEVER LOAD MORE THAN ONE COPY #
##########################################
__module_author__ = 'Aww'
__module_name__ = 'Seen Database'
__module_version__ = '1.0.1'
__module_description__ = 'Seen Database made with sqlite3 and Python'
##########################################
import sqlite3, xchat, datetime, os
class Seen:
    def __init__(self):
        # Auto Delete after database size gets bigger than <some size>
        # self.max_size = (1024 * 1024) * 1024
        if os.name != "posix":
            self.dbconnection = sqlite3.connect(xchat.get_info("xchatdir") + "\\seen.db")
        else:
            self.dbconnection = sqlite3.connect(xchat.get_info("xchatdir") + "/seen.db")
        self.curs = self.dbconnection.cursor()
        self.curs.execute("CREATE TABLE IF NOT EXISTS seen (nick TEXT UNIQUE, msg TEXT)")

    def commit(self, word = None, word_eol = None, userdata = None):
        self.dbconnection.commit()

    def on_unload(self, userdata = None):
        self.dbconnection.commit()
        self.dbconnection.close()

    def parse(self, word, word_eol, userdata = None):
        tempdata = word_eol[0].replace('!', ' ', 1).split()
        data = {
            "Nick": tempdata[0].lstrip(':'),
            "Host": tempdata[1],
            "Type": tempdata[2],
            "Channel": tempdata[3],
            "Message": ' '.join(tempdata[4:]).replace(':', '', 1)
        }
        self.update(data)

    def update(self, data):
        now = datetime.datetime.now().strftime("%B %d, %Y at %I:%M %p %Z")
        msg = "%s was last seen on channel %s on %stheir last message was: %s" % (
            data["Nick"], data["Channel"], now, data["Message"].replace('"', "'"))
        try:
            self.curs.execute('REPLACE INTO seen (nick, msg) VALUES ("%s", "%s")' % (data["Nick"], msg))
        except sqlite3.OperationalError:
            print "ERROR(seen.py - sqlite3.OperationalError): Someone said something funny :-/"

    def lastseen(self, word, word_eol, userdata = None):
        found = False
        colors = ['12', '13']
        color = 0
        if word[1] == '-w':
            if len(word) > 2:
                for nick in self.curs.execute("SELECT * FROM seen WHERE nick LIKE '%s'" % word[2]):
                    xchat.prnt(u'\x03' + colors[color] + nick[1])
                    found = True
                    color = not color # if 1 -> 0 if 0 -> 1
                if not found:
                    print "%s was not found in the database." % word[2]
            else:
                xchat.prnt("/seen <nick>")
                xchat.prnt("Example: /seen Aww")
        else:
            if len(word) > 1:
                for nick in self.curs.execute("SELECT * FROM seen WHERE nick='%s'" % word[1]):
                    xchat.prnt(nick[1])
                    found = True
                if not found:
                    print "%s was not found in the database." % word[1]
            else:
                xchat.prnt("/seen <nick>")
                xchat.prnt("Example: /seen Aww")

    def info(self, word = None, word_eol = None, userdata = None):
        for response in self.curs.execute("SELECT Count(*) FROM seen"):
            num_of_entrys = response[0]
            break
        if os.name != "posix":
            db_size = os.path.getsize(xchat.get_info("xchatdir") + "\\seen.db")
            db_file = xchat.get_info("xchatdir") + "\\seen.db"
            if os.path.exists(xchat.get_info("xchatdir") + "/seen.db-journal"):
                temp_db_size = os.path.getsize(xchat.get_info("xchatdir") + "\\seen.db-journal")
            else:
                temp_db_size = 0
            temp_db_file = xchat.get_info("xchatdir") + "\\seen.db-journal"
        else:
            db_size = os.path.getsize(xchat.get_info("xchatdir") + "/seen.db")
            if os.path.exists(xchat.get_info("xchatdir") + "/seen.db-journal"):
                temp_db_size = os.path.getsize(xchat.get_info("xchatdir") + "/seen.db-journal")
            else:
                temp_db_size = 0
            db_file = xchat.get_info("xchatdir") + "/seen.db"
            temp_db_file = xchat.get_info("xchatdir") + "/seen.db-journal"
        xchat.prnt(
            "13Seen database info: \n13Size: %.2fKB \n13Temp Size: %.2fKB "
            "\n13Entries: %d \n13File: %s\n13Temp File: %s" % (
            float(db_size)/1024.0, float(temp_db_size/1024.0), int(num_of_entrys), db_file, temp_db_file))

seen = Seen()
xchat.hook_unload(seen.on_unload)
xchat.hook_server("PRIVMSG", seen.parse)
xchat.hook_command("seen", seen.lastseen)
xchat.hook_command("seen->info", seen.info)
xchat.hook_command("seen->commit", seen.commit)
xchat.prnt("%s version %s by %s has been loaded." % (__module_name__, __module_version__, __module_author__))
seen.info();
# xchat.prnt("04Note: NEVER LOAD THIS MORE THEN ONCE! IF YOU NEED TO RELOAD IT MAKE SURE TO UNLOAD IT FIRST!!")
<commit_msg>Code cleanup<commit_after># THIS IS A XChat/HexChat PLUGIN #
# MAKE SURE TO NEVER LOAD MORE THAN ONE COPY #
##########################################
__module_author__ = 'Aww'
__module_name__ = 'Seen Database'
__module_version__ = '1.0.1'
__module_description__ = 'Seen Database made with sqlite3 and Python'
##########################################
import sqlite3, xchat, datetime, os
class Seen:
    def __init__(self):
        # Auto Delete after database size gets bigger than <some size>
        # self.max_size = (1024 * 1024) * 1024
        if os.name != "posix":
            self.dbconnection = sqlite3.connect(xchat.get_info("xchatdir") + "\\seen.db")
        else:
            self.dbconnection = sqlite3.connect(xchat.get_info("xchatdir") + "/seen.db")
        self.curs = self.dbconnection.cursor()
        self.curs.execute("CREATE TABLE IF NOT EXISTS seen (nick TEXT UNIQUE, msg TEXT)")

    def commit(self, word = None, word_eol = None, userdata = None):
        self.dbconnection.commit()

    def on_unload(self, userdata = None):
        self.dbconnection.commit()
        self.dbconnection.close()

    def parse(self, word, word_eol, userdata = None):
        tempdata = word_eol[0].replace('!', ' ', 1).split()
        data = {
            "Nick": tempdata[0].lstrip(':'),
            "Host": tempdata[1],
            "Type": tempdata[2],
            "Channel": tempdata[3],
            "Message": ' '.join(tempdata[4:]).replace(':', '', 1)
        }
        self.update(data)

    def update(self, data):
        now = datetime.datetime.now().strftime("%B %d, %Y at %I:%M %p %Z")
        msg = "%s was last seen on channel %s on %stheir last message was: %s" % (
            data["Nick"], data["Channel"], now, data["Message"].replace('"', "'"))
        try:
            self.curs.execute('REPLACE INTO seen (nick, msg) VALUES ("%s", "%s")' % (data["Nick"], msg))
        except sqlite3.OperationalError:
            print "ERROR(seen.py - sqlite3.OperationalError): Someone said something funny :-/"

    def lastseen(self, word, word_eol, userdata = None):
        found = False; colors = ['12', '13']; color = 0
        if word[1] == '-w':
            if len(word) > 2:
                for nick in self.curs.execute("SELECT * FROM seen WHERE nick LIKE '%s'" % word[2]):
                    try:
                        xchat.prnt('\x03' + colors[color] + nick[1])
                        found = True
                    except:
                        found = False
                    color = not color # if 1 -> 0 if 0 -> 1
                if not found:
                    print "%s was not found in the database." % word[2]
            else:
                xchat.prnt("/seen <nick>")
                xchat.prnt("Example: /seen Aww")
        else:
            if len(word) > 1:
                for nick in self.curs.execute("SELECT * FROM seen WHERE nick='%s'" % word[1]):
                    xchat.prnt(nick[1])
                    found = True
                if not found:
                    print "%s was not found in the database." % word[1]
            else:
                xchat.prnt("/seen <nick>")
                xchat.prnt("Example: /seen Aww")

    def info(self, word = None, word_eol = None, userdata = None):
        for response in self.curs.execute("SELECT Count(*) FROM seen"):
            num_of_entrys = response[0]
            break
        if os.name != "posix":
            db_size = os.path.getsize(xchat.get_info("xchatdir") + "\\seen.db")
            db_file = xchat.get_info("xchatdir") + "\\seen.db"
            if os.path.exists(xchat.get_info("xchatdir") + "/seen.db-journal"):
                temp_db_size = os.path.getsize(xchat.get_info("xchatdir") + "\\seen.db-journal")
            else:
                temp_db_size = 0
            temp_db_file = xchat.get_info("xchatdir") + "\\seen.db-journal"
        else:
            db_size = os.path.getsize(xchat.get_info("xchatdir") + "/seen.db")
            if os.path.exists(xchat.get_info("xchatdir") + "/seen.db-journal"):
                temp_db_size = os.path.getsize(xchat.get_info("xchatdir") + "/seen.db-journal")
            else:
                temp_db_size = 0
            db_file = xchat.get_info("xchatdir") + "/seen.db"
            temp_db_file = xchat.get_info("xchatdir") + "/seen.db-journal"
        xchat.prnt(
            "\x02\x0313Seen database info\x02:\n"
            "\x0313\x02Size\x02: %.2fKB\n"      #1
            "\x0313\x02Temp Size\x02: %.2fKB\n" #2
            "\x0313\x02Entries\x02: %d\n"       #3
            "\x0313\x02File\x02: %s\n"          #4
            "\x0313\x02Temp File\x02: %s\n"     #5
            "\x0313\x02Version\x02: %s\n"       #6
            %(
            float(db_size)/1024.0,              #1
            float(temp_db_size/1024.0),         #2
            int(num_of_entrys),                 #3
            db_file,                            #4
            temp_db_file,                       #5
            __module_version__                  #6
            ))

seen = Seen()
xchat.hook_unload(seen.on_unload)
xchat.hook_server("PRIVMSG", seen.parse)
xchat.hook_command("seen", seen.lastseen)
xchat.hook_command("seen->info", seen.info)
xchat.hook_command("seen->commit", seen.commit)
xchat.prnt("%s version %s by %s has been loaded." % (__module_name__, __module_version__, __module_author__))
seen.info();
# xchat.prnt("\x02\x0304Note: NEVER LOAD THIS MORE THEN ONCE! IF YOU NEED TO RELOAD IT MAKE SURE TO UNLOAD IT FIRST!!\x02\x03")
<|endoftext|>


<commit_before>from string import ascii_letters
from random import choice

from rdflib.Identifier import Identifier
from rdflib.Literal import Literal

# Create a (hopefully) unique prefix so that BNode values do not
# collide with ones created with a different instance of this module.
prefix = ""
for i in xrange(0,8):
    prefix += choice(ascii_letters)

node_id = 0
class BNode(Identifier):
    __slots__ = ()
    def __new__(cls, value=None):
        if value==None:
            global node_id
            node_id += 1
            value = "_%s%s" % (prefix, node_id)
        else:
            if not value.startswith("_"):
                value = "".join(("_", value))
        return Identifier.__new__(cls, value)

    def n3(self):
        if not self.startswith("_:"):
	    if self.startswith("_"):
		return "_:%s" % self[1:]
	    else:
		return "_:%s"
        return str(self)

<commit_msg>added TODO note<commit_after>from string import ascii_letters
from random import choice

from rdflib.Identifier import Identifier
from rdflib.Literal import Literal

# Create a (hopefully) unique prefix so that BNode values do not
# collide with ones created with a different instance of this module.
prefix = ""
for i in xrange(0,8):
    prefix += choice(ascii_letters)

# TODO: replace with generator
node_id = 0
class BNode(Identifier):
    __slots__ = ()
    def __new__(cls, value=None):
        if value==None:
            global node_id
            node_id += 1
            value = "_%s%s" % (prefix, node_id)
        else:
            if not value.startswith("_"):
                value = "".join(("_", value))
        return Identifier.__new__(cls, value)

    def n3(self):
        if not self.startswith("_:"):
	    if self.startswith("_"):
		return "_:%s" % self[1:]
	    else:
		return "_:%s"
        return str(self)

<|endoftext|>