<commit_before>#!/usr/bin/env python2.7.5
#Carnac 1.3 Gui test this is with the headfirst guide

#Call Tkinter
from Tkinter import *
import tkFileDialog
import csv

#-------------------
#Application Window
#-------------------
#make app window
app = Tk()
app.title("Test GUI for Carnac")
app.geometry("400x400")

#------------------------
#Defs and Button functions
#------------------------
#define some commands
#import button, gets and reads in file, defines list
def import_csv():
    print "Importing..."
    filename = tkFileDialog.askopenfilename(filetypes=[('CSV (Comma Deliminated)', '.csv')], parent=app, title="import")
    print filename
#write in the CSV

    with open(filename, 'r') as csvfile:
        imported_file = csv.reader(csvfile, delimiter=' ', quotechar='|')
        working_file = []
        for row in imported_file:
                    print ', '.join(row)
                    working_file.append(row)
        print working_file
        global working_file
#copy over the list, so the original is preserved

def alright():
    print "Alright, test that string"
    print working_file
#save button, takes working file turns into output file,
def save_csv():
    print "Saving..."
    print working_file
    exportname = tkFileDialog.asksaveasfilename(filetypes=[('CSV (Comma Deliminated)', '.csv')], defaultextension=".csv", parent=app, title="Save As")
    print exportname
# write contents of list into .csv

    with open(exportname, 'wb') as csvfile:
        output_file = csv.writer(csvfile, delimiter=' ', quotechar='|', quoting=csv.QUOTE_MINIMAL)
        #output_file.writerow(['please', 'work', 'damnit'])
        output_file.writerows(working_file)

#-----------------
#Menu
#-----------------
#creates menu
menu_bar = Menu(app)

#creates sub menu
file_sub_menu = Menu(menu_bar, tearoff=0)
file_sub_menu.add_command(label="Import File", command=import_csv)
file_sub_menu.add_command(label="Save As", command=save_csv)
file_sub_menu.add_separator()
file_sub_menu.add_command(label="Close", command=app.quit)

menu_bar.add_cascade(label="File", menu=file_sub_menu)
#makes menu_bar App's menu
app.config(menu=menu_bar)

#-----------------
#Display
#-----------------
#-----------------
#Button Bar
#-----------------
#button_bar = Frame()
#Label(button_bar, text="").pack(side = "bottom")
close_button = Button(app, text = "Close", command=app.quit)
close_button.pack(side = "right")

alright_button = Button(app, text = "Alright", command=alright)
alright_button.pack(side = "left")
'''
import_button = Button(app, text = "Import", command=import_csv)
import_button.pack(side = "left")

#import_button = Button(app, text = "Manage Rules", command=save_csv)
#import_button.pack(side = "left")

import_button = Button(app, text = "Save", command=save_csv)
import_button.pack(side = "left")

'''

app.mainloop()
app.destroy()

<commit_msg>MAJOR UPDATE -- Total revamp<commit_after>#!/usr/bin/env python2.7.5
#Carnac Gui using OOP
'''
Intent of program is to:
Pull in a csv
Process the title column
Run rules to modify the column contents based on "roles"
Make the rule able to be changed in app by user
Run rules multiple times
Export to file
'''
#----------
#Import your shit
#----------
from Tkinter import *
from tkMessageBox import*
import tkFileDialog
import csv
#----------
#global Variables, to be modified later
#----------
working_file = []
#----------
#call Make the Gui and buttons
#----------
class MainMenu(Frame): #calls the main window
        def __init__(self, parent=None):
            Frame.__init__(self,parent) #makes main menu top level <--- this is a lie? see @learnwhat
            self.pack(expand=YES, fill=BOTH)
            self.createWidgets()
            self.master.title("Carnac Role Guessing Tool")
            self.master.iconname("Carnac")

        def createWidgets(self): #loads widges into MainMenu
            self.makeMenuBar()
            self.makeButtonBar()
            Side_scroll = Scrollbar(self)
            Print_box = Text(self)
            Side_scroll.config(command=Print_box.yview)
            Side_scroll.pack(side=RIGHT, fill=Y)
            Print_box.config(state=DISABLED, relief=SUNKEN, width=40, height=20, bg='white',yscrollcommand=Side_scroll.set)
            Print_box.pack(side=LEFT, expand=YES, fill=BOTH)
            self.Print_box = Print_box

        def makeButtonBar(self): #aka button bar in the psuedo
            ButtonBar = Frame(self, cursor='hand2', relief=SUNKEN, bd=2)
            ButtonBar.pack(side=BOTTOM, fill=X)

            close_button = Button(ButtonBar, text = "Close", command=self.program_quit)
            close_button.pack(side = "right")

            alright_button = Button(ButtonBar, text = "Alright", command=self.alright)
            alright_button.pack(side = "left")
            '''
            import_button = Button(ButtonBar, text = "Import", command=self.import_csv)
            import_button.pack(side = "left")

            #import_button = Button(ButtonBar, text = "Manage Rules", command=self.save_csv)
            #import_button.pack(side = "left")

            import_button = Button(ButtonBar, text = "Save", command=self.save_csv)
            import_button.pack(side = "left")

            '''
        def makeMenuBar(self):
            self.menubar = Menu(self.master)
            self.master.config(menu=self.menubar) #master top level window @leanwhat top level means specifically #THIS IS THE TOPLEVEL WINDOW THAT GETS CLOSED
            self.fileMenu()

        def fileMenu(self):
            pulldown = Menu(self.menubar) # The (self.menubar) sets it in the menubar
            pulldown.add_command(label="Import File", command=self.import_csv)
            pulldown.add_command(label="Save As", command=self.save_csv)
            pulldown.add_separator()
            pulldown.add_command(label="Close", command=self.program_quit)
            self.menubar.add_cascade(label='File', underline=0, menu=pulldown)
        '''
        def askopenfilename(self):
            filename = tkFileDialog.askopenfilename(filetypes=[('CSV (Comma Deliminated)', '.csv')], parent=MainMenu, title="import")

            return filename
        '''
#-------
#define button actions
#-------
        def program_quit(self):
            print "Shut it down"
            self.master.destroy()
            '''if askyesno('Verify Quit', 'Are you sure you want to quit?'):
                Frame.quit(self)
                sys.exit()
            '''

        def import_csv(self):
            print "Importing..."
        '''
    filename = MainMenu.askopenfilename
    print filename
#write in the CSV

    with open(filename, 'r') as csvfile:
        global working_file #modifies global
        imported_file = csv.reader(csvfile, delimiter=' ', quotechar='|')
        working_file = []
        for row in imported_file:
                    print ', '.join(row)
                    working_file.append(row)
        print working_file
        '''
#copy over the list, so the original is preserved
        def alright(self):
            self.Print_box.configure(state=NORMAL) #allows additions to text widget
            self.Print_box.insert(END,"Alright, test that string \n") #try printing to text widget
            print "Alright, test that string" #for debugging
            print working_file
            self.Print_box.configure(state=DISABLED) #stops additions to text widget
#save button, takes working file turns into output file,
        def save_csv(self):

            print "Saving..."
        '''
    print working_file
    exportname = tkFileDialog.asksaveasfilename(filetypes=[('CSV (Comma Deliminated)', '.csv')], defaultextension=".csv", parent=window, title="Save As")
    print exportname
# write contents of list into .csv
    with open(exportname, 'wb') as csvfile:
        output_file = csv.writer(csvfile, delimiter=' ', quotechar='|', quoting=csv.QUOTE_MINIMAL)
        #output_file.writerow(['please', 'work', 'damnit'])
        output_file.writerows(working_file)
        '''
if __name__ == '__main__': MainMenu().mainloop() #if I'm run as a script

<|endoftext|>


<commit_before># encoding: utf8
from __future__ import unicode_literals

EMOTICONS = set("""
:)
:-)
:))
:-))
:)))
:-)))
(:
(-:
=)
(=
:]
:-]
[:
[-:
:o)
(o:
:}
:-}
8)
8-)
(-8

;)
;-)
(;
(-;

:(
:-(
:((
:-((
:(((
:-(((
):
)-:
=(

:')
:'-)
:'(
:'-(

:/
:-/
=/
:|
:-|

:P
:-P
:p
:-p

:O
:-O
:o
:-o
:0
:-0
:()

:*
:-*
:3
:-3
=3
:>
:->

:X
:-X
:x
:-x

:D
:-D
;D
;-D
=D
xD
XD
xDD
XDD
8D
8-D

^_^
^__^
^___^
>.<
>.>
<.<
._.
;_;
-_-
v.v
V.V
v_v
V_V
o_o
o_O
O_o
O_O
0_o
o_0
0_0
o.O
O.o
O.O
o.o
0.0
o.0
0.o

<3
<33
<333
</3

(^_^)
(-_-)
(._.)
(>_<)
(*_*)
(¬_¬)

ಠ_ಠ
ಠ︵ಠ
(ಠ_ಠ)
¯\(ツ)/¯
(╯°□°）╯︵┻━┻
><(((*>
""".split())

__all__ = [ "EMOTICONS" ]
<commit_msg>Add emoticons<commit_after># encoding: utf8
from __future__ import unicode_literals

EMOTICONS = set("""
:)
:-)
:))
:-))
:)))
:-)))
(:
(-:
=)
(=
:]
:-]
[:
[-:
:o)
(o:
:}
:-}
8)
8-)
(-8

;)
;-)
(;
(-;

:(
:-(
:((
:-((
:(((
:-(((
):
)-:
=(
>:(

:')
:'-)
:'(
:'-(

:/
:-/
=/
:|
:-|
:1

:P
:-P
:p
:-p

:O
:-O
:o
:-o
:0
:-0
:()
>:o

:*
:-*
:3
:-3
=3
:>
:->

:X
:-X
:x
:-x

:D
:-D
;D
;-D
=D
xD
XD
xDD
XDD
8D
8-D

^_^
^__^
^___^
>.<
>.>
<.<
._.
;_;
-_-
-__-
v.v
V.V
v_v
V_V
o_o
o_O
O_o
O_O
0_o
o_0
0_0
o.O
O.o
O.O
o.o
0.0
o.0
0.o
@_@

<3
<33
<333
</3

(^_^)
(-_-)
(._.)
(>_<)
(*_*)
(¬_¬)

ಠ_ಠ
ಠ︵ಠ
(ಠ_ಠ)
¯\(ツ)/¯
(╯°□°）╯︵┻━┻
><(((*>
""".split())

__all__ = [ "EMOTICONS" ]
<|endoftext|>


<commit_before>"""
========================================
Loading multiple RSS feeds into SQLite3
========================================

An example showing how the News-Project can be used load news articles from
RSS feeds into a database. This example allows you to create new tables
and load a SQLite3 database with News from multiple RSS feeds.

The list of RSS feeds is located at "~/examples/feeds_list.txt". The sqlite3
database is located at "~/examples/FeedMe.db".

Before running, go to "~/newsfind/capture.py" and adjust the name of your
filepath located in the __init__() method. Your filepath needs to point at
both 'feeds_list.txt' and 'FeedMe.db'.

Feel free to contact me if you run into any problems.
"""
print(__doc__)

# Author: Tyler Brown <tylers.pile@gmail.com>

# Import RSS feed capture class
from gathernews.capture import CaptureFeeds

# File path to where "feeds_list.txt" is located
file_path = "/home/tyler/GatherNews/examples/"
# Instantiate the class
capture_feeds = CaptureFeeds(file_path)

# Create new tables if any new RSS feed addresses have been added
print " Checking for new tables"
capture_feeds.create_tables()
# Populate all tables with RSS news feeds
print " Populating the SQLite3 database"
capture_feeds.populate_db()
# Remove duplicate entries
print " Removing duplicate entries from SQLite3 database"
capture_feeds.rm_duplicates()

<commit_msg>minor<commit_after>"""
========================================
Loading multiple RSS feeds into SQLite3
========================================

An example showing how the News-Project can be used load news articles from
RSS feeds into a database. This example allows you to create new tables
and load a SQLite3 database with News from multiple RSS feeds.

The list of RSS feeds is located at "~/examples/feeds_list.txt". The sqlite3
database is located at "~/examples/FeedMe.db".

Before running, go to "~/newsfind/capture.py" and adjust the name of your
filepath located in the __init__() method. Your filepath needs to point at
both 'feeds_list.txt' and 'FeedMe.db'.

Feel free to contact me if you run into any problems.
"""
print(__doc__)

# Author: Tyler Brown <tylers.pile@gmail.com>

# Import RSS feed capture class
from gathernews.capture import CaptureFeeds

# File path to where "feeds_list.txt" is located
file_path = "/home/tyler/code/GatherNews/examples/"
# Instantiate the class
capture_feeds = CaptureFeeds(file_path)

# Create new tables if any new RSS feed addresses have been added
print " Checking for new tables"
capture_feeds.create_tables()
# Populate all tables with RSS news feeds
print " Populating the SQLite3 database"
capture_feeds.populate_db()
# Remove duplicate entries
print " Removing duplicate entries from SQLite3 database"
capture_feeds.rm_duplicates()

<|endoftext|>


<commit_before>import subprocess
import tempfile
from pathlib import Path

import pytest
import ruamel.yaml as yaml

from yaml2ncml import build

path = Path(__file__).parent.resolve()

def test_call():
    fname = str(path.joinpath("roms_0.yaml").resolve())
    output = subprocess.check_output(["yaml2ncml", fname])
    with path.joinpath("base_roms_test.ncml").open() as f:
        expected = f.read()
    assert output.decode() == expected

def test_save_file():
    outfile = tempfile.mktemp(suffix=".ncml")
    fname = str(path.joinpath("roms_0.yaml").resolve())
    subprocess.call(["yaml2ncml", fname, f"--output={outfile}"])
    with path.joinpath("base_roms_test.ncml").open() as f:
        expected = f.read()
    with open(outfile) as f:
        output = f.read()
    assert output == expected

@pytest.fixture
def load_ymal(fname=path.joinpath("roms_1.yaml")):
    with open(fname) as stream:
        yield yaml.load(stream, Loader=yaml.RoundTripLoader)

def test_bad_yaml(load_ymal):
    with pytest.raises(ValueError):
        build(load_ymal)
<commit_msg>compared stripped out outputs<commit_after>import subprocess
import tempfile
from pathlib import Path

import pytest
import ruamel.yaml as yaml

from yaml2ncml import build

path = Path(__file__).parent.resolve()

def test_call():
    fname = str(path.joinpath("roms_0.yaml"))
    output = subprocess.check_output(["yaml2ncml", fname]).decode()
    output = [line.strip() for line in output.splitlines()]
    with path.joinpath("base_roms_test.ncml").open() as f:
        expected = [line.strip() for line in f.read().splitlines()]
    assert output == expected

def test_save_file():
    outfile = tempfile.mktemp(suffix=".ncml")
    fname = str(path.joinpath("roms_0.yaml"))
    subprocess.call(["yaml2ncml", fname, f"--output={outfile}"])
    with path.joinpath("base_roms_test.ncml").open() as f:
        expected = f.read()
    with open(outfile) as f:
        output = f.read()
    assert output == expected

@pytest.fixture
def load_ymal(fname=path.joinpath("roms_1.yaml")):
    with open(fname) as stream:
        yield yaml.load(stream, Loader=yaml.RoundTripLoader)

def test_bad_yaml(load_ymal):
    with pytest.raises(ValueError):
        build(load_ymal)
<|endoftext|>


<commit_before>import demowlcutils
from demowlcutils import ppxml, WLC_login
from pprint import pprint as pp
from lxml.builder import E
from lxml import etree
from jinja2 import Template

wlc = WLC_login()
rpc = wlc.RpcMaker('set')

# for this example we'll set an example site location of 'SVL' for all converted APs and
# assume that we are putting all site radios into the 'default' radio profile
site = 'SVL'
radioprofile = 'default'

# create a jinja2 template for a new AP
dap_j2 = Template(u"""
  <DAP apnum="{{ apnum }}" fingerprint="{{ fp }}" model="{{ model }}" name="{{ name }}"
      port="{{ port }}" serial-id="{{ serial }}" type="NG">
    <AP-BOOTCONFIG boot-image=""/>
    <AP-RADIO-TABLE>
      <AP-RADIO antenna-mode="DUAL-BAND-3SS" antennatype="INTERNAL" auto-config="YES"
          channel="6" designation="INDOOR" enable="YES" external-antennas="0"
          force-rebalance="NO" load-balance-enable="YES" load-balance-group=""
          max-tuned-power="default" min-tx-rate="" slot="1" tx-power="21" type="NG">
        <RADIO-PROFILE-REF name="{{ radio1profile }}"/>
      </AP-RADIO>
      <AP-RADIO antenna-mode="DUAL-BAND-3SS" antennatype="INTERNAL" auto-config="YES"
        channel="36" designation="INDOOR" enable="YES" external-antennas="0" force-rebalance="NO" load-balance-enable="YES" load-balance-group="" max-tuned-power="default" min-tx-rate="" slot="2" tx-power="11" type="NA">
        <RADIO-PROFILE-REF name="{{ radio2profile }}"/>
      </AP-RADIO>
    </AP-RADIO-TABLE>
    <AP-ETHERNET-TABLE/>
    <APINFO>
      <APCONTACT/>
      <APLOCATION/>
      <APDESCRIPTION/>
    </APINFO>
    <VLAN-PROFILE-REF name=""/>
  </DAP>
""")

# begin with a list of Auto APs from the announce status table
announce_table = wlc.rpc.get_stat_dap_announce_status_table()

# Auto APs have a special status, use this to identify our candidate APs
auto_aps = announce_table.findall(".//DAP-ANNOUNCE-STATUS[@status='AUTO']")

for ap in auto_aps:
    data = {}
    data.update(ap.attrib)

    rpc.data = E('DAP-TABLE')

    # load and customize the template for this AP
    rpc.data.append(etree.XML(dap_j2.render( radio1profile=radioprofile,
        radio2profile=radioprofile,
        serial=data['serial-id'],
        name=site+data['dapnum'],
        apnum=data['dapnum'],
        model=data['model'],
        fp=data['fingerprint'],
        port=str(int(data['dapnum'])+2048))))

    print('Converting Auto AP: %s Site Name: %s' % (data['dapnum'], site+data['dapnum']))

    # execute the config operation
    r = rpc()

    # reboot the ap here, it should help speed up the process, but probably isn't
    # strictly necessary
    # XXX - build a helper fn for rebooting

# we've finished the conversion, now save the config
wlc.rpc.act_write_configuration()

<commit_msg>updates<commit_after>import demowlcutils
from demowlcutils import ppxml, WLC_login
from pprint import pprint as pp
from lxml.builder import E
from lxml import etree
from jinja2 import Template

wlc = WLC_login()
rpc = wlc.RpcMaker('set')

# for this example we'll set an example site location of 'SVL' for all converted APs and
# assume that we are putting all site radios into the 'default' radio profile
site = 'SVL'
radioprofile = 'default'

# create a jinja2 template for a new AP
dap_j2 = Template(u"""
  <DAP apnum="{{ apnum }}" fingerprint="{{ fp }}" model="{{ model }}" name="{{ name }}"
      port="{{ port }}" serial-id="{{ serial }}" type="NG">
    <AP-BOOTCONFIG boot-image=""/>
    <AP-RADIO-TABLE>
      <AP-RADIO antenna-mode="DUAL-BAND-3SS" antennatype="INTERNAL" auto-config="YES"
          channel="6" designation="INDOOR" enable="YES" external-antennas="0"
          force-rebalance="NO" load-balance-enable="YES" load-balance-group=""
          max-tuned-power="default" min-tx-rate="" slot="1" tx-power="21" type="NG">
        <RADIO-PROFILE-REF name="{{ radio1profile }}"/>
      </AP-RADIO>
      <AP-RADIO antenna-mode="DUAL-BAND-3SS" antennatype="INTERNAL" auto-config="YES"
        channel="36" designation="INDOOR" enable="YES" external-antennas="0"
        force-rebalance="NO" load-balance-enable="YES" load-balance-group=""
        max-tuned-power="default" min-tx-rate="" slot="2" tx-power="11" type="NA">
        <RADIO-PROFILE-REF name="{{ radio2profile }}"/>
      </AP-RADIO>
    </AP-RADIO-TABLE>
    <AP-ETHERNET-TABLE/>
    <APINFO>
      <APCONTACT/>
      <APLOCATION/>
      <APDESCRIPTION/>
    </APINFO>
    <VLAN-PROFILE-REF name=""/>
  </DAP>
""")

# begin with a list of Auto APs from the announce status table
announce_table = wlc.rpc.get_stat_dap_announce_status_table()

# Auto APs have a special status, use this to identify our candidate APs
auto_aps = announce_table.findall(".//DAP-ANNOUNCE-STATUS[@status='AUTO']")

for ap in auto_aps:
    data = {}
    data.update(ap.attrib)

    rpc.data = E('DAP-TABLE')

    # load and customize the template for this AP
    rpc.data.append(etree.XML(dap_j2.render( radio1profile=radioprofile,
        radio2profile=radioprofile,
        serial=data['serial-id'],
        name=site+data['dapnum'],
        apnum=data['dapnum'],
        model=data['model'],
        fp=data['fingerprint'],
        port=str(int(data['dapnum'])+2048))))

    print('Converting Auto AP: %s Site Name: %s' % (data['dapnum'], site+data['dapnum']))

    # execute the config operation
    r = rpc()

    # reboot the ap here, it should help speed up the process, but probably isn't
    # strictly necessary
    # XXX - build a helper fn for rebooting

# we've finished the conversion, now save the config
wlc.rpc.act_write_configuration()

<|endoftext|>


<commit_before># coding=utf-8
from __future__ import absolute_import, unicode_literals

from django.db import models

from tests.testapp.constants import ModelState
from tximmutability.models import ImmutableModel
from tximmutability.rule import ImmutabilityRule

class AbstractImmutableModel(ImmutableModel):
    name = models.CharField(null=False, max_length=50, default='Immutable Model')
    state = models.CharField(max_length=50, default=ModelState.IMMUTABLE_STATE)

    @staticmethod
    def get_immutability_rule(**kwargs):
        field = kwargs.pop('field', None)
        field_name = 'state' if field is None else field
        return ImmutabilityRule(field_name, mutable_values=(ModelState.MUTABLE_STATE,), **kwargs)

    class Meta:
        abstract = True

class BaseImmutableModel(AbstractImmutableModel):
    description = models.CharField(null=True, max_length=250)
    immutability_rules = (
        AbstractImmutableModel.get_immutability_rule(mutable_fields=('description',),
                                                     error_message='No se puede {action}, estado es inmutable'),
    )

class ImmutableModelAllowDelete(AbstractImmutableModel):
    immutability_rules = (
        AbstractImmutableModel.get_immutability_rule(allow_delete=True),
    )

class ImmutableModelAllowUpdate(AbstractImmutableModel):
    immutability_rules = (
        AbstractImmutableModel.get_immutability_rule(allow_update=True),
    )

class ImmutableRelationModel(AbstractImmutableModel):
    related_field = models.ForeignKey('BaseImmutableModel', null=True, blank=True)
    immutability_rules = (
        AbstractImmutableModel.get_immutability_rule(field='related_field__state'),
    )

class ImmutableMultiForwardRelModel(AbstractImmutableModel):
    related_field = models.ForeignKey('ModelWithRelation', null=True, blank=True)
    immutability_rules = (
        AbstractImmutableModel.get_immutability_rule(field='related_field__related_field__state'),
    )

class ImmutableReverseRelationModel(AbstractImmutableModel):
    related_field = models.ForeignKey('ImmutableMultiReverseRelModel', null=True, blank=True)
    immutability_rules = (
        AbstractImmutableModel.get_immutability_rule(field='modelwithrelation__state'),
    )

class ImmutableMultiReverseRelModel(AbstractImmutableModel):
    immutability_rules = (
        AbstractImmutableModel.get_immutability_rule(field='immutablereverserelationmodel__'
                                                           'modelwithrelation__state'),
    )

class ImmutableMultiMixRelModel(AbstractImmutableModel):
    related_field = models.ForeignKey('BaseImmutableModel', null=True, blank=True)
    immutability_rules = (
        AbstractImmutableModel.get_immutability_rule(field='related_field__immutablerelationmodel__state'),
        AbstractImmutableModel.get_immutability_rule(field='modelwithrelation__related_field__state')
    )

class ModelWithRelation(AbstractImmutableModel):
    related_field = models.ForeignKey('ImmutableReverseRelationModel', null=True, blank=True)
    related_field2 = models.ForeignKey('ImmutableMultiMixRelModel', null=True, blank=True)

<commit_msg>adapt tests classname renamed 'MutabilityRule'<commit_after># coding=utf-8
from __future__ import absolute_import, unicode_literals

from django.db import models

from tests.testapp.constants import ModelState
from tximmutability.models import ImmutableModel
from tximmutability.rule import MutabilityRule

class AbstractImmutableModel(ImmutableModel):
    name = models.CharField(null=False, max_length=50, default='Immutable Model')
    state = models.CharField(max_length=50, default=ModelState.IMMUTABLE_STATE)

    @staticmethod
    def get_immutability_rule(**kwargs):
        field = kwargs.pop('field', None)
        field_name = 'state' if field is None else field
        return MutabilityRule(field_name, mutable_values=(ModelState.MUTABLE_STATE,), **kwargs)

    class Meta:
        abstract = True

class BaseImmutableModel(AbstractImmutableModel):
    description = models.CharField(null=True, max_length=250)
    immutability_rules = (
        AbstractImmutableModel.get_immutability_rule(mutable_fields=('description',),
                                                     error_message='No se puede {action}, estado es inmutable'),
    )

class ImmutableModelAllowDelete(AbstractImmutableModel):
    immutability_rules = (
        AbstractImmutableModel.get_immutability_rule(allow_delete=True),
    )

class ImmutableModelAllowUpdate(AbstractImmutableModel):
    immutability_rules = (
        AbstractImmutableModel.get_immutability_rule(allow_update=True),
    )

class ImmutableRelationModel(AbstractImmutableModel):
    related_field = models.ForeignKey('BaseImmutableModel', null=True, blank=True)
    immutability_rules = (
        AbstractImmutableModel.get_immutability_rule(field='related_field__state'),
    )

class ImmutableMultiForwardRelModel(AbstractImmutableModel):
    related_field = models.ForeignKey('ModelWithRelation', null=True, blank=True)
    immutability_rules = (
        AbstractImmutableModel.get_immutability_rule(field='related_field__related_field__state'),
    )

class ImmutableReverseRelationModel(AbstractImmutableModel):
    related_field = models.ForeignKey('ImmutableMultiReverseRelModel', null=True, blank=True)
    immutability_rules = (
        AbstractImmutableModel.get_immutability_rule(field='modelwithrelation__state'),
    )

class ImmutableMultiReverseRelModel(AbstractImmutableModel):
    immutability_rules = (
        AbstractImmutableModel.get_immutability_rule(field='immutablereverserelationmodel__'
                                                           'modelwithrelation__state'),
    )

class ImmutableMultiMixRelModel(AbstractImmutableModel):
    related_field = models.ForeignKey('BaseImmutableModel', null=True, blank=True)
    immutability_rules = (
        AbstractImmutableModel.get_immutability_rule(field='related_field__immutablerelationmodel__state'),
        AbstractImmutableModel.get_immutability_rule(field='modelwithrelation__related_field__state')
    )

class ModelWithRelation(AbstractImmutableModel):
    related_field = models.ForeignKey('ImmutableReverseRelationModel', null=True, blank=True)
    related_field2 = models.ForeignKey('ImmutableMultiMixRelModel', null=True, blank=True)

<|endoftext|>


<commit_before>#!/usr/bin/env python
import sys

from EPPs.common import StepEPP

#Script for performing autoplacement of samples. If 1 input and 1 output then 1:1 placement. If multiple input plates then
#takes all samples from each plate before next plate Loops through all inputs and assigns them to the next available space
#by column-row in the output plate
class AutoplacementQPCR384(StepEPP):
    _use_load_config = False  # prevent the loading of the config

    def __init__(self, argv=None):
        super().__init__(argv)

    def _run(self):

        all_inputs = self.process.all_inputs(unique=True)
        if len(all_inputs) > 31:
            print("Maximum number of input samples and standards is 31. %s inputs present in step" % (len(all_inputs)))
            sys.exit(1)

        #loop through the inputs, assemble a nested dicitonary {containers:{input.location:output} this can then be
        #queried in the order container-row-column so the order of the inputs in the Hamilton input file is
        # as efficient as possible.
        input_container_nested_dict={}

        # update of container requires list variable containing the containers, only one container will be present in step
        # because the container has not yet been fully populated then it must be obtained from the step rather than output
        output_container_list = self.process.step.placements.get_selected_containers()

        standards_dict={}
        outputs_dict={}

        for input in all_inputs:
            #obtain outputs for the input that are analytes, assume step is not configured to allow replicates
            #so will always work with output[0]
            outputs = self.process.outputs_per_input(input.id, ResultFile=True)

            #assemble dict of standards and dictionary of output artifacts
            if input.name.split(" ") == "QSTD":
                for output in outputs:
                    standards_dict[input.name]=output
            else:
                for output in outputs:
                    outputs_dict[input.location[1]]=output

        #assemble the plate layout of the output plate as a list
        plate_layout_columns = ["1", "2", "3","4","5","6"]
        plate_layout_rows = ["A", "B", "C", "D", "E", "F", "G", "H","I","J","K","L","M","N","O","P","Q","R",
                             "S","T","U","V","W","X","Y","Z"]
        plate_layout = []

        for column in plate_layout_columns:
            for row in plate_layout_rows:
                plate_layout.append(row + ":" + column)
        well_counter=0
        #create the output_placement_list to be used by th set_placements function
        output_placement_list=[]

        #loop through sorted standards dict and add to output_placement_list

        for key in standards_dict.keys().sort:
            output_placement_list.append((standards_dict[key],(output_container_list[0],plate_layout[well_counter])))
            if plate_layout[wellcounter][1:] == 5:
                well_counter-=62
            else:
                well_counter+=32

        #reset well counter to start for samples
        well_counter=2

        #loop through the outputs_dict in row-column order and assign them the correct well location in
        # the output_placement_list
        for column in columns:
            for row in rows:
                #build the list of tuples required for the placement function
                output_placement_list.append((outputs_dict[row+":"+column],(output_container_list[0],plate_layout[well_counter])))
                if plate_layout[wellcounter][0:1] == "P":
                    well_counter +=18
                if plate_layout[wellcounter] == "P5":
                    well_counter-=33
                if plate_layout[wellcounter] == "06":
                    well_counter-=35
                else:
                    well_counter += 2

        #push the output locations to the LIMS
        self.process.step.set_placements(output_container_list, output_placement)

if __name__ == '__main__':
    AutoplacementQPCR384().run()
<commit_msg>autoplacement_24_in_96 unused code removed new script for autoplacement in QPCR 384 well plate added<commit_after>#!/usr/bin/env python
import sys

from EPPs.common import StepEPP

#Script for performing autoplacement of samples. If 1 input and 1 output then 1:1 placement. If multiple input plates then
#takes all samples from each plate before next plate Loops through all inputs and assigns them to the next available space
#by column-row in the output plate
class AutoplacementQPCR384(StepEPP):
    _use_load_config = False  # prevent the loading of the config

    def __init__(self, argv=None):
        super().__init__(argv)

    def _run(self):

        all_inputs = self.process.all_inputs(unique=True)
        if len(all_inputs) > 31:
            print("Maximum number of input samples and standards is 31. %s inputs present in step" % (len(all_inputs)))
            sys.exit(1)

        #loop through the inputs, assemble a nested dicitonary {containers:{input.location:output} this can then be
        #queried in the order container-row-column so the order of the inputs in the Hamilton input file is
        # as efficient as possible.
        input_container_nested_dict={}

        # update of container requires list variable containing the containers, only one container will be present in step
        # because the container has not yet been fully populated then it must be obtained from the step rather than output
        output_container_list = self.process.step.placements.get_selected_containers()

        standards_dict={}
        outputs_dict={}

        for input in all_inputs:

            #obtain outputs for the input that are analytes, assume step is not configured to allow replicates
            #so will always work with output[0]
            outputs = self.process.outputs_per_input(input.id, ResultFile=True)

            #assemble dict of standards and dictionary of output artifacts
            # using numbers 0-2 to differentiate between the three replicate outputs for each input/standard
            output_counter=0
            if input.name.split(" ")[0] == "QSTD":

                for output in outputs:

                    standards_dict[str(input.name)+str(output_counter)] = output
                    output_counter+=1
            else:
                for output in outputs:

                    outputs_dict[str(output_counter)+input.location[1]] = output
                    output_counter+=1

        #assemble the plate layout of the output plate as a list
        plate_layout_columns = ["1", "2", "3","4","5","6"]
        plate_layout_rows = ["A", "B", "C", "D", "E", "F", "G", "H","I","J","K","L","M","N","O","P"]
        plate_layout = []

        for column in plate_layout_columns:
            for row in plate_layout_rows:
                plate_layout.append(row + ":" + column)
        well_counter=0
        #create the output_placement_list to be used by th set_placements function

        output_placement_list=[]

        #loop through sorted standards dict and add to output_placement_list
        for key in sorted(standards_dict.keys()):

            output_placement_list.append((standards_dict[key],(output_container_list[0],plate_layout[well_counter])))

            if plate_layout[well_counter][1:] == ":5":
                well_counter-=62
            else:
                well_counter+=32

        #reset well counter to start for samples
        well_counter=1

        #need replicate counter to help pull all outputs from dict in order of replicates then row-column order
        replicate_counter=0
        #loop through the outputs_dict in replicate and row-column order and assign them the correct well location in
        # the output_placement_list.
        while replicate_counter <3:
            for column in plate_layout_columns:
                for row in plate_layout_rows:
                        #build the list of tuples required for the placement function. Checking that key exists in dict.
                        if str(replicate_counter)+row+":"+column in outputs_dict.keys():
                            output_placement_list.append((outputs_dict[str(replicate_counter)+row+":"+column],(output_container_list[0],plate_layout[well_counter])))
                            if plate_layout[well_counter] == "P:5":
                                well_counter-=63
                            elif plate_layout[well_counter][0] == "P":
                                well_counter +=18
                            elif plate_layout[well_counter] == "O:6":
                                well_counter-=77
                            elif plate_layout[well_counter][0] == "O":
                                well_counter+=18
                            else:
                                well_counter += 2
            replicate_counter+=1

        #push the output locations to the LIMS
        self.process.step.set_placements(output_container_list, output_placement_list)

if __name__ == '__main__':
    AutoplacementQPCR384().run()
<|endoftext|>


<commit_before>import random
import threading
import socket
import sys

# format: message id|message sender id|message channel id|message
# ids are 10 digits, message is limited to 256 characters
# sample: 0000000000|0000000000|0000000000|Hello world

class Client:
    def __init__(self):
        self.id = None
        self.currentChannel = None

if __name__ == "__main__":
    sys.exit(0)
    # see CL2, will port here soon
<commit_msg>Added import and commented<commit_after>import random
import threading
import socket
import sys
import select

# format: message id|message sender id|message channel id|message
# ids are 10 digits, message is limited to 256 characters
# sample: 0000000000|0000000000|0000000000|Hello world

class Client:
    def __init__(self):
        self.id = None
        self.currentChannel = None

    # def chat_client(self):
    #
    #

if __name__ == "__main__":
    sys.exit(0)
    # see CL2, will port here soon
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
'''
    :codeauthor: :email:`Mike Place <mp@saltstack.com`

    Tests to ensure that the file permissions are set correctly when
    importing from the git repo.
'''

# Import python libs
import os
import stat
import pprint

# Import salt testing libs
from salttesting import TestCase
from salttesting.helpers import ensure_in_syspath

ensure_in_syspath('..')

from integration import CODE_DIR

EXEMPT_DIRS = []
EXEMPT_FILES = [
    'debian/rules',
    'doc/.scripts/compile-translation-catalogs',
    'doc/.scripts/download-translation-catalog',
    'doc/.scripts/setup-transifex-config',
    'doc/.scripts/update-transifex-source-translations',
    'pkg/arch/Makefile',
    'pkg/arch/PKGBUILD',
    'pkg/arch/PKGBUILD-git',
    'pkg/arch/PKGBUILD-local',
    'pkg/arch/git/PKGBUILD',
    'pkg/rpm/build.py',
    'pkg/rpm/salt-master',
    'pkg/rpm/salt-minion',
    'pkg/rpm/salt-syndic',
    'pkg/shar/build_shar.sh'
    'pkg/smartos/esky/install.sh',
    'salt/templates/git/ssh-id-wrapper',
    'scripts/salt',
    'scripts/salt-call',
    'scripts/salt-cloud',
    'scripts/salt-cp',
    'scripts/salt-key',
    'scripts/salt-master',
    'scripts/salt-minion',
    'scripts/salt-run',
    'scripts/salt-ssh',
    'scripts/salt-syndic',
    'setup.py',
    'tests/integration/mockbin/su',
    'tests/runtests.py',
    'tests/saltsh.py',
]

IGNORE_PATHS = [
    '.git',
    '.wti',
    'build',
    'dist',
    'salt.egg-info',
    '.ropeproject',
]

class GitPermTestCase(TestCase):
    def test_perms(self):
        suspect_entries = []
        for root, dirnames, filenames in os.walk(CODE_DIR, topdown=True):
            for dirname in dirnames:
                entry = os.path.relpath(
                    os.path.join(root, dirname), CODE_DIR
                )
                if entry in IGNORE_PATHS:
                    continue

                skip_entry = False
                for ignore_path in IGNORE_PATHS:
                    if entry.startswith(ignore_path):
                        skip_entry = True
                        break

                if skip_entry:
                    continue

                fn_mode = stat.S_IMODE(os.stat(entry).st_mode)
                if fn_mode != 493 and entry not in EXEMPT_DIRS:  # In octal! 493 == 0755
                    suspect_entries.append(entry)

            for filename in filenames:
                entry = os.path.relpath(
                    os.path.join(root, filename), CODE_DIR
                )
                if entry in IGNORE_PATHS:
                    continue

                skip_entry = False
                for ignore_path in IGNORE_PATHS:
                    if entry.startswith(ignore_path):
                        skip_entry = True
                        break

                if skip_entry:
                    continue

                fn_mode = stat.S_IMODE(os.stat(entry).st_mode)
                if fn_mode != 420 and entry not in EXEMPT_FILES:  # In octal! 420 == 0644
                    suspect_entries.append(entry)

        try:
            self.assertEqual(suspect_entries, [])
        except AssertionError:
            self.fail(
                'Found file(s) with incorrect permissions:\n{0}'.format(
                    pprint.pformat(sorted(suspect_entries))
                )
            )

if __name__ == '__main__':
    from integration import run_tests
    run_tests(GitPermTestCase, needs_daemon=False)
<commit_msg>Add missing comma.<commit_after># -*- coding: utf-8 -*-
'''
    :codeauthor: :email:`Mike Place <mp@saltstack.com`

    Tests to ensure that the file permissions are set correctly when
    importing from the git repo.
'''

# Import python libs
import os
import stat
import pprint

# Import salt testing libs
from salttesting import TestCase
from salttesting.helpers import ensure_in_syspath

ensure_in_syspath('..')

from integration import CODE_DIR

EXEMPT_DIRS = []
EXEMPT_FILES = [
    'debian/rules',
    'doc/.scripts/compile-translation-catalogs',
    'doc/.scripts/download-translation-catalog',
    'doc/.scripts/setup-transifex-config',
    'doc/.scripts/update-transifex-source-translations',
    'pkg/arch/Makefile',
    'pkg/arch/PKGBUILD',
    'pkg/arch/PKGBUILD-git',
    'pkg/arch/PKGBUILD-local',
    'pkg/arch/git/PKGBUILD',
    'pkg/rpm/build.py',
    'pkg/rpm/salt-master',
    'pkg/rpm/salt-minion',
    'pkg/rpm/salt-syndic',
    'pkg/shar/build_shar.sh',
    'pkg/smartos/esky/install.sh',
    'salt/templates/git/ssh-id-wrapper',
    'scripts/salt',
    'scripts/salt-call',
    'scripts/salt-cloud',
    'scripts/salt-cp',
    'scripts/salt-key',
    'scripts/salt-master',
    'scripts/salt-minion',
    'scripts/salt-run',
    'scripts/salt-ssh',
    'scripts/salt-syndic',
    'setup.py',
    'tests/integration/mockbin/su',
    'tests/runtests.py',
    'tests/saltsh.py',
]

IGNORE_PATHS = [
    '.git',
    '.wti',
    'build',
    'dist',
    'salt.egg-info',
    '.ropeproject',
]

class GitPermTestCase(TestCase):
    def test_perms(self):
        suspect_entries = []
        for root, dirnames, filenames in os.walk(CODE_DIR, topdown=True):
            for dirname in dirnames:
                entry = os.path.relpath(
                    os.path.join(root, dirname), CODE_DIR
                )
                if entry in IGNORE_PATHS:
                    continue

                skip_entry = False
                for ignore_path in IGNORE_PATHS:
                    if entry.startswith(ignore_path):
                        skip_entry = True
                        break

                if skip_entry:
                    continue

                fn_mode = stat.S_IMODE(os.stat(entry).st_mode)
                if fn_mode != 493 and entry not in EXEMPT_DIRS:  # In octal! 493 == 0755
                    suspect_entries.append(entry)

            for filename in filenames:
                entry = os.path.relpath(
                    os.path.join(root, filename), CODE_DIR
                )
                if entry in IGNORE_PATHS:
                    continue

                skip_entry = False
                for ignore_path in IGNORE_PATHS:
                    if entry.startswith(ignore_path):
                        skip_entry = True
                        break

                if skip_entry:
                    continue

                fn_mode = stat.S_IMODE(os.stat(entry).st_mode)
                if fn_mode != 420 and entry not in EXEMPT_FILES:  # In octal! 420 == 0644
                    suspect_entries.append(entry)

        try:
            self.assertEqual(suspect_entries, [])
        except AssertionError:
            self.fail(
                'Found file(s) with incorrect permissions:\n{0}'.format(
                    pprint.pformat(sorted(suspect_entries))
                )
            )

if __name__ == '__main__':
    from integration import run_tests
    run_tests(GitPermTestCase, needs_daemon=False)
<|endoftext|>


<commit_before>import json
from lxml import etree

from urllib2 import urlopen

from pymarc import marcxml

from django.conf import settings

from ui.templatetags.launchpad_extras import clean_isbn

def get_bib_data(num, num_type):
    for api in settings.API_LIST:
        bib = globals()[api['name']](num=num, num_type=num_type,
                                     url=api.get('url', ''),
                                     key=api.get('key', ''))
        if bib:
            return bib
    return None

def googlebooks(num, num_type, url, key):
    url = url % (num_type, num)
    try:
        response = urlopen(url)
        json_data = json.loads(response.read())
    except:
        return None
    if json_data['totalItems'] == 0 or len(json_data.get('items', [])) == 0:
        return None
    item = json_data['items'][0]
    if not item['volumeInfo']:
        return None
    volinfo = item['volumeInfo']
    bib = {}
    bib[num_type.upper()] = num
    bib['TITLE'] = volinfo.get('title', '')
    bib['TITLE_ALL'] = bib['TITLE']
    bib['SUBTITLE'] = volinfo.get('subtitle', '')
    if bib['SUBTITLE']:
    	bib['TITLE_ALL'] = '%s %s %s' % (bib['TITLE'], ' / ', bib['SUBTITLE'])
    bib['AUTHORS'] = volinfo.get('authors', '')
    bib['PUBLISHER'] = volinfo.get('publisher', '')
    if 'industryIdentifiers' in volinfo:
        std_nums = set()
        std_nums.update([num, ])
        for std_num in volinfo['industryIdentifiers']:
            if num_type.upper() in std_num['type']:
                std_nums.update([std_num['identifier']])
        bib['DISPLAY_%s_LIST' % num_type.upper()] = list(std_nums)
    bib['PUBLISHER_DATE'] = volinfo.get('publishedDate', '')
    bib['EDITION'] = '%s %s' % (bib['PUBLISHER'], bib['PUBLISHER_DATE'])
    bib['PAGES'] = volinfo.get('pageCount', '')
    if bib['PAGES']:
	bib['EDITION'] += '%s %s' % (" Pages: ", bib['PAGES'])
    bib['GOOGLE_MESSAGE'] = 'Information provided below was retrieved from Google Books.'
    bib['GOOGLE_REVIEW'] = volinfo.get('description', '')
    bib['GOOGLE_LINK'] = volinfo.get('infoLink', '')
    return bib

def worldcat(num, num_type, url, key):
    url = url % (num, key)
    try:
        records = marcxml.parse_xml_to_array(urlopen(url))
        if not records:
            return None
        record = records[0]
    except:
        return None
    bib = {}
    bib[num_type.upper()] = num
    bib['TITLE'] = record.uniformtitle()
    if not bib['TITLE']:
        bib['TITLE'] = record.title() if record.title() else ''
    bib['TITLE_ALL'] = bib['TITLE']
    bib['AUTHORS'] = [entry.format_field() for entry in record.addedentries()]
    bib['AUTHOR'] = record.author() if record.author() else ''
    if bib['AUTHOR']:
        bib['AUTHORS'].insert(0, bib['AUTHOR'])
    bib['PUBLISHER'] = record.publisher() if record.publisher() else ''
    bib['PUBLISHER_DATE'] = record.pubyear() if record.pubyear() else ''
    bib['IMPRINT'] = '%s %s' % (bib['PUBLISHER'], bib['PUBLISHER_DATE'])
    bib['BIB_FORMAT'] = 'as' if num_type == 'issn' else 'am'
    return bib

def openlibrary(num, num_type, force=False, as_holding=True):
    # ensure we're dealing with a proper identifier type and value
    try:
        if num_type.upper() not in ('ISBN', 'OCLC', 'LCCN', 'OLID'):
            raise
        if num_type.upper() == 'ISBN':
            num = clean_isbn(num)
            if len(num) not in (10, 13):
                raise
    except:
        return {}
    params = '%s:%s' % (num_type, num)
    url = 'http://openlibrary.org/api/books?format=json&jscmd=data' + \
        '&bibkeys=%s' % params
    try:
        response = urlopen(url)
        json_data = json.loads(response.read())
        book = json_data.get(params, {})
        for ebook in book.get('ebooks', []):
            if ebook.get('availability', '') == 'full':
                return make_openlib_holding(book) if as_holding else book
        if not force:
            return {}
        return make_openlib_holding(book) if as_holding else book
    except:
        return {}

def make_openlib_holding(book):
    holding = {
        'LIBRARY_NAME': 'IA',
        'LOCATION_NAME': 'OL',
        'LOCATION_DISPLAY_NAME': 'OL: Open Library',
        'MFHD_DATA': {
            "marc866list": [],
            "marc856list": [
                {"3": "",
                 "z": "",
                 "u": ""}],
            "marc852": ""
        },
        'MFHD_ID': None,
        'ITEMS': [
            {'ITEM_ENUM': None,
             'ITEM_STATUS': None,
             'TEMPLOCATION': None,
             "ITEM_STATUS_DESC": None,
             "ITEM_ID": 0,
             "PERMLOCATION": None,
             "LIBRARY_FULL_NAME": "Internet Archive",
             "ELIGIBLE": False,
             "TRIMMED_LOCATION_DISPLAY_NAME": "Open Library",
             "CHRON": None,
             "DISPLAY_CALL_NO": None,
             "BIB_ID": None},
        ],
        'ELIGIBLE': False,
        'LIBRARY_FULL_NAME': 'Internet Archive',
        'TRIMMED_LOCATION_DISPLAY_NAME': 'Open Library',
        'ELECTRONIC_DATA': {},
        'LIBRARY_HAS': [],
        'LOCATION_ID': None,
        'AVAILABILITY': {},
        'DISPLAY_CALL_NO': None,
        'BIB_ID': None,
    }
    if book.keys():
        holding['ITEMS'][0]['DISPLAY_CALL_NO'] = \
            book.get('identifiers', {}).get('openlibrary', [])[0]
        holding['MFHD_DATA']['marc856list'][0]['u'] = book.get('url', '')
    return holding

def hathitrust(num, num_type):
    # ensure we're dealing with a proper identifier type and value
    try:
        if num_type.upper() not in ('ISBN', 'OCLC', 'LCCN', 'OLID'):
            raise
        if num_type.upper() == 'ISBN':
            num = clean_isbn(num)
            if len(num) not in (10, 13):
                raise
    except:
        return {}
    params = '%s/%s' % (num_type, num)
    url = 'http://catalog.hathitrust.org/api/volumes/brief/%s.json' % params
    try:
        response = urlopen(url)
        json_data = json.loads(response.read())
        for item in json_data.get('items', []):
            if item.get('usRightsString', '') == 'Full view':
                return make_hathi_holding(item.get('itemURL', ''),
                                          item.get('fromRecord', ''))
    except:
        return {}

def make_hathi_holding(url, fromRecord):
    # use library name IA
    # add dummy elements to conform with holding model
    holding = {
        'LIBRARY_NAME': 'IA',
        'LOCATION_NAME': 'HT',
        'LOCATION_DISPLAY_NAME': 'HT: Hathi Trust',
        'MFHD_DATA': {
            "marc866list": [],
            "marc856list": [
                {"3": "",
                 "z": "",
                 "u": url}],
            "marc852": ""
        },
        'MFHD_ID': None,
        'ITEMS': [
            {'ITEM_ENUM': None,
             'ITEM_STATUS': None,
             'TEMPLOCATION': None,
             "ITEM_STATUS_DESC": None,
             "ITEM_ID": 0,
             "PERMLOCATION": None,
             "LIBRARY_FULL_NAME": "Hathi Trust",
             "ELIGIBLE": False,
             "TRIMMED_LOCATION_DISPLAY_NAME": "Hathi Trust Digital Library",
             "CHRON": None,
             "DISPLAY_CALL_NO": fromRecord,
             "BIB_ID": None},
        ],
        'ELIGIBLE': False,
        'LIBRARY_FULL_NAME': 'Hathi Trust',
        'TRIMMED_LOCATION_DISPLAY_NAME': 'Hathi Trust Digital Library',
        'ELECTRONIC_DATA': {},
        'LIBRARY_HAS': [],
        'LOCATION_ID': None,
        'AVAILABILITY': {},
        'DISPLAY_CALL_NO': 'Record ' + fromRecord,
        'BIB_ID': None,
    }
    return holding

def make_google_holding(bib):
    # use library name IA
    # add dummy elements to conform with holding model
    holding = {
        'LIBRARY_NAME': 'IA',
        'LOCATION_NAME': 'HT',
        'LOCATION_DISPLAY_NAME': 'HT: Hathi Trust',
        'MFHD_DATA': {
            "marc866list": [],
            "marc856list": [
                {"3": "",
                 "z": "",
                 "u": url}],
            "marc852": ""
        },
        'MFHD_ID': None,
        'ITEMS': [
            {'ITEM_ENUM': None,
             'ITEM_STATUS': None,
             'TEMPLOCATION': None,
             "ITEM_STATUS_DESC": None,
             "ITEM_ID": 0,
             "PERMLOCATION": None,
             "LIBRARY_FULL_NAME": "Google Books",
             "ELIGIBLE": False,
             "TRIMMED_LOCATION_DISPLAY_NAME": "Google Books",
             "CHRON": None,
             "DISPLAY_CALL_NO": None,
             "BIB_ID": None},
        ],
        'ELIGIBLE': False,
        'LIBRARY_FULL_NAME': 'Google Books',
        'TRIMMED_LOCATION_DISPLAY_NAME': 'Google Books',
        'ELECTRONIC_DATA': {},
        'LIBRARY_HAS': [],
        'LOCATION_ID': None,
        'AVAILABILITY': {},
        'DISPLAY_CALL_NO': None,
        'BIB_ID': None,
    }
    return holding

def sersol360link(num, num_type, count=0):
    try:
        count += 1
        url = '%s&%s=%s' % (settings.SER_SOL_API_URL, num_type, num)
        response = urlopen(url)
        tree = etree.fromstring(response.read())
    except:
        return []
    output = []
    ns = 'http://xml.serialssolutions.com/ns/openurl/v1.0'
    openurls = tree.xpath('/sso:openURLResponse/sso:results/sso:result/sso' +
                          ':linkGroups/sso:linkGroup[@type="holding"]',
                          namespaces={'sso': ns})
    if not openurls and count < settings.SER_SOL_API_MAX_ATTEMPTS:
        return sersol360link(num, num_type, count)
    for openurl in openurls:
        dbid = openurl.xpath('sso:holdingData/sso:databaseId',
                             namespaces={'sso': ns})
        if not dbid:
            continue
        dbid = dbid[0]
        if dbid.text != settings.SER_SOL_DBID_TEXT:
            data = {}
            start = openurl.xpath('sso:holdingData/sso:startDate',
                                  namespaces={'sso': ns})
            data['start'] = start[0].text if start else ''
            end = openurl.xpath('sso:holdingData/sso:endDate',
                                namespaces={'sso': ns})
            data['end'] = end[0].text if end else ''
            dbname = openurl.xpath('sso:holdingData/sso:databaseName',
                                   namespaces={'sso': ns})
            data['dbname'] = dbname[0].text if dbname else ''
            source = openurl.xpath('sso:url[@type="source"]',
                                   namespaces={'sso': ns})
            data['source'] = source[0].text if source else ''
            journal = openurl.xpath('sso:url[@type="journal"]',
                                    namespaces={'sso': ns})
            data['journal'] = journal[0].text if journal else ''
            output.append(data)
    return output
<commit_msg>deleted unused method make_google_holding<commit_after>import json
from lxml import etree

from urllib2 import urlopen

from pymarc import marcxml

from django.conf import settings

from ui.templatetags.launchpad_extras import clean_isbn

def get_bib_data(num, num_type):
    for api in settings.API_LIST:
        bib = globals()[api['name']](num=num, num_type=num_type,
                                     url=api.get('url', ''),
                                     key=api.get('key', ''))
        if bib:
            return bib
    return None

def googlebooks(num, num_type, url, key):
    url = url % (num_type, num)
    try:
        response = urlopen(url)
        json_data = json.loads(response.read())
    except:
        return None
    if json_data['totalItems'] == 0 or len(json_data.get('items', [])) == 0:
        return None
    item = json_data['items'][0]
    if not item['volumeInfo']:
        return None
    volinfo = item['volumeInfo']
    bib = {}
    bib[num_type.upper()] = num
    bib['TITLE'] = volinfo.get('title', '')
    bib['TITLE_ALL'] = bib['TITLE']
    bib['SUBTITLE'] = volinfo.get('subtitle', '')
    if bib['SUBTITLE']:
    	bib['TITLE_ALL'] = '%s %s %s' % (bib['TITLE'], ' / ', bib['SUBTITLE'])
    bib['AUTHORS'] = volinfo.get('authors', '')
    bib['PUBLISHER'] = volinfo.get('publisher', '')
    if 'industryIdentifiers' in volinfo:
        std_nums = set()
        std_nums.update([num, ])
        for std_num in volinfo['industryIdentifiers']:
            if num_type.upper() in std_num['type']:
                std_nums.update([std_num['identifier']])
        bib['DISPLAY_%s_LIST' % num_type.upper()] = list(std_nums)
    bib['PUBLISHER_DATE'] = volinfo.get('publishedDate', '')
    bib['EDITION'] = '%s %s' % (bib['PUBLISHER'], bib['PUBLISHER_DATE'])
    bib['PAGES'] = volinfo.get('pageCount', '')
    if bib['PAGES']:
	bib['EDITION'] += '%s %s' % (" Pages: ", bib['PAGES'])
    bib['GOOGLE_MESSAGE'] = 'Information provided below was retrieved from Google Books.'
    bib['GOOGLE_REVIEW'] = volinfo.get('description', '')
    bib['GOOGLE_LINK'] = volinfo.get('infoLink', '')
    return bib

def worldcat(num, num_type, url, key):
    url = url % (num, key)
    try:
        records = marcxml.parse_xml_to_array(urlopen(url))
        if not records:
            return None
        record = records[0]
    except:
        return None
    bib = {}
    bib[num_type.upper()] = num
    bib['TITLE'] = record.uniformtitle()
    if not bib['TITLE']:
        bib['TITLE'] = record.title() if record.title() else ''
    bib['TITLE_ALL'] = bib['TITLE']
    bib['AUTHORS'] = [entry.format_field() for entry in record.addedentries()]
    bib['AUTHOR'] = record.author() if record.author() else ''
    if bib['AUTHOR']:
        bib['AUTHORS'].insert(0, bib['AUTHOR'])
    bib['PUBLISHER'] = record.publisher() if record.publisher() else ''
    bib['PUBLISHER_DATE'] = record.pubyear() if record.pubyear() else ''
    bib['IMPRINT'] = '%s %s' % (bib['PUBLISHER'], bib['PUBLISHER_DATE'])
    bib['BIB_FORMAT'] = 'as' if num_type == 'issn' else 'am'
    return bib

def openlibrary(num, num_type, force=False, as_holding=True):
    # ensure we're dealing with a proper identifier type and value
    try:
        if num_type.upper() not in ('ISBN', 'OCLC', 'LCCN', 'OLID'):
            raise
        if num_type.upper() == 'ISBN':
            num = clean_isbn(num)
            if len(num) not in (10, 13):
                raise
    except:
        return {}
    params = '%s:%s' % (num_type, num)
    url = 'http://openlibrary.org/api/books?format=json&jscmd=data' + \
        '&bibkeys=%s' % params
    try:
        response = urlopen(url)
        json_data = json.loads(response.read())
        book = json_data.get(params, {})
        for ebook in book.get('ebooks', []):
            if ebook.get('availability', '') == 'full':
                return make_openlib_holding(book) if as_holding else book
        if not force:
            return {}
        return make_openlib_holding(book) if as_holding else book
    except:
        return {}

def make_openlib_holding(book):
    holding = {
        'LIBRARY_NAME': 'IA',
        'LOCATION_NAME': 'OL',
        'LOCATION_DISPLAY_NAME': 'OL: Open Library',
        'MFHD_DATA': {
            "marc866list": [],
            "marc856list": [
                {"3": "",
                 "z": "",
                 "u": ""}],
            "marc852": ""
        },
        'MFHD_ID': None,
        'ITEMS': [
            {'ITEM_ENUM': None,
             'ITEM_STATUS': None,
             'TEMPLOCATION': None,
             "ITEM_STATUS_DESC": None,
             "ITEM_ID": 0,
             "PERMLOCATION": None,
             "LIBRARY_FULL_NAME": "Internet Archive",
             "ELIGIBLE": False,
             "TRIMMED_LOCATION_DISPLAY_NAME": "Open Library",
             "CHRON": None,
             "DISPLAY_CALL_NO": None,
             "BIB_ID": None},
        ],
        'ELIGIBLE': False,
        'LIBRARY_FULL_NAME': 'Internet Archive',
        'TRIMMED_LOCATION_DISPLAY_NAME': 'Open Library',
        'ELECTRONIC_DATA': {},
        'LIBRARY_HAS': [],
        'LOCATION_ID': None,
        'AVAILABILITY': {},
        'DISPLAY_CALL_NO': None,
        'BIB_ID': None,
    }
    if book.keys():
        holding['ITEMS'][0]['DISPLAY_CALL_NO'] = \
            book.get('identifiers', {}).get('openlibrary', [])[0]
        holding['MFHD_DATA']['marc856list'][0]['u'] = book.get('url', '')
    return holding

def hathitrust(num, num_type):
    # ensure we're dealing with a proper identifier type and value
    try:
        if num_type.upper() not in ('ISBN', 'OCLC', 'LCCN', 'OLID'):
            raise
        if num_type.upper() == 'ISBN':
            num = clean_isbn(num)
            if len(num) not in (10, 13):
                raise
    except:
        return {}
    params = '%s/%s' % (num_type, num)
    url = 'http://catalog.hathitrust.org/api/volumes/brief/%s.json' % params
    try:
        response = urlopen(url)
        json_data = json.loads(response.read())
        for item in json_data.get('items', []):
            if item.get('usRightsString', '') == 'Full view':
                return make_hathi_holding(item.get('itemURL', ''),
                                          item.get('fromRecord', ''))
    except:
        return {}

def make_hathi_holding(url, fromRecord):
    # use library name IA
    # add dummy elements to conform with holding model
    holding = {
        'LIBRARY_NAME': 'IA',
        'LOCATION_NAME': 'HT',
        'LOCATION_DISPLAY_NAME': 'HT: Hathi Trust',
        'MFHD_DATA': {
            "marc866list": [],
            "marc856list": [
                {"3": "",
                 "z": "",
                 "u": url}],
            "marc852": ""
        },
        'MFHD_ID': None,
        'ITEMS': [
            {'ITEM_ENUM': None,
             'ITEM_STATUS': None,
             'TEMPLOCATION': None,
             "ITEM_STATUS_DESC": None,
             "ITEM_ID": 0,
             "PERMLOCATION": None,
             "LIBRARY_FULL_NAME": "Hathi Trust",
             "ELIGIBLE": False,
             "TRIMMED_LOCATION_DISPLAY_NAME": "Hathi Trust Digital Library",
             "CHRON": None,
             "DISPLAY_CALL_NO": fromRecord,
             "BIB_ID": None},
        ],
        'ELIGIBLE': False,
        'LIBRARY_FULL_NAME': 'Hathi Trust',
        'TRIMMED_LOCATION_DISPLAY_NAME': 'Hathi Trust Digital Library',
        'ELECTRONIC_DATA': {},
        'LIBRARY_HAS': [],
        'LOCATION_ID': None,
        'AVAILABILITY': {},
        'DISPLAY_CALL_NO': 'Record ' + fromRecord,
        'BIB_ID': None,
    }
    return holding

def sersol360link(num, num_type, count=0):
    try:
        count += 1
        url = '%s&%s=%s' % (settings.SER_SOL_API_URL, num_type, num)
        response = urlopen(url)
        tree = etree.fromstring(response.read())
    except:
        return []
    output = []
    ns = 'http://xml.serialssolutions.com/ns/openurl/v1.0'
    openurls = tree.xpath('/sso:openURLResponse/sso:results/sso:result/sso' +
                          ':linkGroups/sso:linkGroup[@type="holding"]',
                          namespaces={'sso': ns})
    if not openurls and count < settings.SER_SOL_API_MAX_ATTEMPTS:
        return sersol360link(num, num_type, count)
    for openurl in openurls:
        dbid = openurl.xpath('sso:holdingData/sso:databaseId',
                             namespaces={'sso': ns})
        if not dbid:
            continue
        dbid = dbid[0]
        if dbid.text != settings.SER_SOL_DBID_TEXT:
            data = {}
            start = openurl.xpath('sso:holdingData/sso:startDate',
                                  namespaces={'sso': ns})
            data['start'] = start[0].text if start else ''
            end = openurl.xpath('sso:holdingData/sso:endDate',
                                namespaces={'sso': ns})
            data['end'] = end[0].text if end else ''
            dbname = openurl.xpath('sso:holdingData/sso:databaseName',
                                   namespaces={'sso': ns})
            data['dbname'] = dbname[0].text if dbname else ''
            source = openurl.xpath('sso:url[@type="source"]',
                                   namespaces={'sso': ns})
            data['source'] = source[0].text if source else ''
            journal = openurl.xpath('sso:url[@type="journal"]',
                                    namespaces={'sso': ns})
            data['journal'] = journal[0].text if journal else ''
            output.append(data)
    return output
<|endoftext|>


<commit_before>#window
wdth = 400
hght = 400

#ball
initialBallSpeed = 3
initialBallAngleRandom = 40
ballSpeedMultiplier = 1.1

ballBounceRandom = 15
ballPlayerBounceRandom = 10

physicsMaxSpeed = 5

#player
playerSpeed = 5

#misc
debug = True<commit_msg>Disabled debug mode<commit_after>#window
wdth = 400
hght = 400

#ball
initialBallSpeed = 3
initialBallAngleRandom = 40
ballSpeedMultiplier = 1.1

ballBounceRandom = 15
ballPlayerBounceRandom = 10

physicsMaxSpeed = 5

#player
playerSpeed = 5

#misc
debug = False<|endoftext|>


<commit_before>"""
Extracts selected MARC data to a friendly Python dictionary.
"""

import os
import re
import json

# turn the 043 codes into human readable strings based on the table list at
# http://www.loc.gov/standards/codelists/gacs.xml

gacs_file = os.path.join(os.path.dirname(__file__), "gacs.json")
gacs_dict = json.loads(open(gacs_file).read())

def gacs(field):
    values = []
    for c, v in field:
        # only interested in subfield a
        if c == 'a':
            # strip trailing dashes from gacs code if present
            v = re.sub(r"-+$", "", v)
            # add the string for the gacs code if it is available
            values.append(gacs_dict.get(v, v))
    return values

# a machine readable version of
# https://github.com/gwu-libraries/launchpad/wiki/MARC-Extraction
# note: the order of each rule controls the display order

mapping = (
    ('STANDARD_TITLE', 'Standard Title', ['240']),
    ('OTHER_TITLE', 'Other Title', ['130', '242', '246', '730', '740', '247']),
    ('OTHER_AUTHORS', 'Other Authors', ['700', '710', '711']),
    ('EARLIER_TITLE', 'Earlier Title', ['247', '780']),
    ('TITLE_CHANGED_TO', 'Title Changed To', ['785']),
    ('SUBJECTS', 'Subjects', ['650', '600', '610', '630', '651']),
    ('SERIES', 'Series', ['440', '800', '810', '811', '830']),
    ('DESCRIPTION', 'Description', ['300', '516', '344', '345', '346', '347']),
    ('COPYRIGHT_DATE', 'Copyright Date', [('264', None, None, 'c')]),
    ('NOTES', 'Notes', ['500', '501', '504', '507', '530', '546', '547',
                        '550', '586', '590']),
    ('SUMMARY', 'Summary', ['520']),
    ('CURRENT_FREQUENCY', 'Current Frequency', ['310', '321', '362']),
    ('PUBLICATION_HISTORY', 'Publication History', ['362']),
    ('IN_COLLECTION', 'In Collection', ['773']),
    ('THESIS_DISSERTATION', 'Thesis/Dissertation', ['502']),
    ('CONTENTS', 'Contents', ['505']),
    ('PRODUCTION_CREDITS', 'Production Credits', ['508']),
    ('CITATION', 'Citation', ['510']),
    ('PERFORMERS', 'Performers', ['511']),
    ('REPRODUCTION', 'Reproduction', ['533']),
    ('ORIGINAL_VERSION', 'Original Version', ['534']),
    ('FUNDING_SPONSORS', 'Funding Sponsors', ['536']),
    ('SYSTEM_REQUIREMENTS', 'System Requirements', ['538']),
    ('TERMS_OF_USAGE', 'Terms of Usage', ['540']),
    ('COPYRIGHT', 'Copyright', ['542']),
    ('FINDING_AIDS', 'Finding Aids', ['555']),
    ('TITLE_HISTORY', 'Title History', ['580']),
    ('SOURCE_DESCRIPTION', 'Source Description', ['588']),
    ('MANUFACTURE_NUMBERS', 'Manufacture Numbers', ['028']),
    ('GENRE', 'Genre', [('655', None, None, 'a')]),
    ('OTHER_STANDARD_IDENTIFIER', 'Other Identifiers', ['024']),
    ('PUBLISHER_NUMBER', 'Publisher Numbers', ['028']),
    ('GEOGRAPHIC_AREA', 'Geographic Area', [('043', gacs)]),
    ('OCLC_CODE', 'OCLC Code', ['049']),
    ('DDC', 'Dewey Decimal Classification', ['082']),
)

def extract(record, d={}):
    """
    Takes a pymarc.Record object and returns extracted information as a
    dictionary. If you pass in a dictionary the extracted information will
    be folded into it.
    """
    for name, display_name, specs in mapping:
        d[name] = []
        for spec in specs:

            # simple field specification
            if type(spec) == str:
                for field in record.get_fields(spec):
                    if field.is_subject_field():
                        d[name].append(field.format_field())
                    else:
                        d[name].append(field.value())

            # complex field specification
            elif len(spec) == 4:
                tag, ind1, ind2, subfields = spec
                for field in record.get_fields(tag):
                    if ind(ind1, field.indicator1) and ind(ind2,
                       field.indicator2):
                        parts = []
                        for code, value in field:
                            if code in subfields:
                                parts.append(value)
                        if len(parts) > 0:
                            d[name].append(' '.join(parts))

            # function based specification
            elif len(spec) == 2:
                tag, func = spec
                for field in record.get_fields(tag):
                    d[name].extend(func(field))

            # uhoh, the field specification looks bad
            else:
                raise Exception("invalid mapping for %s" % name)

    return d

def ind(expected, found):
    "Tests an indicator rule"
    if expected is None:
        return True
    elif expected == found:
        return True
    else:
        return False
<commit_msg>remove $0 for now from subjects. ref #180<commit_after>"""
Extracts selected MARC data to a friendly Python dictionary.
"""

import os
import re
import json

# turn the 043 codes into human readable strings based on the table list at
# http://www.loc.gov/standards/codelists/gacs.xml

gacs_file = os.path.join(os.path.dirname(__file__), "gacs.json")
gacs_dict = json.loads(open(gacs_file).read())

def gacs(field):
    values = []
    for c, v in field:
        # only interested in subfield a
        if c == 'a':
            # strip trailing dashes from gacs code if present
            v = re.sub(r"-+$", "", v)
            # add the string for the gacs code if it is available
            values.append(gacs_dict.get(v, v))
    return values

# a machine readable version of
# https://github.com/gwu-libraries/launchpad/wiki/MARC-Extraction
# note: the order of each rule controls the display order

mapping = (
    ('STANDARD_TITLE', 'Standard Title', ['240']),
    ('OTHER_TITLE', 'Other Title', ['130', '242', '246', '730', '740', '247']),
    ('OTHER_AUTHORS', 'Other Authors', ['700', '710', '711']),
    ('EARLIER_TITLE', 'Earlier Title', ['247', '780']),
    ('TITLE_CHANGED_TO', 'Title Changed To', ['785']),
    ('SUBJECTS', 'Subjects', ['650', '600', '610', '630', '651']),
    ('SERIES', 'Series', ['440', '800', '810', '811', '830']),
    ('DESCRIPTION', 'Description', ['300', '516', '344', '345', '346', '347']),
    ('COPYRIGHT_DATE', 'Copyright Date', [('264', None, None, 'c')]),
    ('NOTES', 'Notes', ['500', '501', '504', '507', '530', '546', '547',
                        '550', '586', '590']),
    ('SUMMARY', 'Summary', ['520']),
    ('CURRENT_FREQUENCY', 'Current Frequency', ['310', '321', '362']),
    ('PUBLICATION_HISTORY', 'Publication History', ['362']),
    ('IN_COLLECTION', 'In Collection', ['773']),
    ('THESIS_DISSERTATION', 'Thesis/Dissertation', ['502']),
    ('CONTENTS', 'Contents', ['505']),
    ('PRODUCTION_CREDITS', 'Production Credits', ['508']),
    ('CITATION', 'Citation', ['510']),
    ('PERFORMERS', 'Performers', ['511']),
    ('REPRODUCTION', 'Reproduction', ['533']),
    ('ORIGINAL_VERSION', 'Original Version', ['534']),
    ('FUNDING_SPONSORS', 'Funding Sponsors', ['536']),
    ('SYSTEM_REQUIREMENTS', 'System Requirements', ['538']),
    ('TERMS_OF_USAGE', 'Terms of Usage', ['540']),
    ('COPYRIGHT', 'Copyright', ['542']),
    ('FINDING_AIDS', 'Finding Aids', ['555']),
    ('TITLE_HISTORY', 'Title History', ['580']),
    ('SOURCE_DESCRIPTION', 'Source Description', ['588']),
    ('MANUFACTURE_NUMBERS', 'Manufacture Numbers', ['028']),
    ('GENRE', 'Genre', [('655', None, None, 'a')]),
    ('OTHER_STANDARD_IDENTIFIER', 'Other Identifiers', ['024']),
    ('PUBLISHER_NUMBER', 'Publisher Numbers', ['028']),
    ('GEOGRAPHIC_AREA', 'Geographic Area', [('043', gacs)]),
    ('OCLC_CODE', 'OCLC Code', ['049']),
    ('DDC', 'Dewey Decimal Classification', ['082']),
)

def extract(record, d={}):
    """
    Takes a pymarc.Record object and returns extracted information as a
    dictionary. If you pass in a dictionary the extracted information will
    be folded into it.
    """
    for name, display_name, specs in mapping:
        d[name] = []
        for spec in specs:

            # simple field specification
            if type(spec) == str:
                for field in record.get_fields(spec):
                    if field.is_subject_field():
                        d[name].append(subject(field))
                    else:
                        d[name].append(field.value())

            # complex field specification
            elif len(spec) == 4:
                tag, ind1, ind2, subfields = spec
                for field in record.get_fields(tag):
                    if ind(ind1, field.indicator1) and ind(ind2,
                       field.indicator2):
                        parts = []
                        for code, value in field:
                            if code in subfields:
                                parts.append(value)
                        if len(parts) > 0:
                            d[name].append(' '.join(parts))

            # function based specification
            elif len(spec) == 2:
                tag, func = spec
                for field in record.get_fields(tag):
                    d[name].extend(func(field))

            # uhoh, the field specification looks bad
            else:
                raise Exception("invalid mapping for %s" % name)

    return d

def ind(expected, found):
    "Tests an indicator rule"
    if expected is None:
        return True
    elif expected == found:
        return True
    else:
        return False

def subject(f):
    s = ''
    for code, value in f:
        if code == '0':
            # TODO: might be useful to return subject URLs
            continue
        elif code not in ('v', 'x', 'y', 'z'):
            s += ' %s' % value
        else:
            s += ' -- %s' % value
    return s.strip()
<|endoftext|>


<commit_before>#!/usr/bin/env python
"""Generic config parsing and dumping, the way I remember it from scripts
gone by.

Ideally the config is loaded + mixed with command line options, then locked
during runtime.  The config dump should be loadable and re-runnable for a
duplicate run.
"""

from copy import deepcopy
from optparse import OptionParser
import os
import pprint
import sys
try:
    import json
except:
    import simplejson as json
from Log import SimpleFileLogger, MultiFileLogger

# MozOptionParser {{{1
class MozOptionParser(OptionParser):
    """Very slightly modified optparse.OptionParser, which assumes you know
    all the options you just add_option'ed, which is usually the case.

    However, I wanted to be able to have options defined in various places
    and then figure out the dest for each option (e.g. not -v or --verbose,
    but options.verbose) so I could set those directly in the config.

    The options and parser objects in
        (options, args) = parser.parseArgs()
    don't give an easy way of doing that; dir(options) is pretty ugly and
    I was playing with dict() and str() in ways that made me pretty
    frustrated.

    Adding a self.variables list seems like a fairly innocuous and easy
    way to work around this problem.
    """
    def __init__(self, **kwargs):
        OptionParser.__init__(self, **kwargs)
        self.variables = []

    def add_option(self, *args, **kwargs):
        option = OptionParser.add_option(self, *args, **kwargs)
        if option.dest and option.dest not in self.variables:
            self.variables.append(option.dest)

# BaseConfig {{{1
class BaseConfig(object):
    """Basic config setting/getting.
    Debating whether to be paranoid about this stuff and put it all in
    self._config and forcing everyone to use methods to access it, as I
    did elsewhere to lock down the config during runtime, but that's a
    little heavy handed to go with as the default.
    """
    def __init__(self, config=None, configFile=None):
        self.config = {}
        self.logObj = None
        if config:
            self.setConfig(config)
        elif configFile:
            self.setConfig(self.parseConfigFile(configFile))

    def parseConfigFile(self, fileName):
        """Read a config file and return a dictionary.
        TODO: read subsequent config files once self.config is already
        set, with options to override or drop conflicting config settings.
        TODO: have a config file search path, so we're less inflexible
        about cwd().
        """
        fh = open(fileName)
        config = {}
        if fileName.endswith('.json'):
            jsonConfig = json.load(fh)
            config = dict(jsonConfig)
        else:
            contents = []
            for line in fh:
                line = line[:-1]
                contents.append(line)
                config = dict(contents)
        fh.close()

        """Return it here? Or set something?
        """
        return config

    def mapConfig(self, config1, config2):
        """Copy key/value pairs of config2 onto config1.
        There can be a lot of other behaviors here; writing this one first.
        """
        config = deepcopy(config1)
        for key, value in config2.iteritems():
            config[key] = value
        return config

    def queryConfig(self, varName=None):
        if not varName:
            return self.config
        try:
            str(varName) == varName
        except:
            """It would be cool to allow for dictionaries here, to specify
            which subset(s) of config to return
            """
            pass
        else:
            if varName in self.config:
                return self.config[varName]

    def setConfig(self, config, overwrite=False):
        """It would be good to detect if self.config is already set, and
        if so, have settings as to how to determine what overrides what.
        """
        if self.config and not overwrite:
            self.config = self.mapConfig(self.config, config)
        else:
            self.config = config

    def queryVar(self, varName, default=None):
        value = self.queryConfig(varName=varName)
        if not value:
            return default
        else:
            return value

    def setVar(self, varName, value):
        self.debug("Setting %s to %s" % (varName, value))
        self.config[varName] = value

    def dumpConfig(self, config=None, fileName=None):
        """Dump the configuration somewhere, default to STDOUT.
        Be nice to be able to write a .py or .json file according to
        filename.
        """
        if not config:
            config = self.queryConfig()
        if not fileName:
            pp = pprint.PrettyPrinter(indent=2, width=10)
            return pp.pformat(config)

    def parseArgs(self, usage="usage: %prog [options]"):
        """Parse command line arguments in a generic way.
        Return the parser object after adding the basic options, so
        child objects can manipulate it.

        TODO: accept a list of options to add by default, map these onto
        the config, and just return the leftover args.  This is the ideal
        behavior.
        TODO: be able to read the options to add from a config.
        TODO: add more default options.
        """
        parser = MozOptionParser(usage=usage)
        parser.add_option("--logLevel", action="store", type="choice",
                          dest="logLevel", default="info",
                          choices=['debug', 'info', 'warning', 'error',
                                   'critical', 'fatal'],
                          help="Set log level (debug|info|warning|error|critical|fatal)")
        parser.add_option("-q", "--quiet", action="store_false",
                          dest="logToConsole", default=True,
                          help="Don't log to the console")
        parser.add_option("--appendToLog", action="store_true",
                          dest="appendToLog", default=False,
                          help="Append to the log")
        return parser

    """There may be a better way of doing this, but I did this previously...
    """
    def log(self, message, level='info', exitCode=-1):
        if self.logObj:
            return self.logObj.log(message, level=level, exitCode=exitCode)
        if level == 'info':
            print message
        elif level == 'debug':
            print 'DEBUG: %s' % message
        elif level in ('warning', 'error', 'critical'):
            print >> sys.stderr, "%s: %s" % (level.upper(), message)
        elif level == 'fatal':
            print >> sys.stderr, "FATAL: %s" % message
            sys.exit(exitCode)

    def debug(self, message):
        level = self.queryVar('logLevel')
        if not level:
            level = self.queryVar('logLevel')
        if level and level == 'debug':
            self.log(message, level='debug')

    def info(self, message):
        self.log(message, level='info')

    def warning(self, message):
        self.log(message, level='warning')

    def warn(self, message):
        self.log(message, level='warning')

    def error(self, message):
        self.log(message, level='error')

    def critical(self, message):
        self.log(message, level='critical')

    def fatal(self, message, exitCode=-1):
        self.log(message, level='fatal', exitCode=exitCode)

# SimpleConfig {{{1
class SimpleConfig(BaseConfig):
    """Effectively BaseConfig with logging.
    """
    def __init__(self, **kwargs):
        BaseConfig.__init__(self, **kwargs)
        self.parseArgs()
        self.newLogObj()

    def parseArgs(self, usage="usage: %prog [options]"):
        parser = BaseConfig.parseArgs(self, usage=usage)
        parser.add_option("--multiLog", action="store_true",
                          dest="multiLog", default=False,
                          help="Log using MultiFileLogger")
        return parser

    def newLogObj(self):
        logConfig = {"loggerName": 'Simple',
                     "logName": 'simple.log',
                     "logDir": '.',
                     "logLevel": 'info',
                     "logFormat": '%(asctime)s - %(levelname)s - %(message)s',
                     "logToConsole": True,
                     "appendToLog": False,
                    }
        for key in logConfig.keys():
            value = self.queryVar(key)
            if value:
                logConfig[key] = value
        if self.queryVar("multiLog"):
            self.logObj = MultiFileLogger(**logConfig)
        else:
            self.logObj = SimpleFileLogger(**logConfig)

# __main__ {{{1
if __name__ == '__main__':
    obj = SimpleConfig(configFile=os.path.join(sys.path[0], 'configs', 'test',
                       'test.json'))
    obj.setVar('additionalkey', 'additionalvalue')
    obj.setVar('key2', 'value2override')
    obj.dumpConfig()
    if obj.queryVar('key1') != "value1":
        obj.error("key1 isn't value1!")

    obj = ParanoidConfig(configFile=os.path.join(sys.path[0], 'configs',
                         'test', 'test.json'))
    obj.lockConfig()
    try:
        obj.info("This should fail: with a FATAL message")
        obj.setVar('thisShouldFail', 'miserably')
    except:
        obj.info("Yay!")
    else:
        obj.error("Gah. ParanoidConfig is broken.")
    if os.path.exists("simple.log"):
        os.remove("simple.log")
<commit_msg>aha, that's why signdebs is logging to .<commit_after>#!/usr/bin/env python
"""Generic config parsing and dumping, the way I remember it from scripts
gone by.

Ideally the config is loaded + mixed with command line options, then locked
during runtime.  The config dump should be loadable and re-runnable for a
duplicate run.
"""

from copy import deepcopy
from optparse import OptionParser
import os
import pprint
import sys
try:
    import json
except:
    import simplejson as json
from Log import SimpleFileLogger, MultiFileLogger

# MozOptionParser {{{1
class MozOptionParser(OptionParser):
    """Very slightly modified optparse.OptionParser, which assumes you know
    all the options you just add_option'ed, which is usually the case.

    However, I wanted to be able to have options defined in various places
    and then figure out the dest for each option (e.g. not -v or --verbose,
    but options.verbose) so I could set those directly in the config.

    The options and parser objects in
        (options, args) = parser.parseArgs()
    don't give an easy way of doing that; dir(options) is pretty ugly and
    I was playing with dict() and str() in ways that made me pretty
    frustrated.

    Adding a self.variables list seems like a fairly innocuous and easy
    way to work around this problem.
    """
    def __init__(self, **kwargs):
        OptionParser.__init__(self, **kwargs)
        self.variables = []

    def add_option(self, *args, **kwargs):
        option = OptionParser.add_option(self, *args, **kwargs)
        if option.dest and option.dest not in self.variables:
            self.variables.append(option.dest)

# BaseConfig {{{1
class BaseConfig(object):
    """Basic config setting/getting.
    Debating whether to be paranoid about this stuff and put it all in
    self._config and forcing everyone to use methods to access it, as I
    did elsewhere to lock down the config during runtime, but that's a
    little heavy handed to go with as the default.
    """
    def __init__(self, config=None, configFile=None):
        self.config = {}
        self.logObj = None
        if config:
            self.setConfig(config)
        elif configFile:
            self.setConfig(self.parseConfigFile(configFile))

    def parseConfigFile(self, fileName):
        """Read a config file and return a dictionary.
        TODO: read subsequent config files once self.config is already
        set, with options to override or drop conflicting config settings.
        TODO: have a config file search path, so we're less inflexible
        about cwd().
        """
        fh = open(fileName)
        config = {}
        if fileName.endswith('.json'):
            jsonConfig = json.load(fh)
            config = dict(jsonConfig)
        else:
            contents = []
            for line in fh:
                line = line[:-1]
                contents.append(line)
                config = dict(contents)
        fh.close()

        """Return it here? Or set something?
        """
        return config

    def mapConfig(self, config1, config2):
        """Copy key/value pairs of config2 onto config1.
        There can be a lot of other behaviors here; writing this one first.
        """
        config = deepcopy(config1)
        for key, value in config2.iteritems():
            config[key] = value
        return config

    def queryConfig(self, varName=None):
        if not varName:
            return self.config
        try:
            str(varName) == varName
        except:
            """It would be cool to allow for dictionaries here, to specify
            which subset(s) of config to return
            """
            pass
        else:
            if varName in self.config:
                return self.config[varName]

    def setConfig(self, config, overwrite=False):
        """It would be good to detect if self.config is already set, and
        if so, have settings as to how to determine what overrides what.
        """
        if self.config and not overwrite:
            self.config = self.mapConfig(self.config, config)
        else:
            self.config = config

    def queryVar(self, varName, default=None):
        value = self.queryConfig(varName=varName)
        if not value:
            return default
        else:
            return value

    def setVar(self, varName, value):
        self.debug("Setting %s to %s" % (varName, value))
        self.config[varName] = value

    def dumpConfig(self, config=None, fileName=None):
        """Dump the configuration somewhere, default to STDOUT.
        Be nice to be able to write a .py or .json file according to
        filename.
        """
        if not config:
            config = self.queryConfig()
        if not fileName:
            pp = pprint.PrettyPrinter(indent=2, width=10)
            return pp.pformat(config)

    def parseArgs(self, usage="usage: %prog [options]"):
        """Parse command line arguments in a generic way.
        Return the parser object after adding the basic options, so
        child objects can manipulate it.

        TODO: accept a list of options to add by default, map these onto
        the config, and just return the leftover args.  This is the ideal
        behavior.
        TODO: be able to read the options to add from a config.
        TODO: add more default options.
        """
        parser = MozOptionParser(usage=usage)
        parser.add_option("--logLevel", action="store", type="choice",
                          dest="logLevel", default="info",
                          choices=['debug', 'info', 'warning', 'error',
                                   'critical', 'fatal'],
                          help="Set log level (debug|info|warning|error|critical|fatal)")
        parser.add_option("-q", "--quiet", action="store_false",
                          dest="logToConsole", default=True,
                          help="Don't log to the console")
        parser.add_option("--appendToLog", action="store_true",
                          dest="appendToLog", default=False,
                          help="Append to the log")
        return parser

    """There may be a better way of doing this, but I did this previously...
    """
    def log(self, message, level='info', exitCode=-1):
        if self.logObj:
            return self.logObj.log(message, level=level, exitCode=exitCode)
        if level == 'info':
            print message
        elif level == 'debug':
            print 'DEBUG: %s' % message
        elif level in ('warning', 'error', 'critical'):
            print >> sys.stderr, "%s: %s" % (level.upper(), message)
        elif level == 'fatal':
            print >> sys.stderr, "FATAL: %s" % message
            sys.exit(exitCode)

    def debug(self, message):
        level = self.queryVar('logLevel')
        if not level:
            level = self.queryVar('logLevel')
        if level and level == 'debug':
            self.log(message, level='debug')

    def info(self, message):
        self.log(message, level='info')

    def warning(self, message):
        self.log(message, level='warning')

    def warn(self, message):
        self.log(message, level='warning')

    def error(self, message):
        self.log(message, level='error')

    def critical(self, message):
        self.log(message, level='critical')

    def fatal(self, message, exitCode=-1):
        self.log(message, level='fatal', exitCode=exitCode)

# SimpleConfig {{{1
class SimpleConfig(BaseConfig):
    """Effectively BaseConfig with logging.
    """
    def __init__(self, **kwargs):
        BaseConfig.__init__(self, **kwargs)
        self.parseArgs()
        self.newLogObj()

    def parseArgs(self, usage="usage: %prog [options]"):
        parser = BaseConfig.parseArgs(self, usage=usage)
        parser.add_option("--multiLog", action="store_true",
                          dest="multiLog", default=False,
                          help="Log using MultiFileLogger")
        return parser

    def newLogObj(self):
        logConfig = {"loggerName": 'Simple',
                     "logName": 'simple.log',
                     "logDir": 'logs',
                     "logLevel": 'info',
                     "logFormat": '%(asctime)s - %(levelname)s - %(message)s',
                     "logToConsole": True,
                     "appendToLog": False,
                    }
        for key in logConfig.keys():
            value = self.queryVar(key)
            if value:
                logConfig[key] = value
        if self.queryVar("multiLog"):
            self.logObj = MultiFileLogger(**logConfig)
        else:
            self.logObj = SimpleFileLogger(**logConfig)

# __main__ {{{1
if __name__ == '__main__':
    obj = SimpleConfig(configFile=os.path.join(sys.path[0], 'configs', 'test',
                       'test.json'))
    obj.setVar('additionalkey', 'additionalvalue')
    obj.setVar('key2', 'value2override')
    obj.dumpConfig()
    if obj.queryVar('key1') != "value1":
        obj.error("key1 isn't value1!")

    obj = ParanoidConfig(configFile=os.path.join(sys.path[0], 'configs',
                         'test', 'test.json'))
    obj.lockConfig()
    try:
        obj.info("This should fail: with a FATAL message")
        obj.setVar('thisShouldFail', 'miserably')
    except:
        obj.info("Yay!")
    else:
        obj.error("Gah. ParanoidConfig is broken.")
    if os.path.exists("simple.log"):
        os.remove("simple.log")
<|endoftext|>