<commit_before># Copyright 2015 Google Inc. All rights reserved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import collections
import datetime
import json

import apiclient.discovery
import apiclient.http
import gdata.gauth
import gdata.spreadsheets.client
import gdata.spreadsheets.data
import httplib2
import oauth2client.client

from . import util

GOOGLE_SPREADSHEET_SCOPES = (
    'https://spreadsheets.google.com/feeds',
    'https://www.googleapis.com/auth/drive',
)

SPREADSHEET_URL = (
    'https://spreadsheets.google.com/feeds/spreadsheets/private/full/%s')

class Collection(util.LazyOrderedDictionary):
  def __init__(self, client, drive):
    super(Collection, self).__init__(
        self._spreadsheet_enumerator,
        self._spreadsheet_constructor)
    self.client = client
    self.drive = drive

  @classmethod
  def login(cls, json_path=None, json_text=None):
    if json_text is None:
      with open(json_path, 'rb') as f:
        json_text = f.read()
    json_data = json.loads(json_text)
    if '_module' in json_data:
      credentials = oauth2client.client.Credentials.new_from_json(json_text)
    elif 'private_key' in json_data:
      credentials = oauth2client.client.SignedJwtAssertionCredentials(
          service_account_name=json_data['client_email'],
          private_key=json_data['private_key'],
          scope=GOOGLE_SPREADSHEET_SCOPES)
    else:
      raise ValueError('unrecognized credential format')
    # Don't use auth_token= argument. It does not refresh tokens.
    client = gdata.spreadsheets.client.SpreadsheetsClient()
    auth_http = httplib2.Http()
    auth_token = gdata.gauth.OAuth2TokenFromCredentials(credentials)
    auth_token.authorize(client)
    auth_http = credentials.authorize(auth_http)
    drive = apiclient.discovery.build('drive', 'v2', http=auth_http)
    return cls(client, drive)

  def create_spreadsheet(self, title, rows=1000, cols=26):
    body = {
        'title': title,
        'mimeType': 'application/vnd.google-apps.spreadsheet',
    }
    response = self.drive.files().insert(body=body).execute()
    key = response['id']
    self.refresh()
    spreadsheet = self[key]
    if (rows, cols) != (1000, 26):
      spreadsheet[0].set_size(rows, cols)
    return spreadsheet

  def refresh(self):
    super(Collection, self).refresh()

  def _spreadsheet_enumerator(self):
    feed = self.client.get_spreadsheets()
    for entry in feed.entry:
      key = entry.get_spreadsheet_key()
      yield (key, Spreadsheet(self, self.client, self.drive, key, entry))

  def _spreadsheet_constructor(self, key):
    # TODO: Upstream to gdata.
    entry = self.client.get_feed(
        SPREADSHEET_URL % key,
        desired_class=gdata.spreadsheets.data.Spreadsheet)
    key = entry.get_spreadsheet_key()
    return Spreadsheet(self, self.client, self.drive, key, entry)

class Spreadsheet(util.LazyOrderedDictionary):
  def __init__(self, collection, client, drive, key, entry):
    super(Spreadsheet, self).__init__(self._worksheet_enumerator, None)
    self.collection = collection
    self.client = client
    self.drive = drive
    self.key = key
    self._entry = entry

  def refresh(self):
    super(Spreadsheet, self).refresh()
    # TODO: Upstream to gdata.
    self._entry = self.client.get_feed(
        SPREADSHEET_URL % self.key,
        desired_class=gdata.spreadsheets.data.Spreadsheet)

  def add_worksheet(self, title, rows=1000, cols=26):
    self.client.add_worksheet(self.key, title, rows=rows, cols=cols)
    self.refresh()
    return self[title]

  def delete_worksheet(self, title):
    worksheet = self[title]
    url = gdata.spreadsheets.client.WORKSHEET_URL % (self.key, worksheet.key)
    self.client.delete(url, force=True)
    self.refresh()

  @property
  def url(self):
    return 'https://docs.google.com/spreadsheets/d/%s/edit' % self.key

  @property
  def title(self):
    return self._entry.title.text

  @title.setter
  def title(self, new_title):
    body = {'title': new_title}
    response = self.drive.files().update(fileId=self.key, body=body).execute()
    self.refresh()

  @property
  def updated(self):
    return datetime.datetime.strptime(
        self._entry.updated.text, '%Y-%m-%dT%H:%M:%S.%fZ')

  def _worksheet_enumerator(self):
    feed = self.client.get_worksheets(self.key)
    for entry in feed.entry:
      key = entry.get_worksheet_id()
      worksheet = Worksheet(self, self.client, key, entry)
      yield (worksheet.title, worksheet)

class WorksheetView(object):
  def __init__(self, worksheet, client, start_row, end_row, start_col, end_col):
    self.worksheet = worksheet
    self.client = client
    self._reset_size(start_row, end_row, start_col, end_col)
    self._input_value_map = {}
    self._cells_fetched = False
    self._queued_updates = []
    self.refresh()

  def refresh(self):
    self._input_value_map.clear()
    self._cells_fetched = False
    del self._queued_updates[:]

  def _reset_size(self, start_row, end_row, start_col, end_col):
    self.start_row = start_row
    self.end_row = end_row
    self.start_col = start_col
    self.end_col = end_col
    self._view_rows = [
        WorksheetViewRow(self, row, start_col, end_col)
        for row in xrange(start_row, end_row)]

  def _ensure_cells_fetched(self):
    if self._cells_fetched:
      return
    query = gdata.spreadsheets.client.CellQuery(
        min_row=(self.start_row + 1),
        max_row=self.end_row,
        min_col=(self.start_col + 1),
        max_col=self.end_col,
        return_empty=False)
    feed = self.client.get_cells(
        self.worksheet.spreadsheet.key, self.worksheet.key, query=query)
    self._input_value_map = {}
    for entry in feed.entry:
      cell = entry.cell
      self._input_value_map.setdefault(
          (int(cell.row) - 1, int(cell.col) - 1),
          cell.input_value)
    self._cells_fetched = True

  def commit(self):
    if not self._queued_updates:
      return
    feed = gdata.spreadsheets.data.build_batch_cells_update(
        self.worksheet.spreadsheet.key, self.worksheet.key)
    for row, col, new_value in self._queued_updates:
      feed.add_set_cell(row + 1, col + 1, new_value)
    self.client.batch(feed, force=True)
    del self._queued_updates[:]

  def __getitem__(self, index):
    return self._view_rows[index]

  def __len__(self):
    return self.rows

  def __iter__(self):
    for row in self._view_rows:
      yield row

  def __repr__(self):
    return '<%s %r>' % (self.__class__.__name__, self._view_rows,)

  def __enter__(self):
    return self

  def __exit__(self, exc_type, exc_value, traceback):
    self.commit()

  @property
  def rows(self):
    return self.end_row - self.start_row

  @property
  def cols(self):
    return self.end_col - self.start_col

class WorksheetViewRow(util.CustomMutableFixedList):
  def __init__(self, view, row, start_col, end_col):
    self._view = view
    self._row = row
    self._start_col = start_col
    self._end_col = end_col

  def __getitem__(self, index):
    if isinstance(index, slice):
      start, stop, step = index.indices(len(self))
      assert step == 1, 'slicing with step is not supported'
      if stop < start:
        stop = start
      return WorksheetViewRow(
          self._view, self._row,
          self._start_col + start, self._end_col + stop)
    assert isinstance(index, int)
    col = self._start_col + index
    if not (self._start_col <= col < self._end_col):
      raise KeyError()
    if (self._row, col) not in self._view._input_value_map:
      self._view._ensure_cells_fetched()
    return self._view._input_value_map.get((self._row, col))

  def __setitem__(self, index, new_value):
    assert isinstance(index, int)
    col = self._start_col + index
    if not (self._start_col <= col < self._end_col):
      raise KeyError()
    if new_value is None:
      pass
    elif isinstance(new_value, int):
      new_value = u'%d' % new_value
    elif isinstance(new_value, float):
      # Do best not to lose precision...
      new_value = u'%20e' % new_value
    elif isinstance(new_value, str):
      new_value = new_value.encode('utf-8')
    elif not isinstance(new_value, unicode):
      new_value = unicode(new_value)
    self._view._input_value_map[(self._row, col)] = new_value
    self._view._queued_updates.append((self._row, col, new_value))

  def __len__(self):
    return self._end_col - self._start_col

  def __iter__(self):
    self._view._ensure_cells_fetched()
    for col in xrange(self._start_col, self._end_col):
      yield self._view._input_value_map.get((self._row, col))

  def __repr__(self):
    return repr([self[i] for i in xrange(len(self))])

class Worksheet(WorksheetView):
  def __init__(self, spreadsheet, client, key, entry):
    self.spreadsheet = spreadsheet
    self.client = client
    self.key = key
    self._entry = entry
    super(Worksheet, self).__init__(self, client, 0, self.rows, 0, self.cols)

  def refresh(self):
    self._entry = self.client.get_worksheet(self.spreadsheet.key, self.key)
    self._reset_size(0, self.rows, 0, self.cols)
    super(Worksheet, self).refresh()

  def view(self, start_row=None, end_row=None, start_col=None, end_col=None):
    if start_row is None:
      start_row = 0
    if end_row is None:
      end_row = self.rows
    if start_col is None:
      start_col = 0
    if end_col is None:
      end_col = self.cols
    if not (0 <= start_row <= end_row <= self.rows):
      raise KeyError()
    if not (0 <= start_col <= end_col <= self.cols):
      raise KeyError()
    return WorksheetView(
        self, self.client,
        start_row=start_row, end_row=end_row,
        start_col=start_col, end_col=end_col)

  def set_size(self, rows, cols):
    assert isinstance(rows, int) and rows > 0
    assert isinstance(cols, int) and cols > 0
    self._entry.row_count.text = str(rows)
    self._entry.col_count.text = str(cols)
    self._update()

  @property
  def title(self):
    return self._entry.title.text

  @title.setter
  def title(self, new_title):
    self._entry.title.text = new_title
    self._update()

  @property
  def rows(self):
    return int(self._entry.row_count.text)

  @rows.setter
  def rows(self, rows):
    assert isinstance(rows, int) and rows > 0
    self._entry.row_count.text = str(rows)
    self._update()

  @property
  def cols(self):
    return int(self._entry.col_count.text)

  @cols.setter
  def cols(self, cols):
    assert isinstance(cols, int) and cols > 0
    self._entry.col_count.text = str(cols)
    self._update()

  def _update(self):
    url = gdata.spreadsheets.client.WORKSHEET_URL % (
        self.spreadsheet.key, self.key)
    # TODO: Use returned entry to speed up
    unused_entry = self.client.update(self._entry, uri=url, force=True)
    self.refresh()
<commit_msg>Fill empty cells with empty strings.<commit_after># Copyright 2015 Google Inc. All rights reserved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import collections
import datetime
import json

import apiclient.discovery
import apiclient.http
import gdata.gauth
import gdata.spreadsheets.client
import gdata.spreadsheets.data
import httplib2
import oauth2client.client

from . import util

GOOGLE_SPREADSHEET_SCOPES = (
    'https://spreadsheets.google.com/feeds',
    'https://www.googleapis.com/auth/drive',
)

SPREADSHEET_URL = (
    'https://spreadsheets.google.com/feeds/spreadsheets/private/full/%s')

class Collection(util.LazyOrderedDictionary):
  def __init__(self, client, drive):
    super(Collection, self).__init__(
        self._spreadsheet_enumerator,
        self._spreadsheet_constructor)
    self.client = client
    self.drive = drive

  @classmethod
  def login(cls, json_path=None, json_text=None):
    if json_text is None:
      with open(json_path, 'rb') as f:
        json_text = f.read()
    json_data = json.loads(json_text)
    if '_module' in json_data:
      credentials = oauth2client.client.Credentials.new_from_json(json_text)
    elif 'private_key' in json_data:
      credentials = oauth2client.client.SignedJwtAssertionCredentials(
          service_account_name=json_data['client_email'],
          private_key=json_data['private_key'],
          scope=GOOGLE_SPREADSHEET_SCOPES)
    else:
      raise ValueError('unrecognized credential format')
    # Don't use auth_token= argument. It does not refresh tokens.
    client = gdata.spreadsheets.client.SpreadsheetsClient()
    auth_http = httplib2.Http()
    auth_token = gdata.gauth.OAuth2TokenFromCredentials(credentials)
    auth_token.authorize(client)
    auth_http = credentials.authorize(auth_http)
    drive = apiclient.discovery.build('drive', 'v2', http=auth_http)
    return cls(client, drive)

  def create_spreadsheet(self, title, rows=1000, cols=26):
    body = {
        'title': title,
        'mimeType': 'application/vnd.google-apps.spreadsheet',
    }
    response = self.drive.files().insert(body=body).execute()
    key = response['id']
    self.refresh()
    spreadsheet = self[key]
    if (rows, cols) != (1000, 26):
      spreadsheet[0].set_size(rows, cols)
    return spreadsheet

  def refresh(self):
    super(Collection, self).refresh()

  def _spreadsheet_enumerator(self):
    feed = self.client.get_spreadsheets()
    for entry in feed.entry:
      key = entry.get_spreadsheet_key()
      yield (key, Spreadsheet(self, self.client, self.drive, key, entry))

  def _spreadsheet_constructor(self, key):
    # TODO: Upstream to gdata.
    entry = self.client.get_feed(
        SPREADSHEET_URL % key,
        desired_class=gdata.spreadsheets.data.Spreadsheet)
    key = entry.get_spreadsheet_key()
    return Spreadsheet(self, self.client, self.drive, key, entry)

class Spreadsheet(util.LazyOrderedDictionary):
  def __init__(self, collection, client, drive, key, entry):
    super(Spreadsheet, self).__init__(self._worksheet_enumerator, None)
    self.collection = collection
    self.client = client
    self.drive = drive
    self.key = key
    self._entry = entry

  def refresh(self):
    super(Spreadsheet, self).refresh()
    # TODO: Upstream to gdata.
    self._entry = self.client.get_feed(
        SPREADSHEET_URL % self.key,
        desired_class=gdata.spreadsheets.data.Spreadsheet)

  def add_worksheet(self, title, rows=1000, cols=26):
    self.client.add_worksheet(self.key, title, rows=rows, cols=cols)
    self.refresh()
    return self[title]

  def delete_worksheet(self, title):
    worksheet = self[title]
    url = gdata.spreadsheets.client.WORKSHEET_URL % (self.key, worksheet.key)
    self.client.delete(url, force=True)
    self.refresh()

  @property
  def url(self):
    return 'https://docs.google.com/spreadsheets/d/%s/edit' % self.key

  @property
  def title(self):
    return self._entry.title.text

  @title.setter
  def title(self, new_title):
    body = {'title': new_title}
    response = self.drive.files().update(fileId=self.key, body=body).execute()
    self.refresh()

  @property
  def updated(self):
    return datetime.datetime.strptime(
        self._entry.updated.text, '%Y-%m-%dT%H:%M:%S.%fZ')

  def _worksheet_enumerator(self):
    feed = self.client.get_worksheets(self.key)
    for entry in feed.entry:
      key = entry.get_worksheet_id()
      worksheet = Worksheet(self, self.client, key, entry)
      yield (worksheet.title, worksheet)

class WorksheetView(object):
  def __init__(self, worksheet, client, start_row, end_row, start_col, end_col):
    self.worksheet = worksheet
    self.client = client
    self._reset_size(start_row, end_row, start_col, end_col)
    self._input_value_map = {}
    self._cells_fetched = False
    self._queued_updates = []
    self.refresh()

  def refresh(self):
    self._input_value_map.clear()
    self._cells_fetched = False
    del self._queued_updates[:]

  def _reset_size(self, start_row, end_row, start_col, end_col):
    self.start_row = start_row
    self.end_row = end_row
    self.start_col = start_col
    self.end_col = end_col
    self._view_rows = [
        WorksheetViewRow(self, row, start_col, end_col)
        for row in xrange(start_row, end_row)]

  def _ensure_cells_fetched(self):
    if self._cells_fetched:
      return
    query = gdata.spreadsheets.client.CellQuery(
        min_row=(self.start_row + 1),
        max_row=self.end_row,
        min_col=(self.start_col + 1),
        max_col=self.end_col,
        return_empty=False)
    feed = self.client.get_cells(
        self.worksheet.spreadsheet.key, self.worksheet.key, query=query)
    self._input_value_map = {}
    for entry in feed.entry:
      cell = entry.cell
      self._input_value_map.setdefault(
          (int(cell.row) - 1, int(cell.col) - 1),
          cell.input_value)
    self._cells_fetched = True

  def commit(self):
    if not self._queued_updates:
      return
    feed = gdata.spreadsheets.data.build_batch_cells_update(
        self.worksheet.spreadsheet.key, self.worksheet.key)
    for row, col, new_value in self._queued_updates:
      feed.add_set_cell(row + 1, col + 1, new_value)
    self.client.batch(feed, force=True)
    del self._queued_updates[:]

  def __getitem__(self, index):
    return self._view_rows[index]

  def __len__(self):
    return self.rows

  def __iter__(self):
    for row in self._view_rows:
      yield row

  def __repr__(self):
    return '<%s %r>' % (self.__class__.__name__, self._view_rows,)

  def __enter__(self):
    return self

  def __exit__(self, exc_type, exc_value, traceback):
    self.commit()

  @property
  def rows(self):
    return self.end_row - self.start_row

  @property
  def cols(self):
    return self.end_col - self.start_col

class WorksheetViewRow(util.CustomMutableFixedList):
  def __init__(self, view, row, start_col, end_col):
    self._view = view
    self._row = row
    self._start_col = start_col
    self._end_col = end_col

  def __getitem__(self, index):
    if isinstance(index, slice):
      start, stop, step = index.indices(len(self))
      assert step == 1, 'slicing with step is not supported'
      if stop < start:
        stop = start
      return WorksheetViewRow(
          self._view, self._row,
          self._start_col + start, self._end_col + stop)
    assert isinstance(index, int)
    col = self._start_col + index
    if not (self._start_col <= col < self._end_col):
      raise KeyError()
    if (self._row, col) not in self._view._input_value_map:
      self._view._ensure_cells_fetched()
    return self._view._input_value_map.get((self._row, col), '')

  def __setitem__(self, index, new_value):
    assert isinstance(index, int)
    col = self._start_col + index
    if not (self._start_col <= col < self._end_col):
      raise KeyError()
    if new_value is None:
      pass
    elif isinstance(new_value, int):
      new_value = u'%d' % new_value
    elif isinstance(new_value, float):
      # Do best not to lose precision...
      new_value = u'%20e' % new_value
    elif isinstance(new_value, str):
      new_value = new_value.encode('utf-8')
    elif not isinstance(new_value, unicode):
      new_value = unicode(new_value)
    self._view._input_value_map[(self._row, col)] = new_value
    self._view._queued_updates.append((self._row, col, new_value))

  def __len__(self):
    return self._end_col - self._start_col

  def __iter__(self):
    self._view._ensure_cells_fetched()
    for col in xrange(self._start_col, self._end_col):
      yield self._view._input_value_map.get((self._row, col), '')

  def __repr__(self):
    return repr([self[i] for i in xrange(len(self))])

class Worksheet(WorksheetView):
  def __init__(self, spreadsheet, client, key, entry):
    self.spreadsheet = spreadsheet
    self.client = client
    self.key = key
    self._entry = entry
    super(Worksheet, self).__init__(self, client, 0, self.rows, 0, self.cols)

  def refresh(self):
    self._entry = self.client.get_worksheet(self.spreadsheet.key, self.key)
    self._reset_size(0, self.rows, 0, self.cols)
    super(Worksheet, self).refresh()

  def view(self, start_row=None, end_row=None, start_col=None, end_col=None):
    if start_row is None:
      start_row = 0
    if end_row is None:
      end_row = self.rows
    if start_col is None:
      start_col = 0
    if end_col is None:
      end_col = self.cols
    if not (0 <= start_row <= end_row <= self.rows):
      raise KeyError()
    if not (0 <= start_col <= end_col <= self.cols):
      raise KeyError()
    return WorksheetView(
        self, self.client,
        start_row=start_row, end_row=end_row,
        start_col=start_col, end_col=end_col)

  def set_size(self, rows, cols):
    assert isinstance(rows, int) and rows > 0
    assert isinstance(cols, int) and cols > 0
    self._entry.row_count.text = str(rows)
    self._entry.col_count.text = str(cols)
    self._update()

  @property
  def title(self):
    return self._entry.title.text

  @title.setter
  def title(self, new_title):
    self._entry.title.text = new_title
    self._update()

  @property
  def rows(self):
    return int(self._entry.row_count.text)

  @rows.setter
  def rows(self, rows):
    assert isinstance(rows, int) and rows > 0
    self._entry.row_count.text = str(rows)
    self._update()

  @property
  def cols(self):
    return int(self._entry.col_count.text)

  @cols.setter
  def cols(self, cols):
    assert isinstance(cols, int) and cols > 0
    self._entry.col_count.text = str(cols)
    self._update()

  def _update(self):
    url = gdata.spreadsheets.client.WORKSHEET_URL % (
        self.spreadsheet.key, self.key)
    # TODO: Use returned entry to speed up
    unused_entry = self.client.update(self._entry, uri=url, force=True)
    self.refresh()
<|endoftext|>


<commit_before># OpenSCAD gui init module
#
# Gathering all the information to start FreeCAD
# This is the second one of three init scripts, the third one
# runs when the gui is up

#***************************************************************************
#*   (c) Juergen Riegel (juergen.riegel@web.de) 2002                       *
#*                                                                         *
#*   This file is part of the FreeCAD CAx development system.              *
#*                                                                         *
#*   This program is free software; you can redistribute it and/or modify  *
#*   it under the terms of the GNU Lesser General Public License (LGPL)    *
#*   as published by the Free Software Foundation; either version 2 of     *
#*   the License, or (at your option) any later version.                   *
#*   for detail see the LICENCE text file.                                 *
#*                                                                         *
#*   FreeCAD is distributed in the hope that it will be useful,            *
#*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
#*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
#*   GNU Lesser General Public License for more details.                   *
#*                                                                         *
#*   You should have received a copy of the GNU Library General Public     *
#*   License along with FreeCAD; if not, write to the Free Software        *
#*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
#*   USA                                                                   *
#*                                                                         *
#*   Juergen Riegel 2002                                                   *
#***************************************************************************/

import FreeCAD
param = FreeCAD.ParamGet(\
    "User parameter:BaseApp/Preferences/Mod/OpenSCAD")
openscadfilename = param.GetString('openscadexecutable')

class OpenSCADWorkbench ( Workbench ):
    "OpenSCAD workbench object"
    def __init__(self):
        self.__class__.Icon = FreeCAD.getResourceDir() + "Mod/OpenSCAD/Resources/icons/OpenSCADWorkbench.svg"
        self.__class__.MenuText = "OpenSCAD"
        self.__class__.ToolTip = "OpenSCAD workbench"

    def Initialize(self):
        def QT_TRANSLATE_NOOP(scope, text):
            return text
        import OpenSCAD_rc,OpenSCADCommands
        commands=['OpenSCAD_ReplaceObject','OpenSCAD_RemoveSubtree',\
            'OpenSCAD_RefineShapeFeature',\
            'OpenSCAD_IncreaseToleranceFeature', 'OpenSCAD_Edgestofaces', \
            'OpenSCAD_ExpandPlacements','OpenSCAD_ExplodeGroup']
        toolbarcommands=['OpenSCAD_ReplaceObject','OpenSCAD_RemoveSubtree',\
            'OpenSCAD_ExplodeGroup','OpenSCAD_RefineShapeFeature']
            #'OpenSCAD_IncreaseToleranceFeature' #icon still missing
        import PartGui
        parttoolbarcommands = ['Part_CheckGeometry',"Part_Primitives",\
            "Part_Builder",'Part_Cut','Part_Fuse','Part_Common',\
            'Part_Extrude',"Part_Revolve"]
        import FreeCAD
        param = FreeCAD.ParamGet(\
            "User parameter:BaseApp/Preferences/Mod/OpenSCAD")
        openscadfilename = param.GetString('openscadexecutable')
        if not openscadfilename:

            import OpenSCADUtils
            openscadfilename = OpenSCADUtils.searchforopenscadexe()
            if openscadfilename: #automatic search was succsessful
                FreeCAD.addImportType("OpenSCAD Format (*.scad)","importCSG")
                param.SetString('openscadexecutable',openscadfilename) #save the result
        if openscadfilename:
            commands.extend(['OpenSCAD_AddOpenSCADElement',
                'OpenSCAD_MeshBoolean','OpenSCAD_Hull','OpenSCAD_Minkowski'])
            toolbarcommands.extend(['OpenSCAD_AddOpenSCADElement',
                'OpenSCAD_MeshBoolean','OpenSCAD_Hull','OpenSCAD_Minkowski'])
        else:
            FreeCAD.Console.PrintWarning('OpenSCAD executable not found\n')

        self.appendToolbar(QT_TRANSLATE_NOOP('Workbench','OpenSCADTools'),toolbarcommands)
        self.appendMenu('OpenSCAD',commands)
        self.appendToolbar(QT_TRANSLATE_NOOP('Workbech','OpenSCAD Part tools'),parttoolbarcommands)
        #self.appendMenu('OpenSCAD',["AddOpenSCADElement"])
        ###self.appendCommandbar("&Generic Tools",["ColorCodeShape"])
        FreeCADGui.addIconPath(":/icons")
        FreeCADGui.addLanguagePath(":/translations")
        FreeCADGui.addPreferencePage(":/ui/openscadprefs-base.ui","OpenSCAD")
    def GetClassName(self):
        #return "OpenSCADGui::Workbench"
        return "Gui::PythonWorkbench"

Gui.addWorkbench(OpenSCADWorkbench())
<commit_msg>OpenSCAD: Add IncreaseToleranceFeature icon to toolbar<commit_after># OpenSCAD gui init module
#
# Gathering all the information to start FreeCAD
# This is the second one of three init scripts, the third one
# runs when the gui is up

#***************************************************************************
#*   (c) Juergen Riegel (juergen.riegel@web.de) 2002                       *
#*                                                                         *
#*   This file is part of the FreeCAD CAx development system.              *
#*                                                                         *
#*   This program is free software; you can redistribute it and/or modify  *
#*   it under the terms of the GNU Lesser General Public License (LGPL)    *
#*   as published by the Free Software Foundation; either version 2 of     *
#*   the License, or (at your option) any later version.                   *
#*   for detail see the LICENCE text file.                                 *
#*                                                                         *
#*   FreeCAD is distributed in the hope that it will be useful,            *
#*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
#*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
#*   GNU Lesser General Public License for more details.                   *
#*                                                                         *
#*   You should have received a copy of the GNU Library General Public     *
#*   License along with FreeCAD; if not, write to the Free Software        *
#*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
#*   USA                                                                   *
#*                                                                         *
#*   Juergen Riegel 2002                                                   *
#***************************************************************************/

import FreeCAD
param = FreeCAD.ParamGet(\
    "User parameter:BaseApp/Preferences/Mod/OpenSCAD")
openscadfilename = param.GetString('openscadexecutable')

class OpenSCADWorkbench ( Workbench ):
    "OpenSCAD workbench object"
    def __init__(self):
        self.__class__.Icon = FreeCAD.getResourceDir() + "Mod/OpenSCAD/Resources/icons/OpenSCADWorkbench.svg"
        self.__class__.MenuText = "OpenSCAD"
        self.__class__.ToolTip = "OpenSCAD workbench"

    def Initialize(self):
        def QT_TRANSLATE_NOOP(scope, text):
            return text
        import OpenSCAD_rc,OpenSCADCommands
        commands=['OpenSCAD_ReplaceObject','OpenSCAD_RemoveSubtree',\
            'OpenSCAD_RefineShapeFeature',\
            'OpenSCAD_IncreaseToleranceFeature', 'OpenSCAD_Edgestofaces',\
            'OpenSCAD_ExpandPlacements','OpenSCAD_ExplodeGroup']
        toolbarcommands=['OpenSCAD_ReplaceObject','OpenSCAD_RemoveSubtree',\
            'OpenSCAD_ExplodeGroup','OpenSCAD_RefineShapeFeature',\
            'OpenSCAD_IncreaseToleranceFeature']
        import PartGui
        parttoolbarcommands = ['Part_CheckGeometry',"Part_Primitives",\
            "Part_Builder",'Part_Cut','Part_Fuse','Part_Common',\
            'Part_Extrude',"Part_Revolve"]
        import FreeCAD
        param = FreeCAD.ParamGet(\
            "User parameter:BaseApp/Preferences/Mod/OpenSCAD")
        openscadfilename = param.GetString('openscadexecutable')
        if not openscadfilename:

            import OpenSCADUtils
            openscadfilename = OpenSCADUtils.searchforopenscadexe()
            if openscadfilename: #automatic search was succsessful
                FreeCAD.addImportType("OpenSCAD Format (*.scad)","importCSG")
                param.SetString('openscadexecutable',openscadfilename) #save the result
        if openscadfilename:
            commands.extend(['OpenSCAD_AddOpenSCADElement',
                'OpenSCAD_MeshBoolean','OpenSCAD_Hull','OpenSCAD_Minkowski'])
            toolbarcommands.extend(['OpenSCAD_AddOpenSCADElement',
                'OpenSCAD_MeshBoolean','OpenSCAD_Hull','OpenSCAD_Minkowski'])
        else:
            FreeCAD.Console.PrintWarning('OpenSCAD executable not found\n')

        self.appendToolbar(QT_TRANSLATE_NOOP('Workbench','OpenSCADTools'),toolbarcommands)
        self.appendMenu('OpenSCAD',commands)
        self.appendToolbar(QT_TRANSLATE_NOOP('Workbech','OpenSCAD Part tools'),parttoolbarcommands)
        #self.appendMenu('OpenSCAD',["AddOpenSCADElement"])
        ###self.appendCommandbar("&Generic Tools",["ColorCodeShape"])
        FreeCADGui.addIconPath(":/icons")
        FreeCADGui.addLanguagePath(":/translations")
        FreeCADGui.addPreferencePage(":/ui/openscadprefs-base.ui","OpenSCAD")
    def GetClassName(self):
        #return "OpenSCADGui::Workbench"
        return "Gui::PythonWorkbench"

Gui.addWorkbench(OpenSCADWorkbench())
<|endoftext|>


<commit_before>import argparse
import logging
import subprocess
import glob

import pkg_resources

from imhotep.repomanagers import ShallowRepoManager, RepoManager
from .reporters.printing import PrintingReporter
from .reporters.github import CommitReporter, PRReporter
from .diff_parser import DiffContextParser
from .shas import get_pr_info, CommitInfo
from imhotep import http
from .errors import UnknownTools, NoCommitInfo

log = logging.getLogger(__name__)

def run(cmd, cwd='.'):
    log.debug("Running: %s", cmd)
    return subprocess.Popen(
        [cmd], stdout=subprocess.PIPE, shell=True, cwd=cwd).communicate()[0]

def find_config(dirname, config_filenames):
    configs = []
    for filename in config_filenames:
        configs += glob.glob('%s/%s' % (dirname, filename))
    return set(configs)

def run_analysis(repo, filenames=set(), linter_configs=set()):
    results = {}
    for tool in repo.tools:
        log.debug("running %s" % tool.__class__.__name__)
        configs = {}
        try:
            configs = tool.get_configs()
        except AttributeError:
            pass
        linter_configs = find_config(repo.dirname, configs)
        log.debug("Tool configs %s, found configs %s", configs, linter_configs)
        run_results = tool.invoke(repo.dirname,
                                  filenames=filenames,
                                  linter_configs=linter_configs)
        results.update(run_results)
    return results

def load_plugins():
    tools = []
    for ep in pkg_resources.iter_entry_points(group='imhotep_linters'):
        klass = ep.load()
        tools.append(klass(run))
    return tools

class Imhotep(object):
    def __init__(self, requester=None, repo_manager=None,
                 repo_name=None, pr_number=None,
                 commit_info=None,
                 commit=None, origin_commit=None, no_post=None, debug=None,
                 filenames=None, shallow_clone=False, **kwargs):
        # TODO(justinabrahms): kwargs exist until we handle cli params better
        # TODO(justinabrahms): This is a sprawling API. Tighten it up.
        self.requester = requester
        self.manager = repo_manager

        self.commit_info = commit_info
        self.repo_name = repo_name
        self.pr_number = pr_number
        self.commit = commit
        self.origin_commit = origin_commit
        self.no_post = no_post
        self.debug = debug
        if filenames is None:
            filenames = []
        self.requested_filenames = set(filenames)
        self.shallow = shallow_clone

        if self.commit is None and self.pr_number is None:
            raise NoCommitInfo()

    def get_reporter(self):
        if self.no_post:
            return PrintingReporter()
        if self.pr_number:
            return PRReporter(self.requester, self.pr_number)
        elif self.commit is not None:
            return CommitReporter(self.requester)

    def get_filenames(self, entries, requested_set=None):
        filenames = set([x.result_filename for x in entries])
        if requested_set is not None and len(requested_set):
            filenames = requested_set.intersection(filenames)
        return list(filenames)

    def invoke(self):
        cinfo = self.commit_info
        reporter = self.get_reporter()

        try:
            repo = self.manager.clone_repo(self.repo_name,
                                           remote_repo=cinfo.remote_repo,
                                           ref=cinfo.ref)
            diff = repo.diff_commit(cinfo.commit,
                                    compare_point=cinfo.origin)

            # Move out to its own thing
            parser = DiffContextParser(diff)
            parse_results = parser.parse()
            filenames = self.get_filenames(parse_results,
                                           self.requested_filenames)
            results = run_analysis(repo,
                                   filenames=filenames)

            error_count = 0
            for entry in parse_results:
                added_lines = [l.number for l in entry.added_lines]
                pos_map = {}
                for x in entry.added_lines:
                    pos_map[x.number] = x.position

                violations = results.get(entry.result_filename, {})
                violating_lines = [int(l) for l in violations.keys()]

                matching_numbers = set(added_lines).intersection(
                    violating_lines)
                for x in matching_numbers:
                    error_count += 1
                    reporter.report_line(
                        repo.name, cinfo.origin, entry.result_filename,
                        x, pos_map[x], violations['%s' % x])

                log.info("%d violations.", error_count)
        finally:
            self.manager.cleanup()

def gen_imhotep(**kwargs):
    # TODO(justinabrahms): Interface should have a "are creds valid?" method
    req = http.BasicAuthRequester(kwargs['github_username'],
                                  kwargs['github_password'])

    plugins = load_plugins()
    tools = get_tools(kwargs['linter'], plugins)

    if kwargs['shallow']:
        Manager = ShallowRepoManager
    else:
        Manager = RepoManager

    manager = Manager(authenticated=kwargs['authenticated'],
                      cache_directory=kwargs['cache_directory'],
                      tools=tools,
                      executor=run)

    if kwargs['pr_number']:
        pr_info = get_pr_info(req, kwargs['repo_name'], kwargs['pr_number'])
        commit_info = pr_info.to_commit_info()
    else:
        # TODO(justinabrahms): origin & remote_repo doesnt work for commits
        commit_info = CommitInfo(kwargs['commit'], None, None, None)

    log.debug('Shallow: %s', kwargs['shallow'])
    shallow_clone = kwargs['shallow'] or False

    return Imhotep(
        requester=req, repo_manager=manager, commit_info=commit_info,
        shallow_clone=shallow_clone, **kwargs)

def get_tools(whitelist, known_plugins):
    """
    Filter all known plugins by a whitelist specified. If the whitelist is
    empty, default to all plugins.
    """
    getpath = lambda c: "%s:%s" % (c.__module__, c.__class__.__name__)

    tools = [x for x in known_plugins if getpath(x) in whitelist]

    if not tools:
        if whitelist:
            raise UnknownTools(map(getpath, known_plugins))
        tools = known_plugins
    return tools

def parse_args(args):
    arg_parser = argparse.ArgumentParser(
        description="Posts static analysis results to github.")
    arg_parser.add_argument(
        '--config-file',
        default="imhotep_config.json",
        type=str,
        help="Configuration file in json.")
    arg_parser.add_argument(
        '--repo_name', required=True,
        help="Github repository name in owner/repo format")
    arg_parser.add_argument(
        '--commit',
        help="The sha of the commit to run static analysis on.")
    arg_parser.add_argument(
        '--origin-commit',
        required=False,
        default='HEAD^',
        help='Commit to use as the comparison point.')
    arg_parser.add_argument(
        '--filenames', nargs="+",
        help="filenames you want static analysis to be limited to.")
    arg_parser.add_argument(
        '--debug',
        action='store_true',
        help="Will dump debugging output and won't clean up after itself.")
    arg_parser.add_argument(
        '--github-username',
        help='Github user to post comments as.')
    arg_parser.add_argument(
        '--github-password',
        help='Github password for the above user.')
    arg_parser.add_argument(
        '--no-post',
        action="store_true",
        help="[DEBUG] will print out comments rather than posting to github.")
    arg_parser.add_argument(
        '--authenticated',
        action="store_true",
        help="Indicates the repository requires authentication")
    arg_parser.add_argument(
        '--pr-number',
        help="Number of the pull request to comment on")
    arg_parser.add_argument(
        '--cache-directory',
        help="Path to directory to cache the repository",
        type=str,
        required=False)
    arg_parser.add_argument(
        '--linter',
        help="Path to linters to run, e.g. 'imhotep.tools:PyLint'",
        type=str,
        nargs="+",
        default=[],
        required=False)
    arg_parser.add_argument(
        '--shallow',
        help="Performs a shallow clone of the repo",
        action="store_true")
    # parse out repo name
    return arg_parser.parse_args(args)
<commit_msg> E731 do not assign a lambda expression, use a def<commit_after>import argparse
import logging
import subprocess
import glob

import pkg_resources

from imhotep.repomanagers import ShallowRepoManager, RepoManager
from .reporters.printing import PrintingReporter
from .reporters.github import CommitReporter, PRReporter
from .diff_parser import DiffContextParser
from .shas import get_pr_info, CommitInfo
from imhotep import http
from .errors import UnknownTools, NoCommitInfo

log = logging.getLogger(__name__)

def run(cmd, cwd='.'):
    log.debug("Running: %s", cmd)
    return subprocess.Popen(
        [cmd], stdout=subprocess.PIPE, shell=True, cwd=cwd).communicate()[0]

def find_config(dirname, config_filenames):
    configs = []
    for filename in config_filenames:
        configs += glob.glob('%s/%s' % (dirname, filename))
    return set(configs)

def run_analysis(repo, filenames=set(), linter_configs=set()):
    results = {}
    for tool in repo.tools:
        log.debug("running %s" % tool.__class__.__name__)
        configs = {}
        try:
            configs = tool.get_configs()
        except AttributeError:
            pass
        linter_configs = find_config(repo.dirname, configs)
        log.debug("Tool configs %s, found configs %s", configs, linter_configs)
        run_results = tool.invoke(repo.dirname,
                                  filenames=filenames,
                                  linter_configs=linter_configs)
        results.update(run_results)
    return results

def load_plugins():
    tools = []
    for ep in pkg_resources.iter_entry_points(group='imhotep_linters'):
        klass = ep.load()
        tools.append(klass(run))
    return tools

class Imhotep(object):
    def __init__(self, requester=None, repo_manager=None,
                 repo_name=None, pr_number=None,
                 commit_info=None,
                 commit=None, origin_commit=None, no_post=None, debug=None,
                 filenames=None, shallow_clone=False, **kwargs):
        # TODO(justinabrahms): kwargs exist until we handle cli params better
        # TODO(justinabrahms): This is a sprawling API. Tighten it up.
        self.requester = requester
        self.manager = repo_manager

        self.commit_info = commit_info
        self.repo_name = repo_name
        self.pr_number = pr_number
        self.commit = commit
        self.origin_commit = origin_commit
        self.no_post = no_post
        self.debug = debug
        if filenames is None:
            filenames = []
        self.requested_filenames = set(filenames)
        self.shallow = shallow_clone

        if self.commit is None and self.pr_number is None:
            raise NoCommitInfo()

    def get_reporter(self):
        if self.no_post:
            return PrintingReporter()
        if self.pr_number:
            return PRReporter(self.requester, self.pr_number)
        elif self.commit is not None:
            return CommitReporter(self.requester)

    def get_filenames(self, entries, requested_set=None):
        filenames = set([x.result_filename for x in entries])
        if requested_set is not None and len(requested_set):
            filenames = requested_set.intersection(filenames)
        return list(filenames)

    def invoke(self):
        cinfo = self.commit_info
        reporter = self.get_reporter()

        try:
            repo = self.manager.clone_repo(self.repo_name,
                                           remote_repo=cinfo.remote_repo,
                                           ref=cinfo.ref)
            diff = repo.diff_commit(cinfo.commit,
                                    compare_point=cinfo.origin)

            # Move out to its own thing
            parser = DiffContextParser(diff)
            parse_results = parser.parse()
            filenames = self.get_filenames(parse_results,
                                           self.requested_filenames)
            results = run_analysis(repo,
                                   filenames=filenames)

            error_count = 0
            for entry in parse_results:
                added_lines = [l.number for l in entry.added_lines]
                pos_map = {}
                for x in entry.added_lines:
                    pos_map[x.number] = x.position

                violations = results.get(entry.result_filename, {})
                violating_lines = [int(l) for l in violations.keys()]

                matching_numbers = set(added_lines).intersection(
                    violating_lines)
                for x in matching_numbers:
                    error_count += 1
                    reporter.report_line(
                        repo.name, cinfo.origin, entry.result_filename,
                        x, pos_map[x], violations['%s' % x])

                log.info("%d violations.", error_count)
        finally:
            self.manager.cleanup()

def gen_imhotep(**kwargs):
    # TODO(justinabrahms): Interface should have a "are creds valid?" method
    req = http.BasicAuthRequester(kwargs['github_username'],
                                  kwargs['github_password'])

    plugins = load_plugins()
    tools = get_tools(kwargs['linter'], plugins)

    if kwargs['shallow']:
        Manager = ShallowRepoManager
    else:
        Manager = RepoManager

    manager = Manager(authenticated=kwargs['authenticated'],
                      cache_directory=kwargs['cache_directory'],
                      tools=tools,
                      executor=run)

    if kwargs['pr_number']:
        pr_info = get_pr_info(req, kwargs['repo_name'], kwargs['pr_number'])
        commit_info = pr_info.to_commit_info()
    else:
        # TODO(justinabrahms): origin & remote_repo doesnt work for commits
        commit_info = CommitInfo(kwargs['commit'], None, None, None)

    log.debug('Shallow: %s', kwargs['shallow'])
    shallow_clone = kwargs['shallow'] or False

    return Imhotep(
        requester=req, repo_manager=manager, commit_info=commit_info,
        shallow_clone=shallow_clone, **kwargs)

def get_tools(whitelist, known_plugins):
    """
    Filter all known plugins by a whitelist specified. If the whitelist is
    empty, default to all plugins.
    """
    def getpath(c):
        return "%s:%s" % (c.__module__, c.__class__.__name__)

    tools = [x for x in known_plugins if getpath(x) in whitelist]

    if not tools:
        if whitelist:
            raise UnknownTools(map(getpath, known_plugins))
        tools = known_plugins
    return tools

def parse_args(args):
    arg_parser = argparse.ArgumentParser(
        description="Posts static analysis results to github.")
    arg_parser.add_argument(
        '--config-file',
        default="imhotep_config.json",
        type=str,
        help="Configuration file in json.")
    arg_parser.add_argument(
        '--repo_name', required=True,
        help="Github repository name in owner/repo format")
    arg_parser.add_argument(
        '--commit',
        help="The sha of the commit to run static analysis on.")
    arg_parser.add_argument(
        '--origin-commit',
        required=False,
        default='HEAD^',
        help='Commit to use as the comparison point.')
    arg_parser.add_argument(
        '--filenames', nargs="+",
        help="filenames you want static analysis to be limited to.")
    arg_parser.add_argument(
        '--debug',
        action='store_true',
        help="Will dump debugging output and won't clean up after itself.")
    arg_parser.add_argument(
        '--github-username',
        help='Github user to post comments as.')
    arg_parser.add_argument(
        '--github-password',
        help='Github password for the above user.')
    arg_parser.add_argument(
        '--no-post',
        action="store_true",
        help="[DEBUG] will print out comments rather than posting to github.")
    arg_parser.add_argument(
        '--authenticated',
        action="store_true",
        help="Indicates the repository requires authentication")
    arg_parser.add_argument(
        '--pr-number',
        help="Number of the pull request to comment on")
    arg_parser.add_argument(
        '--cache-directory',
        help="Path to directory to cache the repository",
        type=str,
        required=False)
    arg_parser.add_argument(
        '--linter',
        help="Path to linters to run, e.g. 'imhotep.tools:PyLint'",
        type=str,
        nargs="+",
        default=[],
        required=False)
    arg_parser.add_argument(
        '--shallow',
        help="Performs a shallow clone of the repo",
        action="store_true")
    # parse out repo name
    return arg_parser.parse_args(args)
<|endoftext|>


<commit_before>"""Base kernel for the HMC family."""
from typing import Callable, Dict, List, NamedTuple, Tuple, Union

import jax
import jax.numpy as jnp

from blackjax.inference.proposals import HMCProposalInfo, HMCProposalState

__all__ = ["HMCState", "HMCInfo", "hmc"]

PyTree = Union[Dict, List, Tuple]

class HMCState(NamedTuple):
    """State of the HMC algorithm.

    The HMC algorithm takes one position of the chain and returns another
    position. In order to make computations more efficient, we also store
    the current potential energy as well as the current gradient of the
    potential energy.
    """

    position: PyTree
    potential_energy: float
    potential_energy_grad: PyTree

class HMCInfo(NamedTuple):
    """Additional information on the HMC transition.

    This additional information can be used for debugging or computing
    diagnostics.

    acceptance_probability
        The acceptance probability of the transition, linked to the energy
        difference between the original and the proposed states.
    is_accepted
        Whether the proposed position was accepted or the original position
        was returned.
    is_divergent
        Whether the difference in energy between the original and the new state
        exceeded the divergence threshold.
    energy
        The total energy that corresponds to the returned state.
    proposal
        The state proposed by the proposal. Typically includes the position and
        momentum.
    proposal_info
        Information returned by the proposal. Typically includes the step size,
        number of integration steps and intermediate states.
    """

    acceptance_probability: float
    is_accepted: bool
    is_divergent: bool
    energy: float
    proposal: HMCProposalState
    proposal_info: HMCProposalInfo

def hmc(
    proposal_generator: Callable,
    momentum_generator: Callable,
    kinetic_energy: Callable,
    divergence_threshold: float = 1000.0,
) -> Callable:
    """Create a Hamiltonian Monte Carlo transition kernel.

    Hamiltonian Monte Carlo (HMC) is known to yield effective Markov
    transitions and has been a major empirical success, leading to an extensive
    use in probabilistic programming languages and libraries [1,2,3]_.

    HMC works by augmenting the state space in which the chain evolves with an
    auxiliary momentum :math:`p`. At each step of the chain we draw a momentum
    value from the `momentum_generator` function. We then use Hamilton's
    equations [4]_ to push the state forward; we then compute the new state's
    energy using the `kinetic_energy` function and `logpdf` (potential energy).
    While the hamiltonian dynamics is conservative, numerical integration can
    introduce some discrepancy; we perform a Metropolis acceptance test to
    compensate for integration errors after having flipped the new state's
    momentum to make the transition reversible.

    I encourage anyone interested in the theoretical underpinning of the method
    to read Michael Betancourts' excellent introduction [3]_ and his more
    technical paper [5]_ on the geometric foundations of the method.

    This implementation is very general and should accomodate most variations
    on the method.

    Parameters
    ----------
    proposal_generator:
        The function used to propose a new state for the chain. For vanilla HMC this
        function integrates the trajectory over many steps, but gets more involved
        with other algorithms such as empirical and dynamical HMC.
    momentum_generator:
        A function that returns a new value for the momentum when called.
    kinetic_energy:
        A function that computes the current state's kinetic energy.
    potential:
        The potential function that is being explored, equal to minus the likelihood.
    divergence_threshold:
        The maximum difference in energy between the initial and final state
        after which we consider the transition to be divergent.

    Returns
    -------
    A kernel that moves the chain by one step when called.

    References
    ----------
    .. [1]: Duane, Simon, et al. "Hybrid monte carlo." Physics letters B
            195.2 (1987): 216-222.
    .. [2]: Neal, Radford M. "An improved acceptance procedure for the
            hybrid Monte Carlo algorithm." Journal of Computational Physics 111.1
            (1994): 194-203.
    .. [3]: Betancourt, Michael. "A conceptual introduction to
            Hamiltonian Monte Carlo." arXiv preprint arXiv:1701.02434 (2018).
    .. [4]: "Hamiltonian Mechanics", Wikipedia.
            https://en.wikipedia.org/wiki/Hamiltonian_mechanics#Deriving_Hamilton's_equations
    .. [5]: Betancourt, Michael, et al. "The geometric foundations
            of hamiltonian monte carlo." Bernoulli 23.4A (2017): 2257-2298.

    """

    def kernel(
        rng_key: jax.random.PRNGKey, state: HMCState
    ) -> Tuple[HMCState, HMCInfo]:
        """Moves the chain by one step using the Hamiltonian dynamics.

        Parameters
        ----------
        rng_key:
           The pseudo-random number generator key used to generate random numbers.
        state:
            The current state of the chain: position, log-probability and gradient
            of the log-probability.

        Returns
        -------
        The next state of the chain and additional information about the current step.
        """
        key_momentum, key_integrator, key_accept = jax.random.split(rng_key, 3)

        position, potential_energy, potential_energy_grad = state
        momentum = momentum_generator(key_momentum, position)
        energy = potential_energy + kinetic_energy(momentum, position)

        proposal, proposal_info = proposal_generator(
            key_integrator,
            HMCProposalState(
                position, momentum, potential_energy, potential_energy_grad
            ),
        )

        flipped_momentum = jax.tree_util.tree_multimap(
            lambda m: -1.0 * m, proposal.momentum
        )
        new_energy = proposal.potential_energy + kinetic_energy(
            flipped_momentum, proposal.position
        )
        new_state = HMCState(
            proposal.position, proposal.potential_energy, proposal.potential_energy_grad
        )

        delta_energy = energy - new_energy
        delta_energy = jnp.where(jnp.isnan(delta_energy), -jnp.inf, delta_energy)
        is_divergent = jnp.abs(delta_energy) > divergence_threshold

        p_accept = jnp.clip(jnp.exp(delta_energy), a_max=1)
        do_accept = jax.random.bernoulli(key_accept, p_accept)
        accept_state = (
            new_state,
            HMCInfo(
                p_accept,
                True,
                is_divergent,
                new_energy,
                proposal,
                proposal_info,
            ),
        )
        reject_state = (
            state,
            HMCInfo(
                p_accept,
                False,
                is_divergent,
                energy,
                proposal,
                proposal_info,
            ),
        )
        return jax.lax.cond(
            do_accept,
            accept_state,
            lambda state: state,
            reject_state,
            lambda state: state,
        )

    return kernel
<commit_msg>Remove missing param from docstring (#11)<commit_after>"""Base kernel for the HMC family."""
from typing import Callable, Dict, List, NamedTuple, Tuple, Union

import jax
import jax.numpy as jnp

from blackjax.inference.proposals import HMCProposalInfo, HMCProposalState

__all__ = ["HMCState", "HMCInfo", "hmc"]

PyTree = Union[Dict, List, Tuple]

class HMCState(NamedTuple):
    """State of the HMC algorithm.

    The HMC algorithm takes one position of the chain and returns another
    position. In order to make computations more efficient, we also store
    the current potential energy as well as the current gradient of the
    potential energy.
    """

    position: PyTree
    potential_energy: float
    potential_energy_grad: PyTree

class HMCInfo(NamedTuple):
    """Additional information on the HMC transition.

    This additional information can be used for debugging or computing
    diagnostics.

    acceptance_probability
        The acceptance probability of the transition, linked to the energy
        difference between the original and the proposed states.
    is_accepted
        Whether the proposed position was accepted or the original position
        was returned.
    is_divergent
        Whether the difference in energy between the original and the new state
        exceeded the divergence threshold.
    energy
        The total energy that corresponds to the returned state.
    proposal
        The state proposed by the proposal. Typically includes the position and
        momentum.
    proposal_info
        Information returned by the proposal. Typically includes the step size,
        number of integration steps and intermediate states.
    """

    acceptance_probability: float
    is_accepted: bool
    is_divergent: bool
    energy: float
    proposal: HMCProposalState
    proposal_info: HMCProposalInfo

def hmc(
    proposal_generator: Callable,
    momentum_generator: Callable,
    kinetic_energy: Callable,
    divergence_threshold: float = 1000.0,
) -> Callable:
    """Create a Hamiltonian Monte Carlo transition kernel.

    Hamiltonian Monte Carlo (HMC) is known to yield effective Markov
    transitions and has been a major empirical success, leading to an extensive
    use in probabilistic programming languages and libraries [1,2,3]_.

    HMC works by augmenting the state space in which the chain evolves with an
    auxiliary momentum :math:`p`. At each step of the chain we draw a momentum
    value from the `momentum_generator` function. We then use Hamilton's
    equations [4]_ to push the state forward; we then compute the new state's
    energy using the `kinetic_energy` function and `logpdf` (potential energy).
    While the hamiltonian dynamics is conservative, numerical integration can
    introduce some discrepancy; we perform a Metropolis acceptance test to
    compensate for integration errors after having flipped the new state's
    momentum to make the transition reversible.

    I encourage anyone interested in the theoretical underpinning of the method
    to read Michael Betancourts' excellent introduction [3]_ and his more
    technical paper [5]_ on the geometric foundations of the method.

    This implementation is very general and should accomodate most variations
    on the method.

    Parameters
    ----------
    proposal_generator:
        The function used to propose a new state for the chain. For vanilla HMC this
        function integrates the trajectory over many steps, but gets more involved
        with other algorithms such as empirical and dynamical HMC.
    momentum_generator:
        A function that returns a new value for the momentum when called.
    kinetic_energy:
        A function that computes the current state's kinetic energy.
    divergence_threshold:
        The maximum difference in energy between the initial and final state
        after which we consider the transition to be divergent.

    Returns
    -------
    A kernel that moves the chain by one step when called.

    References
    ----------
    .. [1]: Duane, Simon, et al. "Hybrid monte carlo." Physics letters B
            195.2 (1987): 216-222.
    .. [2]: Neal, Radford M. "An improved acceptance procedure for the
            hybrid Monte Carlo algorithm." Journal of Computational Physics 111.1
            (1994): 194-203.
    .. [3]: Betancourt, Michael. "A conceptual introduction to
            Hamiltonian Monte Carlo." arXiv preprint arXiv:1701.02434 (2018).
    .. [4]: "Hamiltonian Mechanics", Wikipedia.
            https://en.wikipedia.org/wiki/Hamiltonian_mechanics#Deriving_Hamilton's_equations
    .. [5]: Betancourt, Michael, et al. "The geometric foundations
            of hamiltonian monte carlo." Bernoulli 23.4A (2017): 2257-2298.

    """

    def kernel(
        rng_key: jax.random.PRNGKey, state: HMCState
    ) -> Tuple[HMCState, HMCInfo]:
        """Moves the chain by one step using the Hamiltonian dynamics.

        Parameters
        ----------
        rng_key:
           The pseudo-random number generator key used to generate random numbers.
        state:
            The current state of the chain: position, log-probability and gradient
            of the log-probability.

        Returns
        -------
        The next state of the chain and additional information about the current step.
        """
        key_momentum, key_integrator, key_accept = jax.random.split(rng_key, 3)

        position, potential_energy, potential_energy_grad = state
        momentum = momentum_generator(key_momentum, position)
        energy = potential_energy + kinetic_energy(momentum, position)

        proposal, proposal_info = proposal_generator(
            key_integrator,
            HMCProposalState(
                position, momentum, potential_energy, potential_energy_grad
            ),
        )

        flipped_momentum = jax.tree_util.tree_multimap(
            lambda m: -1.0 * m, proposal.momentum
        )
        new_energy = proposal.potential_energy + kinetic_energy(
            flipped_momentum, proposal.position
        )
        new_state = HMCState(
            proposal.position, proposal.potential_energy, proposal.potential_energy_grad
        )

        delta_energy = energy - new_energy
        delta_energy = jnp.where(jnp.isnan(delta_energy), -jnp.inf, delta_energy)
        is_divergent = jnp.abs(delta_energy) > divergence_threshold

        p_accept = jnp.clip(jnp.exp(delta_energy), a_max=1)
        do_accept = jax.random.bernoulli(key_accept, p_accept)
        accept_state = (
            new_state,
            HMCInfo(
                p_accept,
                True,
                is_divergent,
                new_energy,
                proposal,
                proposal_info,
            ),
        )
        reject_state = (
            state,
            HMCInfo(
                p_accept,
                False,
                is_divergent,
                energy,
                proposal,
                proposal_info,
            ),
        )
        return jax.lax.cond(
            do_accept,
            accept_state,
            lambda state: state,
            reject_state,
            lambda state: state,
        )

    return kernel
<|endoftext|>


<commit_before>"""
$description Global live-streaming and video on-demand hosting platform.
$url dailymotion.com
$type live, vod
"""

import logging
import re

from streamlink.plugin import Plugin, pluginmatcher
from streamlink.plugin.api import validate
from streamlink.stream.hls import HLSStream
from streamlink.stream.http import HTTPStream

log = logging.getLogger(__name__)

@pluginmatcher(re.compile(r"""
    https?://(?:\w+\.)?dailymotion\.com
    (?:
        (/embed)?/(video|live)/(?P<media_id>[^_?/]+)
        |
        /(?P<user>[\w-]+)
    )
""", re.VERBOSE))
class DailyMotion(Plugin):
    _URL_API_USER_VIDEO = "https://api.dailymotion.com/user/{user}/videos"
    _URL_STREAM_INFO = "https://www.dailymotion.com/player/metadata/video/{media_id}"

    def _get_streams_from_media(self, media_id):
        media = self.session.http.get(
            self._URL_STREAM_INFO.format(media_id=media_id),
            cookies={
                "family_filter": "off",
                "ff": "off",
            },
            schema=validate.Schema(
                validate.parse_json(),
                validate.any(
                    {
                        "error": {"type": "not_found"},
                    },
                    {
                        "error": {"title": str},
                    },
                    {
                        "owner.username": str,
                        "title": str,
                        "qualities": {
                            str: [{
                                "type": str,
                                "url": validate.url(),
                            }],
                        },
                    },
                ),
            ),
        )

        error = media.get("error")
        if error:
            if error.get("type") == "not_found":
                log.error(f"Unknown media ID: {media_id}")
            else:
                log.error(f"Failed to get stream: {error['title']}")
            return

        self.id = media_id
        self.author = media["owner.username"]
        self.title = media["title"]

        for quality, streams in media["qualities"].items():
            for stream in streams:
                if stream["type"] == "application/x-mpegURL":
                    if quality != "auto":
                        # Avoid duplicate HLS streams with bitrate selector in the URL query
                        continue
                    yield from HLSStream.parse_variant_playlist(self.session, stream["url"]).items()
                elif stream["type"] == "video/mp4":
                    # Drop FPS in quality
                    quality = re.sub(r"@\d+", "", quality)
                    resolution = f"{quality}p"
                    yield resolution, HTTPStream(self.session, stream["url"])

    def _get_media_id(self, user):
        # https://developers.dailymotion.com/tools/
        data = self.session.http.get(
            self._URL_API_USER_VIDEO.format(user=user),
            params={
                "fields": "id",
                "flags": "live_onair",
                "family_filter": "false",
            },
            acceptable_status=(200, 404),
            schema=validate.Schema(
                validate.parse_json(),
                validate.any(
                    {
                        "error": {"message": str},
                    },
                    {
                        "list": [{"id": str}],
                    },
                ),
            ),
        )

        if data.get("error"):
            log.error(f"Error while retrieving media ID: {data['error']['message']}")
            return

        if not data["list"]:
            log.error(f"No live streams found for channel {user}")
            return

        return data["list"][0]["id"]

    def _get_streams(self):
        media_id = self.match.group("media_id")
        user = self.match.group("user")

        if not media_id and user:
            media_id = self._get_media_id(user)

        if media_id:
            log.debug(f"Found media ID: {media_id}")
            return self._get_streams_from_media(media_id)

__plugin__ = DailyMotion
<commit_msg>plugins.dailymotion: fix validation schema<commit_after>"""
$description Global live-streaming and video on-demand hosting platform.
$url dailymotion.com
$type live, vod
"""

import logging
import re

from streamlink.plugin import Plugin, pluginmatcher
from streamlink.plugin.api import validate
from streamlink.stream.hls import HLSStream
from streamlink.stream.http import HTTPStream

log = logging.getLogger(__name__)

@pluginmatcher(re.compile(r"""
    https?://(?:\w+\.)?dailymotion\.com
    (?:
        (/embed)?/(video|live)/(?P<media_id>[^_?/]+)
        |
        /(?P<user>[\w-]+)
    )
""", re.VERBOSE))
class DailyMotion(Plugin):
    _URL_API_USER_VIDEO = "https://api.dailymotion.com/user/{user}/videos"
    _URL_STREAM_INFO = "https://www.dailymotion.com/player/metadata/video/{media_id}"

    def _get_streams_from_media(self, media_id):
        media = self.session.http.get(
            self._URL_STREAM_INFO.format(media_id=media_id),
            cookies={
                "family_filter": "off",
                "ff": "off",
            },
            schema=validate.Schema(
                validate.parse_json(),
                validate.any(
                    {
                        "error": {"type": "not_found"},
                    },
                    {
                        "error": {"title": str},
                    },
                    {
                        "owner": {
                            "username": str,
                        },
                        "title": str,
                        "qualities": {
                            str: [{
                                "type": str,
                                "url": validate.url(),
                            }],
                        },
                    },
                ),
            ),
        )

        error = media.get("error")
        if error:
            if error.get("type") == "not_found":
                log.error(f"Unknown media ID: {media_id}")
            else:
                log.error(f"Failed to get stream: {error['title']}")
            return

        self.id = media_id
        self.author = media["owner"]["username"]
        self.title = media["title"]

        for quality, streams in media["qualities"].items():
            for stream in streams:
                if stream["type"] == "application/x-mpegURL":
                    if quality != "auto":
                        # Avoid duplicate HLS streams with bitrate selector in the URL query
                        continue
                    yield from HLSStream.parse_variant_playlist(self.session, stream["url"]).items()
                elif stream["type"] == "video/mp4":
                    # Drop FPS in quality
                    quality = re.sub(r"@\d+", "", quality)
                    resolution = f"{quality}p"
                    yield resolution, HTTPStream(self.session, stream["url"])

    def _get_media_id(self, user):
        # https://developers.dailymotion.com/tools/
        data = self.session.http.get(
            self._URL_API_USER_VIDEO.format(user=user),
            params={
                "fields": "id",
                "flags": "live_onair",
                "family_filter": "false",
            },
            acceptable_status=(200, 404),
            schema=validate.Schema(
                validate.parse_json(),
                validate.any(
                    {
                        "error": {"message": str},
                    },
                    {
                        "list": [{"id": str}],
                    },
                ),
            ),
        )

        if data.get("error"):
            log.error(f"Error while retrieving media ID: {data['error']['message']}")
            return

        if not data["list"]:
            log.error(f"No live streams found for channel {user}")
            return

        return data["list"][0]["id"]

    def _get_streams(self):
        media_id = self.match.group("media_id")
        user = self.match.group("user")

        if not media_id and user:
            media_id = self._get_media_id(user)

        if media_id:
            log.debug(f"Found media ID: {media_id}")
            return self._get_streams_from_media(media_id)

__plugin__ = DailyMotion
<|endoftext|>


<commit_before><commit_msg>Release script that I used to release goo-0.1<commit_after><|endoftext|>