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

"""This module contains the Role Model."""

__authors__ = [
  '"Todd Larsen" <tlarsen@google.com>',
  '"Sverre Rabbelier" <sverre@rabbelier.nl>',
  '"Pawel Solyga" <pawel.solyga@gmail.com>',
]

from google.appengine.ext import db

from django.utils.translation import ugettext_lazy

from soc.models import countries

import soc.models.linkable
import soc.models.user

class Role(soc.models.linkable.Linkable):
  """Information common to Program participation for all Roles.

  Some details of a Role are considered "public" information, and nearly
  all of these are optional (except for given_name, surname, and email).
  Other details of a Role are kept "private" and are only provided to
  other Users in roles that "need to know" this information.  How these
  fields are revealed is usually covered by Program terms of service.

  Role is the entity that is created when a User actually participates
  in some fashion in a Program. Role details could *possibly* be collected
  without actual participation (voluntary, opt-in, of course).

  A Role is a User's participation in a single Program.  To avoid
  duplication of data entry, facilities will be available for selecting
  an existing Role associated with a particular User to be duplicated for
  participation in a new Program.

  A User has to have at least one Role in order to be able to create
  any Work (such as a Document) on the site.  The easiest-to-obtain Role is
  probably Club Member (though Clubs can set their own membership criteria).

  A Role entity participates in the following relationships implemented
  as a db.ReferenceProperty elsewhere in another db.Model:

   documentation) a 1:many relationship of Documentation (tax forms,
     letters from schools, etc.) associated with the Role by Hosts.  This
     relation is implemented as the 'documentation' back-reference Query of
     the Documentation model 'role' reference.

   works) a many:many relationship with Works, stored in a separate
     WorksRoles model, representing the Work authored by this Role.
     See the WorksRoles model class for details.
  """

  #: A required many:1 relationship that ties (possibly multiple
  #: entities of) Role details to a unique User. A Role cannot
  #: exist unassociated from a login identity and credentials. The
  #: back-reference in the User model is a Query named 'roles'.
  user = db.ReferenceProperty(reference_class=soc.models.user.User,
                              required=True, collection_name='roles')

  #: field storing whether User has agreed to the Role-specific Terms of
  #: Service. (Not a required field because some Roles may not have special
  #: Terms of Service.)
  agrees_to_tos = db.BooleanProperty(
      verbose_name=ugettext_lazy('Agrees to ToS'))
  agrees_to_tos.help_text = ugettext_lazy(
      'Indicates that the user agrees to the Terms of Service for this Role.')

  #====================================================================
  #  (public) name information
  #====================================================================

  #: Required field storing the parts of the Role's name
  #: corresponding to the field names; displayed publicly.
  #: given_name can only be lower ASCII, not UTF-8 text, because it is
  #: used, for example, as part of the shipping (mailing) address.
  given_name = db.StringProperty(required=True,
      verbose_name=ugettext_lazy('First (given) name'))
  given_name.help_text = ugettext_lazy('lower ASCII characters only')

  #: Required field storing the parts of the Role's name
  #: corresponding to the field names; displayed publicly.
  #: Surname can only be lower ASCII, not UTF-8 text, because it is
  #: used, for example, as part of the shipping (mailing) address.
  surname = db.StringProperty(
      required=True,
      verbose_name=ugettext_lazy('Last (family) name'))
  surname.help_text = ugettext_lazy('lower ASCII characters only')

  #: Optional field used as a display name, such as for awards
  #: certificates. Should be the entire display name in the format
  #: the Role would like it displayed (could be surname followed by
  #: given name in some cultures, for example). Display names can be
  #: any valid UTF-8 text.
  display_name = db.StringProperty(
      verbose_name=ugettext_lazy('Display Name'))
  display_name.help_text = ugettext_lazy(
      'Optional field used as a display name, such as for awards '
      'certificates. Should be the entire display name in the format '
      'the person would like it displayed (could be family name followed '
      'by given name in some cultures, for example). Display names can be '
      'any valid UTF-8 text.')

  #====================================================================
  #  (public) contact information
  #====================================================================

  #: Required field used as the 'public' contact mechanism for the
  #: Role (as opposed to the user.account email address which is
  #: kept secret).
  email = db.EmailProperty(
      required=True,
      verbose_name=ugettext_lazy('Email Address'))

  #: Optional field storing Instant Messaging network; displayed publicly.
  im_network = db.StringProperty(
      verbose_name=ugettext_lazy('IM Network'))
  im_network.help_text = ugettext_lazy(
      'examples: irc:irc.freenode.org xmpp:gmail.com/Home')

  #: Optional field storing Instant Messaging handle; displayed publicly.
  im_handle = db.StringProperty(
      verbose_name=ugettext_lazy('IM Handle'))
  im_handle.help_text = ugettext_lazy(
      'personal identifier, such as: screen name, IRC nick, user name')

  #: Optional field storing a home page URL; displayed publicly.
  home_page = db.LinkProperty(
      verbose_name=ugettext_lazy('Home Page URL'))

  #: Optional field storing a blog URL; displayed publicly.
  blog = db.LinkProperty(
      verbose_name=ugettext_lazy('Blog URL'))

  #: Optional field storing a URL to an image, expected to be a
  #: personal photo (or cartoon avatar, perhaps); displayed publicly.
  photo_url = db.LinkProperty(
      verbose_name=ugettext_lazy('Thumbnail Photo URL'))
  photo_url.help_text = ugettext_lazy(
      'URL of 64x64 pixel thumbnail image')

  #: Optional field storing the latitude provided by the Role; displayed
  #: publicly.
  latitude = db.FloatProperty(
      verbose_name=ugettext_lazy('Latitude'))
  latitude.help_text = ugettext_lazy(
      'decimal degrees northerly (N), use minus sign (-) for southerly (S)')

  #: Optional field storing the longitude provided by the Role; displayed
  #: publicly.
  longitude = db.FloatProperty(
      verbose_name=ugettext_lazy('Longitude'))
  longitude.help_text = ugettext_lazy(
      'decimal degrees easterly (E), use minus sign (-) for westerly (W)')

  #====================================================================
  # (private) contact information
  #====================================================================

  #: Required field containing residence street address; kept private.
  #: Residence street address can only be lower ASCII, not UTF-8 text, because
  #: it may be used as a shipping address.
  res_street = db.StringProperty(required=True,
      verbose_name=ugettext_lazy('Street address'))
  res_street.help_text = ugettext_lazy(
      'street number and name, lower ASCII characters only')

  #: Required field containing residence address city; kept private.
  #: Residence city can only be lower ASCII, not UTF-8 text, because it
  #: may be used as a shipping address.
  res_city = db.StringProperty(required=True,
      verbose_name=ugettext_lazy('City'))
  res_city.help_text = ugettext_lazy('lower ASCII characters only')

  #: Optional field containing residence address state or province; kept
  #: private.  Residence state/province can only be lower ASCII, not UTF-8
  #: text, because it may be used as a shipping address.
  res_state = db.StringProperty(
      verbose_name=ugettext_lazy('State/Province'))
  res_state.help_text = ugettext_lazy(
      'optional if country/territory does not have states or provinces, '
      'lower ASCII characters only')

  #: Required field containing residence address country or territory; kept
  #: private.
  res_country = db.StringProperty(required=True,
      verbose_name=ugettext_lazy('Country/Territory'),
      choices=countries.COUNTRIES_AND_TERRITORIES)

  #: Required field containing residence address postal code (ZIP code in
  #: the United States); kept private.  Residence postal code can only be
  #: lower ASCII, not UTF-8 text, because it may be used as a shipping address.
  res_postalcode = db.StringProperty(required=True,
      verbose_name=ugettext_lazy('ZIP/Postal Code'))
  res_postalcode.help_text = ugettext_lazy('lower ASCII characters only')

  #: Optional field containing a separate shipping street address; kept
  #: private.  If shipping address is not present in its entirety, the
  #: residence address will be used instead.  Shipping street address can only
  #: be lower ASCII, not UTF-8 text, because, if supplied, it is used as a
  #: shipping address.
  ship_street = db.StringProperty(
      verbose_name=ugettext_lazy('Street address'))
  ship_street.help_text = ugettext_lazy(
      'street number and name, lower ASCII characters only')

  #: Optional field containing shipping address city; kept private.
  #: Shipping city can only be lower ASCII, not UTF-8 text, because, if
  #: supplied, it is used as a shipping address.
  ship_city = db.StringProperty(
      verbose_name=ugettext_lazy('City'))
  ship_city.help_text = ugettext_lazy('lower ASCII characters only')

  #: Optional field containing shipping address state or province; kept
  #: private.  Shipping state/province can only be lower ASCII, not UTF-8
  #: text, because, if supplied, it is used as a shipping address.
  ship_state = db.StringProperty(
      verbose_name=ugettext_lazy('State/Province'))
  ship_state.help_text = ugettext_lazy(
      'optional if country/territory does not have states or provinces, '
      'lower ASCII characters only')

  #: Optional field containing shipping address country or territory; kept
  #: private.
  ship_country = db.StringProperty(
      verbose_name=ugettext_lazy('Country/Territory'),
      choices=countries.COUNTRIES_AND_TERRITORIES)

  #: Optional field containing shipping address postal code (ZIP code in
  #: the United States); kept private.  Shipping postal code can only be
  #: lower ASCII, not UTF-8 text, because, if supplied, it is used as a
  #: shipping address.
  ship_postalcode = db.StringProperty(
      verbose_name=ugettext_lazy('ZIP/Postal Code'))
  ship_postalcode.help_text = ugettext_lazy('lower ASCII characters only')

  #: Required field containing a phone number that will be supplied
  #: to shippers; kept private.
  phone = db.PhoneNumberProperty(
      required=True,
      verbose_name=ugettext_lazy('Phone Number'))
  phone.help_text = ugettext_lazy(
      'include complete international calling number with country code')

  #====================================================================
  # (private) personal information
  #====================================================================

  #: Required field containing the Role's birthdate (for
  #: determining Program participation eligibility); kept private.
  birth_date = db.DateProperty(
      required=True,
      verbose_name=ugettext_lazy('Birth Date'))
  birth_date.help_text = ugettext_lazy(
      'required for determining program eligibility')

  #: Optional field indicating choice of t-shirt, from XXS to XXXL;
  #: kept private.
  tshirt_size = db.StringProperty(
      verbose_name=ugettext_lazy('T-shirt Size'),
      choices=('XXS', 'XS', 'S', 'M', 'L', 'XL', 'XXL', 'XXXL'))

  #: Optional field indicating choice of t-shirt fit; kept private.
  tshirt_style = db.StringProperty(
      verbose_name=ugettext_lazy('T-shirt Style'),
      choices=('male', 'female'))

  def name(self):
    """Alias 'display_name' Property as 'name' for use in common templates.
    """
    return self.display_name
<commit_msg>This file should not have been included in r1428.  Reverting...<commit_after>#!/usr/bin/python2.5
#
# Copyright 2008 the Melange authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""This module contains the Role Model."""

__authors__ = [
  '"Todd Larsen" <tlarsen@google.com>',
  '"Sverre Rabbelier" <sverre@rabbelier.nl>',
  '"Pawel Solyga" <pawel.solyga@gmail.com>',
]

from google.appengine.ext import db

from django.utils.translation import ugettext_lazy

from soc.models import countries

import soc.models.linkable
import soc.models.user

class Role(soc.models.linkable.Linkable):
  """Information common to Program participation for all Roles.

  Some details of a Role are considered "public" information, and nearly
  all of these are optional (except for given_name, surname, and email).
  Other details of a Role are kept "private" and are only provided to
  other Users in roles that "need to know" this information.  How these
  fields are revealed is usually covered by Program terms of service.

  Role is the entity that is created when a User actually participates
  in some fashion in a Program. Role details could *possibly* be collected
  without actual participation (voluntary, opt-in, of course).

  A Role is a User's participation in a single Program.  To avoid
  duplication of data entry, facilities will be available for selecting
  an existing Role associated with a particular User to be duplicated for
  participation in a new Program.

  A User has to have at least one Role in order to be able to create
  any Work (such as a Document) on the site.  The easiest-to-obtain Role is
  probably Club Member (though Clubs can set their own membership criteria).

  A Role entity participates in the following relationships implemented
  as a db.ReferenceProperty elsewhere in another db.Model:

   documentation) a 1:many relationship of Documentation (tax forms,
     letters from schools, etc.) associated with the Role by Hosts.  This
     relation is implemented as the 'documentation' back-reference Query of
     the Documentation model 'role' reference.

   works) a many:many relationship with Works, stored in a separate
     WorksRoles model, representing the Work authored by this Role.
     See the WorksRoles model class for details.
  """

  #: A required many:1 relationship that ties (possibly multiple
  #: entities of) Role details to a unique User. A Role cannot
  #: exist unassociated from a login identity and credentials. The
  #: back-reference in the User model is a Query named 'roles'.
  user = db.ReferenceProperty(reference_class=soc.models.user.User,
                              required=True, collection_name='roles')

  #====================================================================
  #  (public) name information
  #====================================================================

  #: Required field storing the parts of the Role's name
  #: corresponding to the field names; displayed publicly.
  #: given_name can only be lower ASCII, not UTF-8 text, because it is
  #: used, for example, as part of the shipping (mailing) address.
  given_name = db.StringProperty(required=True,
      verbose_name=ugettext_lazy('First (given) name'))
  given_name.help_text = ugettext_lazy('lower ASCII characters only')

  #: Required field storing the parts of the Role's name
  #: corresponding to the field names; displayed publicly.
  #: Surname can only be lower ASCII, not UTF-8 text, because it is
  #: used, for example, as part of the shipping (mailing) address.
  surname = db.StringProperty(
      required=True,
      verbose_name=ugettext_lazy('Last (family) name'))
  surname.help_text = ugettext_lazy('lower ASCII characters only')

  #: Optional field used as a display name, such as for awards
  #: certificates. Should be the entire display name in the format
  #: the Role would like it displayed (could be surname followed by
  #: given name in some cultures, for example). Display names can be
  #: any valid UTF-8 text.
  display_name = db.StringProperty(
      verbose_name=ugettext_lazy('Display Name'))
  display_name.help_text = ugettext_lazy(
      'Optional field used as a display name, such as for awards '
      'certificates. Should be the entire display name in the format '
      'the person would like it displayed (could be family name followed '
      'by given name in some cultures, for example). Display names can be '
      'any valid UTF-8 text.')

  #====================================================================
  #  (public) contact information
  #====================================================================

  #: Required field used as the 'public' contact mechanism for the
  #: Role (as opposed to the user.account email address which is
  #: kept secret).
  email = db.EmailProperty(
      required=True,
      verbose_name=ugettext_lazy('Email Address'))

  #: Optional field storing Instant Messaging network; displayed publicly.
  im_network = db.StringProperty(
      verbose_name=ugettext_lazy('IM Network'))
  im_network.help_text = ugettext_lazy(
      'examples: irc:irc.freenode.org xmpp:gmail.com/Home')

  #: Optional field storing Instant Messaging handle; displayed publicly.
  im_handle = db.StringProperty(
      verbose_name=ugettext_lazy('IM Handle'))
  im_handle.help_text = ugettext_lazy(
      'personal identifier, such as: screen name, IRC nick, user name')

  #: Optional field storing a home page URL; displayed publicly.
  home_page = db.LinkProperty(
      verbose_name=ugettext_lazy('Home Page URL'))

  #: Optional field storing a blog URL; displayed publicly.
  blog = db.LinkProperty(
      verbose_name=ugettext_lazy('Blog URL'))

  #: Optional field storing a URL to an image, expected to be a
  #: personal photo (or cartoon avatar, perhaps); displayed publicly.
  photo_url = db.LinkProperty(
      verbose_name=ugettext_lazy('Thumbnail Photo URL'))
  photo_url.help_text = ugettext_lazy(
      'URL of 64x64 pixel thumbnail image')

  #: Optional field storing the latitude provided by the Role; displayed
  #: publicly.
  latitude = db.FloatProperty(
      verbose_name=ugettext_lazy('Latitude'))
  latitude.help_text = ugettext_lazy(
      'decimal degrees northerly (N), use minus sign (-) for southerly (S)')

  #: Optional field storing the longitude provided by the Role; displayed
  #: publicly.
  longitude = db.FloatProperty(
      verbose_name=ugettext_lazy('Longitude'))
  longitude.help_text = ugettext_lazy(
      'decimal degrees easterly (E), use minus sign (-) for westerly (W)')

  #====================================================================
  # (private) contact information
  #====================================================================

  #: Required field containing residence street address; kept private.
  #: Residence street address can only be lower ASCII, not UTF-8 text, because
  #: it may be used as a shipping address.
  res_street = db.StringProperty(required=True,
      verbose_name=ugettext_lazy('Street address'))
  res_street.help_text = ugettext_lazy(
      'street number and name, lower ASCII characters only')

  #: Required field containing residence address city; kept private.
  #: Residence city can only be lower ASCII, not UTF-8 text, because it
  #: may be used as a shipping address.
  res_city = db.StringProperty(required=True,
      verbose_name=ugettext_lazy('City'))
  res_city.help_text = ugettext_lazy('lower ASCII characters only')

  #: Optional field containing residence address state or province; kept
  #: private.  Residence state/province can only be lower ASCII, not UTF-8
  #: text, because it may be used as a shipping address.
  res_state = db.StringProperty(
      verbose_name=ugettext_lazy('State/Province'))
  res_state.help_text = ugettext_lazy(
      'optional if country/territory does not have states or provinces, '
      'lower ASCII characters only')

  #: Required field containing residence address country or territory; kept
  #: private.
  res_country = db.StringProperty(required=True,
      verbose_name=ugettext_lazy('Country/Territory'),
      choices=countries.COUNTRIES_AND_TERRITORIES)

  #: Required field containing residence address postal code (ZIP code in
  #: the United States); kept private.  Residence postal code can only be
  #: lower ASCII, not UTF-8 text, because it may be used as a shipping address.
  res_postalcode = db.StringProperty(required=True,
      verbose_name=ugettext_lazy('ZIP/Postal Code'))
  res_postalcode.help_text = ugettext_lazy('lower ASCII characters only')

  #: Optional field containing a separate shipping street address; kept
  #: private.  If shipping address is not present in its entirety, the
  #: residence address will be used instead.  Shipping street address can only
  #: be lower ASCII, not UTF-8 text, because, if supplied, it is used as a
  #: shipping address.
  ship_street = db.StringProperty(
      verbose_name=ugettext_lazy('Street address'))
  ship_street.help_text = ugettext_lazy(
      'street number and name, lower ASCII characters only')

  #: Optional field containing shipping address city; kept private.
  #: Shipping city can only be lower ASCII, not UTF-8 text, because, if
  #: supplied, it is used as a shipping address.
  ship_city = db.StringProperty(
      verbose_name=ugettext_lazy('City'))
  ship_city.help_text = ugettext_lazy('lower ASCII characters only')

  #: Optional field containing shipping address state or province; kept
  #: private.  Shipping state/province can only be lower ASCII, not UTF-8
  #: text, because, if supplied, it is used as a shipping address.
  ship_state = db.StringProperty(
      verbose_name=ugettext_lazy('State/Province'))
  ship_state.help_text = ugettext_lazy(
      'optional if country/territory does not have states or provinces, '
      'lower ASCII characters only')

  #: Optional field containing shipping address country or territory; kept
  #: private.
  ship_country = db.StringProperty(
      verbose_name=ugettext_lazy('Country/Territory'),
      choices=countries.COUNTRIES_AND_TERRITORIES)

  #: Optional field containing shipping address postal code (ZIP code in
  #: the United States); kept private.  Shipping postal code can only be
  #: lower ASCII, not UTF-8 text, because, if supplied, it is used as a
  #: shipping address.
  ship_postalcode = db.StringProperty(
      verbose_name=ugettext_lazy('ZIP/Postal Code'))
  ship_postalcode.help_text = ugettext_lazy('lower ASCII characters only')

  #: Required field containing a phone number that will be supplied
  #: to shippers; kept private.
  phone = db.PhoneNumberProperty(
      required=True,
      verbose_name=ugettext_lazy('Phone Number'))
  phone.help_text = ugettext_lazy(
      'include complete international calling number with country code')

  #====================================================================
  # (private) personal information
  #====================================================================

  #: Required field containing the Role's birthdate (for
  #: determining Program participation eligibility); kept private.
  birth_date = db.DateProperty(
      required=True,
      verbose_name=ugettext_lazy('Birth Date'))
  birth_date.help_text = ugettext_lazy(
      'required for determining program eligibility')

  #: Optional field indicating choice of t-shirt, from XXS to XXXL;
  #: kept private.
  tshirt_size = db.StringProperty(
      verbose_name=ugettext_lazy('T-shirt Size'),
      choices=('XXS', 'XS', 'S', 'M', 'L', 'XL', 'XXL', 'XXXL'))

  #: Optional field indicating choice of t-shirt fit; kept private.
  tshirt_style = db.StringProperty(
      verbose_name=ugettext_lazy('T-shirt Style'),
      choices=('male', 'female'))

  def name(self):
    """Alias 'display_name' Property as 'name' for use in common templates.
    """
    return self.display_name
<|endoftext|>


<commit_before>import unittest, os

from tvunfucker import cfg

class Test_Cfg(unittest.TestCase):
    @classmethod
    def setUp(self):
        dfg = os.path.join(
            os.path.dirname(__file__),
            'tvunfucker/default.cfg'
            )
        self.cfgparser = cfg.ThreeTierConfigParser(
            'test_program_tvuf',
            global_config_path=dfg
            )
        self.cfgparser.initialize()

    def tearDown(self):
        pass

    def test_set_get(self):
        self.cfgparser.set('newsection', 'dasoption', 45, parser='user')
        v = self.cfgparser.get('newsection', 'dasoption')
        self.assertEquals(v, 45)

    def test_set_write_read_get(self):
        self.cfgparser.set('newsection', 'dasoption', False, parser='user')
        self.cfgparser.write_user_config()
        self.cfgparser.read_all()
        v = self.cfgparser.get('newsection', 'dasoption', as_type=bool)
        self.assertEquals(v, False)

    def test_make_get_runtime_cfg(self):
        v = {'cake':{'flavor':'chocolate','candles':5,'is_lie':True}}
        self.cfgparser.import_to_runtime_parser(v)
        self.assertEquals(self.cfgparser.get('cake', 'is_lie'), True)

unittest.main()
<commit_msg>more testing<commit_after>import unittest, os

from tvunfucker import cfg

class Test_Cfg(unittest.TestCase):
    @classmethod
    def setUp(self):
        dfg = os.path.join(
            os.path.dirname(__file__),
            'tvunfucker/default.cfg'
            )
        self.cfgparser = cfg.ThreeTierConfigParser(
            'test_program_tvuf',
            global_config_path=dfg
            )
        self.cfgparser.initialize()

    def tearDown(self):
        pass

    def test_set_get(self):
        self.cfgparser.set('newsection', 'dasoption', 45, parser='user')
        v = self.cfgparser.get('newsection', 'dasoption')
        self.assertEquals(v, 45)

    def test_set_write_read_get(self):
        self.cfgparser.set('newsection', 'dasoption', False, parser='user')
        self.cfgparser.write_user_config()
        self.cfgparser.read_all()
        v = self.cfgparser.get('newsection', 'dasoption', as_type=bool)
        self.assertEquals(v, False)

    def test_make_get_runtime_cfg(self):
        v = {'cake':{'flavor':'chocolate','candles':5,'is_lie':True}}
        self.cfgparser.import_to_runtime_parser(v)
        self.assertEquals(self.cfgparser.get('cake', 'is_lie'), True)

    def test_runtime_cfg_override(self):
        """Test if runtime cfg overrides user cfg properly."""
        v = self.cfgparser.get('cake', 'islie')
        self.assertEquals(v, 'yes')
        self.cfgparser.set('cake', 'islie', 'no', parser='runtime')
        v = self.cfgparser.get('cake', 'islie')
        self.assertEquals(v, 'no')

unittest.main()
<|endoftext|>


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

import os
from decimal import Decimal
from typing import Optional, Union, Sequence

# noinspection PyPep8Naming
from PIL import Image as image

from correios import DATADIR
from correios.exceptions import (InvalidAddressesException, InvalidVolumeInformation,
                                 InvalidTrackingCode, PostingListError)
from .address import Address
from .data import SERVICES
from .user import Service, ExtraService, PostingCard

TRACKING_CODE_SIZE = 13
TRACKING_CODE_NUMBER_SIZE = 8
TRACKING_CODE_PREFIX_SIZE = 2
TRACKING_CODE_SUFFIX_SIZE = 2

class TrackingCode:
    def __init__(self, code: str):
        self.prefix = code[:2].upper()
        self.number = "".join(d for d in code[2:10] if d.isdigit())
        self.suffix = code[-2:].upper()
        self._digit = None

        if len(code) == TRACKING_CODE_SIZE and code[10:11] != " ":
            self._digit = int(code[10:11])

        self._validate()

    def _validate(self):
        if len(self.prefix) != TRACKING_CODE_PREFIX_SIZE or not self.prefix.isalpha():
            raise InvalidTrackingCode("Invalid tracking code prefix {}".format(self.prefix))

        if len(self.suffix) != TRACKING_CODE_SUFFIX_SIZE or not self.suffix.isalpha():
            raise InvalidTrackingCode("Invalid tracking code suffix {}".format(self.suffix))

        if len(self.number) != TRACKING_CODE_NUMBER_SIZE or not self.number.isnumeric():
            raise InvalidTrackingCode("Invalid tracking code number {}".format(self.number))

        if self._digit is not None and self._digit != self.calculate_digit(self.number):
            raise InvalidTrackingCode("Invalid tracking code number {} or digit {} (must be {})".format(
                self.number,
                self._digit,
                self.calculate_digit(self.number))
            )

    def calculate_digit(self, number: str) -> int:
        numbers = [int(c) for c in number if c.isdigit()]

        multipliers = [8, 6, 4, 2, 3, 5, 9, 7]
        module = sum(multipliers[i] * digit for i, digit in enumerate(numbers)) % 11

        if not module:
            return 5

        if module == 1:
            return 0

        return 11 - module

    @property
    def digit(self):
        if self._digit is None:
            self._digit = self.calculate_digit(self.number)
        return self._digit

    @property
    def code(self):
        return self.prefix + self.number + str(self.digit) + self.suffix

    @property
    def nodigit(self):
        return "{}{} {}".format(self.prefix, self.number, self.suffix)

    @property
    def short(self):
        return "{}{}{}".format(self.prefix, self.number, self.suffix)

    @property
    def splitted(self):
        code = self.code
        return "{!s} {!s} {!s} {!s} {!s}".format(code[:2], code[2:5], code[5:8], code[8:11], code[11:])

    def __str__(self):
        return self.code

    def __repr__(self):
        return "<TrackingCode code={!r}>".format(self.code)

class ShippingLabel:
    variable_data_identifier = 51  # Variable data identifier for package
    invoice_template = "{!s}"
    contract_number_template = "{!s}"
    order_template = "{!s}"
    service_name_template = "{!s}"
    volume_template = "{!s}/{!s}"
    weight_template = "{!s}"
    receipt_template = ("Recebedor: ___________________________________________
"
                        "Assinatura: __________________ Documento: _______________")
    sender_header = "DESTINATÁRIO"
    carrier_logo = os.path.join(DATADIR, "carrier_logo.png")
    receiver_data_template = ("{receiver.name}
"
                              "{receiver.street}, {receiver.number}
"
                              "{receiver.complement} {receiver.neighborhood}
"
                              "{receiver.zip_code_display} {receiver.city}/{receiver.state}")

    sender_data_template = ("Remetente: {sender.name}
"
                            "{sender.street}, {sender.number}
"
                            "{sender.complement} - {sender.neighborhood}
"
                            "{sender.zip_code_display} {sender.city}-{sender.state}")

    def __init__(self,
                 posting_card: PostingCard,
                 sender: Address,
                 receiver: Address,
                 service: Union[Service, int],
                 tracking_code: Union[TrackingCode, str],
                 extra_services: Optional[Sequence[Union[ExtraService, str, int]]] = None,
                 logo: Optional[Union[str, image.Image]] = None,
                 order: Optional[str] = "",
                 invoice: Optional[str] = "",
                 value: Optional[Decimal] = None,
                 volume: tuple = (1, 1),
                 weight: int = 0,
                 text: Optional[str] = ""):

        self.posting_card = posting_card

        if sender == receiver:
            raise InvalidAddressesException("Sender and receiver cannot be the same")

        self.sender = sender
        self.receiver = receiver

        if isinstance(service, int):
            service = SERVICES[service]
        self.service = service

        self.extra_services = []
        self.extra_services += self.service.default_extra_services
        if extra_services:
            self.extra_services += [ExtraService.get(es) for es in extra_services]

        if isinstance(tracking_code, str):
            tracking_code = TrackingCode(tracking_code)
        self.tracking_code = tracking_code

        if logo is None:
            logo = os.path.join(DATADIR, "default_logo.png")

        if isinstance(logo, str):
            logo = image.open(logo)

        self.logo = logo

        self.order = order
        self.invoice = invoice

        if value is None:
            value = Decimal("0.00")
        self.value = value

        if len(volume) != 2:
            raise InvalidVolumeInformation("Volume must be a tuple with 2 elements: (number, total)")

        self.volume = volume
        self.weight = weight
        self.text = text
        self.carrier_logo = image.open(self.carrier_logo)

        self.posting_list = None  # TODO

    def __repr__(self):
        return "<ShippingLabel tracking={!r}>".format(str(self.tracking_code))

    @property
    def symbol(self):
        return self.service.symbol_image

    def get_order(self):
        return self.order_template.format(self.order)

    def get_invoice(self):
        return self.invoice_template.format(self.invoice)

    def get_contract_number(self):
        return self.contract_number_template.format(self.posting_card.get_contract_number())

    def get_service_name(self):
        return self.service_name_template.format(self.service.display_name)

    def get_volume(self):
        return self.volume_template.format(*self.volume)

    def get_weight(self):
        return self.weight_template.format(self.weight)

    def get_symbol_filename(self, extension="gif"):
        return self.service.get_symbol_filename(extension)

    def get_tracking_code(self):
        return self.tracking_code.splitted

    def get_receiver_data(self):
        return self.receiver_data_template.format(receiver=self.receiver)

    def get_sender_data(self):
        return self.sender_data_template.format(sender=self.sender)

    def _get_extra_service_info(self) -> str:
        extra_services_numbers = ["00" for _ in range(6)]
        for i, extra_service in enumerate(self.extra_services[:6]):
            extra_services_numbers[i] = "{:02d}".format(extra_service.number)
        return "".join(extra_services_numbers)

    def get_datamatrix_info(self):
        parts = [
            "{!s:>08}".format(self.receiver.zip_code),
            "{!s:>05}".format(self.receiver.zip_code_complement),
            "{!s:>08}".format(self.receiver.zip_code),
            "{!s:>05}".format(self.receiver.zip_code_complement),
            "{!s:>01}".format(self.receiver.zip_code.digit),
            "{!s:>02}".format(self.variable_data_identifier),
            "{!s:>13}".format(self.tracking_code),
            "{!s:>12}".format(self._get_extra_service_info()),
            "{!s:>010}".format(self.posting_card.number),
            "{!s:>05}".format(self.service.code),
            "00",  # TODO: Posting listing group
            "{!s:>05}".format(self.receiver.number),
            "{!s:<20}".format(self.receiver.complement[:20]),
            "{!s:>05}".format(str(int(self.value * 100))),
            "{!s:>012}".format(str(self.receiver.phone)[:12] or "0" * 12),
            "-00.000000",  # TODO: latitude
            "-00.000000",  # TODO: longitude
            "|",
            "{!s:<30}".format(self.text[:30]),
        ]
        return "".join(parts)

class PostingList:
    def __init__(self,
                 customer_id: int):
        self.customer_id = customer_id
        self.closed = False
        self.shipping_labels = {}

    def add_shipping_label(self, shipping_label: ShippingLabel):
        if shipping_label.tracking_code in self.shipping_labels:
            raise PostingListError("Shipping label {!r} alread in posting list".format(shipping_label))

        self.shipping_labels[shipping_label.tracking_code] = shipping_label

    def get_tracking_codes(self):
        return []  # TODO

    def close(self):
        self.closed = True
<commit_msg>Fix sender address in datamatrix info string<commit_after># Copyright 2016 Osvaldo Santana Neto
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
from decimal import Decimal
from typing import Optional, Union, Sequence

# noinspection PyPep8Naming
from PIL import Image as image

from correios import DATADIR
from correios.exceptions import (InvalidAddressesException, InvalidVolumeInformation,
                                 InvalidTrackingCode, PostingListError)
from .address import Address
from .data import SERVICES
from .user import Service, ExtraService, PostingCard

TRACKING_CODE_SIZE = 13
TRACKING_CODE_NUMBER_SIZE = 8
TRACKING_CODE_PREFIX_SIZE = 2
TRACKING_CODE_SUFFIX_SIZE = 2

class TrackingCode:
    def __init__(self, code: str):
        self.prefix = code[:2].upper()
        self.number = "".join(d for d in code[2:10] if d.isdigit())
        self.suffix = code[-2:].upper()
        self._digit = None

        if len(code) == TRACKING_CODE_SIZE and code[10:11] != " ":
            self._digit = int(code[10:11])

        self._validate()

    def _validate(self):
        if len(self.prefix) != TRACKING_CODE_PREFIX_SIZE or not self.prefix.isalpha():
            raise InvalidTrackingCode("Invalid tracking code prefix {}".format(self.prefix))

        if len(self.suffix) != TRACKING_CODE_SUFFIX_SIZE or not self.suffix.isalpha():
            raise InvalidTrackingCode("Invalid tracking code suffix {}".format(self.suffix))

        if len(self.number) != TRACKING_CODE_NUMBER_SIZE or not self.number.isnumeric():
            raise InvalidTrackingCode("Invalid tracking code number {}".format(self.number))

        if self._digit is not None and self._digit != self.calculate_digit(self.number):
            raise InvalidTrackingCode("Invalid tracking code number {} or digit {} (must be {})".format(
                self.number,
                self._digit,
                self.calculate_digit(self.number))
            )

    def calculate_digit(self, number: str) -> int:
        numbers = [int(c) for c in number if c.isdigit()]

        multipliers = [8, 6, 4, 2, 3, 5, 9, 7]
        module = sum(multipliers[i] * digit for i, digit in enumerate(numbers)) % 11

        if not module:
            return 5

        if module == 1:
            return 0

        return 11 - module

    @property
    def digit(self):
        if self._digit is None:
            self._digit = self.calculate_digit(self.number)
        return self._digit

    @property
    def code(self):
        return self.prefix + self.number + str(self.digit) + self.suffix

    @property
    def nodigit(self):
        return "{}{} {}".format(self.prefix, self.number, self.suffix)

    @property
    def short(self):
        return "{}{}{}".format(self.prefix, self.number, self.suffix)

    @property
    def splitted(self):
        code = self.code
        return "{!s} {!s} {!s} {!s} {!s}".format(code[:2], code[2:5], code[5:8], code[8:11], code[11:])

    def __str__(self):
        return self.code

    def __repr__(self):
        return "<TrackingCode code={!r}>".format(self.code)

class ShippingLabel:
    variable_data_identifier = 51  # Variable data identifier for package
    invoice_template = "{!s}"
    contract_number_template = "{!s}"
    order_template = "{!s}"
    service_name_template = "{!s}"
    volume_template = "{!s}/{!s}"
    weight_template = "{!s}"
    receipt_template = ("Recebedor: ___________________________________________
"
                        "Assinatura: __________________ Documento: _______________")
    sender_header = "DESTINATÁRIO"
    carrier_logo = os.path.join(DATADIR, "carrier_logo.png")
    receiver_data_template = ("{receiver.name}
"
                              "{receiver.street}, {receiver.number}
"
                              "{receiver.complement} {receiver.neighborhood}
"
                              "{receiver.zip_code_display} {receiver.city}/{receiver.state}")

    sender_data_template = ("Remetente: {sender.name}
"
                            "{sender.street}, {sender.number}
"
                            "{sender.complement} - {sender.neighborhood}
"
                            "{sender.zip_code_display} {sender.city}-{sender.state}")

    def __init__(self,
                 posting_card: PostingCard,
                 sender: Address,
                 receiver: Address,
                 service: Union[Service, int],
                 tracking_code: Union[TrackingCode, str],
                 extra_services: Optional[Sequence[Union[ExtraService, str, int]]] = None,
                 logo: Optional[Union[str, image.Image]] = None,
                 order: Optional[str] = "",
                 invoice: Optional[str] = "",
                 value: Optional[Decimal] = None,
                 volume: tuple = (1, 1),
                 weight: int = 0,
                 text: Optional[str] = ""):

        self.posting_card = posting_card

        if sender == receiver:
            raise InvalidAddressesException("Sender and receiver cannot be the same")

        self.sender = sender
        self.receiver = receiver

        if isinstance(service, int):
            service = SERVICES[service]
        self.service = service

        self.extra_services = []
        self.extra_services += self.service.default_extra_services
        if extra_services:
            self.extra_services += [ExtraService.get(es) for es in extra_services]

        if isinstance(tracking_code, str):
            tracking_code = TrackingCode(tracking_code)
        self.tracking_code = tracking_code

        if logo is None:
            logo = os.path.join(DATADIR, "default_logo.png")

        if isinstance(logo, str):
            logo = image.open(logo)

        self.logo = logo

        self.order = order
        self.invoice = invoice

        if value is None:
            value = Decimal("0.00")
        self.value = value

        if len(volume) != 2:
            raise InvalidVolumeInformation("Volume must be a tuple with 2 elements: (number, total)")

        self.volume = volume
        self.weight = weight
        self.text = text
        self.carrier_logo = image.open(self.carrier_logo)

        self.posting_list = None  # TODO

    def __repr__(self):
        return "<ShippingLabel tracking={!r}>".format(str(self.tracking_code))

    @property
    def symbol(self):
        return self.service.symbol_image

    def get_order(self):
        return self.order_template.format(self.order)

    def get_invoice(self):
        return self.invoice_template.format(self.invoice)

    def get_contract_number(self):
        return self.contract_number_template.format(self.posting_card.get_contract_number())

    def get_service_name(self):
        return self.service_name_template.format(self.service.display_name)

    def get_volume(self):
        return self.volume_template.format(*self.volume)

    def get_weight(self):
        return self.weight_template.format(self.weight)

    def get_symbol_filename(self, extension="gif"):
        return self.service.get_symbol_filename(extension)

    def get_tracking_code(self):
        return self.tracking_code.splitted

    def get_receiver_data(self):
        return self.receiver_data_template.format(receiver=self.receiver)

    def get_sender_data(self):
        return self.sender_data_template.format(sender=self.sender)

    def _get_extra_service_info(self) -> str:
        extra_services_numbers = ["00" for _ in range(6)]
        for i, extra_service in enumerate(self.extra_services[:6]):
            extra_services_numbers[i] = "{:02d}".format(extra_service.number)
        return "".join(extra_services_numbers)

    def get_datamatrix_info(self):
        parts = [
            "{!s:>08}".format(self.receiver.zip_code),
            "{!s:>05}".format(self.receiver.zip_code_complement),
            "{!s:>08}".format(self.sender.zip_code),
            "{!s:>05}".format(self.sender.zip_code_complement),
            "{!s:>01}".format(self.receiver.zip_code.digit),
            "{!s:>02}".format(self.variable_data_identifier),
            "{!s:>13}".format(self.tracking_code),
            "{!s:>12}".format(self._get_extra_service_info()),
            "{!s:>010}".format(self.posting_card.number),
            "{!s:>05}".format(self.service.code),
            "00",  # TODO: Posting listing group
            "{!s:>05}".format(self.receiver.number),
            "{!s:<20}".format(self.receiver.complement[:20]),
            "{!s:>05}".format(str(int(self.value * 100))),
            "{!s:>012}".format(str(self.receiver.phone)[:12] or "0" * 12),
            "-00.000000",  # TODO: latitude
            "-00.000000",  # TODO: longitude
            "|",
            "{!s:<30}".format(self.text[:30]),
        ]
        return "".join(parts)

class PostingList:
    def __init__(self,
                 customer_id: int):
        self.customer_id = customer_id
        self.closed = False
        self.shipping_labels = {}

    def add_shipping_label(self, shipping_label: ShippingLabel):
        if shipping_label.tracking_code in self.shipping_labels:
            raise PostingListError("Shipping label {!r} alread in posting list".format(shipping_label))

        self.shipping_labels[shipping_label.tracking_code] = shipping_label

    def get_tracking_codes(self):
        return []  # TODO

    def close(self):
        self.closed = True
<|endoftext|>


<commit_before>#!/usr/bin/python

import re
import urllib
import urlparse
from bs4 import BeautifulSoup
from bs4.diagnose import diagnose

url = 'http://www.hannaford.com/catalog/browse_products.cmd'
soupFile = urllib.urlopen(url, 'r+')
soup = BeautifulSoup(soupFile)
##print(soup.prettify())

title_tag = soup.head.title
print title_tag

##This seems to work, but need to look at actual results to determine difference between techniques
subNav_tag = soup.find_all(id = re.compile('subNav').search('id'))
print subNav_tag
print len(subNav_tag)
##current length is 1522

##This function is a filter to search for id attribute with subNav
##Not quite sure how the return statement works right now, but it does
def has_id_subNav(idattr):
	'''
	takes in tag and returns true if 'subNav' is in tag
	'''
	return idattr and re.compile('subNav').search(idattr)
##This creates a list of the tags with subNav id attributes
subNavId = soup.find_all(id=has_id_subNav)
print subNavId
print 'subNavId Length: '+str(len(subNavId))+' tags'
print 'subNav_tag Length: '+str(len(subNav_tag))+' tags'
print 'needs further analysis'

##length currently 152

##[x.decompose() for x in soup('script')]
##[x.decompose() for x in soup('style')]
##print soup.get_text()

##print soup('class = "vert subnav nav1"')

##print soup.find_all(id=has_id_subNav)

##page1File = open('page1File.txt', 'w')
##page1File.write(str(soup))
##page1File.close()

'''
create tree of nodes
each node is a tag
traverse tree downwards
and across
until the desired div is found
store that div
or act on it in some other fashion
repeat process till end of doc/etc
'''

<commit_msg>messing around with the BSoup<commit_after>#!/usr/bin/python

import re
import urllib
import urlparse
from bs4 import BeautifulSoup
from bs4.diagnose import diagnose

url = 'http://www.hannaford.com/catalog/browse_products.cmd'
soupFile = urllib.urlopen(url, 'r+')
soup = BeautifulSoup(soupFile)
##print(soup.prettify())

title_tag = soup.head.title
print title_tag

##This seems to work, but need to look at actual results to determine difference between techniques
subNav_tag = soup.find_all(id = re.compile('subNav'))
##print subNav_tag
print len(subNav_tag)
##current length is 151
subNode_tree = {}
for tag in subNav_tag:
     tmpId = tag.get('id')
##     print tmpId
     tmpId = tmpId.split('-')
##     print tmpId
     subNode_tree[tag] = [child for child in tag.children if child not in ['\n']]

print subNode_tree[subNav_tag[0]]
total = 0
for x in subNode_tree:
        total += len(x.a)
        print x.a
        print x.get('id')
        for y in x.children:
                print y.string
print total
print subNode_tree.keys()
##for x in subNode_tree:
##        print type(x)
##        for tag in x.children:
##                print x
print 'see'
i = 0
for tag in soup.select('ul li'):
        if tag.get('id')==re.compile('subnode'):
                print tag
                print'\n'
                i += 1
print i
##This function is a filter to search for id attribute with subNav
##Not quite sure how the return statement works right now, but it does
def has_id_subNav(idattr):
	'''
	takes in tag and returns true if 'subNav' is in tag
	'''
	return idattr and re.compile('subNav').search(idattr)
##This creates a list of the tags with subNav id attributes
subNavId = soup.find_all(id=has_id_subNav)
##print subNavId
print 'subNavId Length: '+str(len(subNavId))+' tags'
print 'subNav_tag Length: '+str(len(subNav_tag))+' tags'
print 'needs further analysis'

##length currently 152
##now it's 151

##for tag in subNav_tag.descendants:
##	if tag.get('li'):
##		print tag.get('a')

##for parent in soup.a.parents:
##	if parent is None:
##		print parent
##	else:
##		print parent.name
##[x.decompose() for x in soup('script')]
##[x.decompose() for x in soup('style')]
##print soup.get_text()

##print soup('class = "vert subnav nav1"')

##print soup.find_all(id=has_id_subNav)

##page1File = open('page1File.txt', 'w')
##page1File.write(str(soup))
##page1File.close()

'''
create tree of nodes
each node is a tag
traverse tree downwards
and across
until the desired div is found
store that div
or act on it in some other fashion
repeat process till end of doc/etc
'''

<|endoftext|>


<commit_before># Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@hp.com>
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from designate.tests.test_mdns import MdnsTestCase

class MdnsServiceTest(MdnsTestCase):
    def setUp(self):
        super(MdnsServiceTest, self).setUp()

        # Use a random port for MDNS
        self.config(port=0, group='service:mdns')

        self.service = self.start_service('mdns')

    def test_stop(self):
        # NOTE: Start is already done by the fixture in start_service()
        self.service.stop()
<commit_msg>Add more unit tests to mdns service<commit_after># Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@hp.com>
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import binascii
import socket

import dns
import mock

from designate.tests.test_mdns import MdnsTestCase

class MdnsServiceTest(MdnsTestCase):
    def setUp(self):
        super(MdnsServiceTest, self).setUp()

        # Use a random port for MDNS
        self.config(port=0, group='service:mdns')

        self.service = self.start_service('mdns')
        self.addr = ['0.0.0.0', 5556]

    def test_stop(self):
        # NOTE: Start is already done by the fixture in start_service()
        self.service.stop()

    @mock.patch.object(dns.message, 'make_query')
    def test_handle_empty_payload(self, query_mock):
        self.service._handle(self.addr, None)
        query_mock.assert_called_once_with('unknown', dns.rdatatype.A)

    @mock.patch.object(socket.socket, 'sendto', new_callable=mock.MagicMock)
    def test_handle_udp_payload(self, sendto_mock):
        # DNS packet with IQUERY opcode
        payload = "271209000001000000000000076578616d706c6503636f6d0000010001"

        # expected response is an error code REFUSED.  The other fields are
        # id 10002
        # opcode IQUERY
        # rcode REFUSED
        # flags QR RD
        # ;QUESTION
        # example.com. IN A
        # ;ANSWER
        # ;AUTHORITY
        # ;ADDITIONAL
        expected_response = ("271289050001000000000000076578616d706c6503636f6d"
                             "0000010001")

        self.service._handle(self.addr, binascii.a2b_hex(payload))
        sendto_mock.assert_called_once_with(
            binascii.a2b_hex(expected_response), self.addr)
<|endoftext|>


<commit_before>#!/usr/bin/env python3

# This requires a sqlite database dump from
# http://pozniak.pl/dbdump/ody110-sqlite3-v1.db.bz2

# Something that I ran to extract module lists from copy pasted forum posts:
# cat new-list | tr '[' '\n' | tr ',' '\n' | sed -e 's/^[ \t]*//' | sed 's/ x.$//' | sort | uniq | ./market-stuff.py --filter

from collections import namedtuple
import email
import sys
import sqlite3
import urllib.request as urlreq
from xml.dom.minidom import parseString

CHUNK_SIZE = 100
SYSTEM = 'Hemin'
ITEM_LIST = 'items'

Item = namedtuple('Item', ['id', 'name', 'group'])

id2item = {}
name2item = {}

conn = sqlite3.connect('ody110-sqlite3-v1.db')

def get_system_id(name):
    c = conn.cursor()
    c.execute("SELECT itemID from invnames where itemName = ?", (name,))
    return c.fetchone()

system_id = get_system_id(SYSTEM)

def load_items():
    c = conn.cursor()
    c.execute("select typeId, typeName, groupName from invtypes join invgroups on invtypes.groupID = invgroups.groupID")

    for (itemid, name, group) in c:
        item = Item(itemid, name, group)
#        print(item)
        name2item[name] = item
        id2item[itemid] = item

def download_data(ids):
    base_url = 'http://api.eve-central.com/api/marketstat?hours=24&usesystem=%d&' % system_id
    suffix = "&".join("typeid=%d" % i for i in ids)
    url = base_url + suffix
#    print(url)
    s = urlreq.urlopen(url)
    s = "".join(x.decode() for x in s)
#    print(s)

    obj = parseString(s)
    return obj

def chunk(l, size):
    chunked = []
    i = 0
    while i < len(l):
        chunked.append(l[i:i+size])
        i += size
    return chunked

def read_xml_field(node, key):
    return node.getElementsByTagName(key)[0].childNodes[0].data

def handle_data(table, xml):
    items = xml.getElementsByTagName("type")
    for item_report in items:
        i = int(item_report.getAttribute("id"))
        item = id2item[i]

        sell = item_report.getElementsByTagName("sell")[0]
        volume = int(read_xml_field(sell, "volume"))
        min_price = float(read_xml_field(sell, "min"))
        table.append((item.name, volume, min_price, item.group))

def text_output(table):
    for parts in table:
        print("%s: %d at %s (%s)" % parts)

def html_output(table):
    page_template = """
<title>%(system)s market data</title>

<link rel="stylesheet" type="text/css" href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables.css">

Data may be out of date or missing. Items might be in the wrong station. Price shown is the lowest price. If you want more items on here, message sully on IRC with links to lists of items (probably pastebinned).

Want to help out and keep this up-to-date?
Run the poller while ship-spinning in Curse!

%(system)s market

Last updated %(timestamp)s [EVE time], from
eve-central data no more than 24 hours old
at that time.

Item	quantity	price	group

%(table)s

"""

    table_output = ""
    for (name, count, price, group) in table:
        price_fmt = "{:,.2f}".format(price)
        table_output += "
%s	%d	%s	%s
\n" % (name, count, price_fmt, group)

    print(page_template % {
        'system': SYSTEM,
        'timestamp': email.utils.formatdate(usegmt=True),
        'table': table_output
        })

def make_table(formatter):
    item_names = [s.strip() for s in open(ITEM_LIST)]
#    print(item_names)
    item_ids = [name2item[name].id for name in item_names]
#    print(item_ids)

    table = []
    for part in chunk(item_ids, CHUNK_SIZE):
        data = download_data(part)
        handle_data(table, data)

    formatter(table)

def make_poller():
    item_names = [s.strip() for s in open(ITEM_LIST)]
    item_ids = [name2item[name].id for name in item_names]
    print("item_ids = %s;" % str(item_ids))

def filter_input():
    for name in sys.stdin:
        name = name.strip()
        if name in name2item:
            print(name)

def main(args):
    load_items()

    if len(args) > 1 and args[1] == "--filter":
        filter_input()
    elif len(args) > 1 and args[1] == "--poller":
        make_poller()
    elif len(args) > 1 and args[1] == "--text":
        make_table(text_output)
    else:
        make_table(html_output)

if __name__ == '__main__':
    sys.exit(main(sys.argv))
<commit_msg>Generalize the table construction a bit.<commit_after>#!/usr/bin/env python3

# This requires a sqlite database dump from
# http://pozniak.pl/dbdump/ody110-sqlite3-v1.db.bz2

# Something that I ran to extract module lists from copy pasted forum posts:
# cat new-list | tr '[' '\n' | tr ',' '\n' | sed -e 's/^[ \t]*//' | sed 's/ x.$//' | sort | uniq | ./market-stuff.py --filter

from collections import namedtuple
import email
import sys
import sqlite3
import urllib.request as urlreq
from xml.dom.minidom import parseString

CHUNK_SIZE = 100
SYSTEM = 'Hemin'
ITEM_LIST = 'items'

Item = namedtuple('Item', ['id', 'name', 'group'])
Row = namedtuple('Row', ['Item', 'quantity', 'price', 'group'])

id2item = {}
name2item = {}

conn = sqlite3.connect('ody110-sqlite3-v1.db')

def get_system_id(name):
    c = conn.cursor()
    c.execute("SELECT itemID from invnames where itemName = ?", (name,))
    return c.fetchone()

system_id = get_system_id(SYSTEM)

def load_items():
    c = conn.cursor()
    c.execute("select typeId, typeName, groupName from invtypes join invgroups on invtypes.groupID = invgroups.groupID")

    for (itemid, name, group) in c:
        item = Item(itemid, name, group)
#        print(item)
        name2item[name] = item
        id2item[itemid] = item

def download_data(ids):
    base_url = 'http://api.eve-central.com/api/marketstat?hours=24&usesystem=%d&' % system_id
    suffix = "&".join("typeid=%d" % i for i in ids)
    url = base_url + suffix
#    print(url)
    s = urlreq.urlopen(url)
    s = "".join(x.decode() for x in s)
#    print(s)

    obj = parseString(s)
    return obj

def chunk(l, size):
    chunked = []
    i = 0
    while i < len(l):
        chunked.append(l[i:i+size])
        i += size
    return chunked

def read_xml_field(node, key):
    return node.getElementsByTagName(key)[0].childNodes[0].data

def handle_data(table, xml):
    items = xml.getElementsByTagName("type")
    for item_report in items:
        i = int(item_report.getAttribute("id"))
        item = id2item[i]

        sell = item_report.getElementsByTagName("sell")[0]
        volume = int(read_xml_field(sell, "volume"))
        min_price = float(read_xml_field(sell, "min"))
        price_fmted = "{:,.2f}".format(min_price)
        table.append(Row(item.name, volume, price_fmted, item.group))

def text_output(table):
    for parts in table:
        print("%s: %d at %s (%s)" % parts)

def make_row(open_tag, close_tag, entries):
    fmt_string = (open_tag + "%s" + close_tag) * len(entries)
    return fmt_string % entries

def format_table(table):
    table_output = ""
    for entry in table:
        table_output += "
" + make_row("", "	", entry) + "
\n"

    return table_output

def html_output(table):
    page_template = """
<title>%(system)s market data</title>

<link rel="stylesheet" type="text/css" href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables.css">

Data may be out of date or missing. Items might be in the wrong station. Price shown is the lowest price. If you want more items on here, message sully on IRC with links to lists of items (probably pastebinned).

Want to help out and keep this up-to-date?
Run the poller while ship-spinning in Curse!

%(system)s market

Last updated %(timestamp)s [EVE time], from
eve-central data no more than 24 hours old
at that time.

%(header)s

%(table)s

"""

    print(page_template % {
        'system': SYSTEM,
        'header': make_row("", "	", Row._fields),
        'timestamp': email.utils.formatdate(usegmt=True),
        'table': format_table(table)
        })

def make_table(formatter):
    item_names = [s.strip() for s in open(ITEM_LIST)]
#    print(item_names)
    item_ids = [name2item[name].id for name in item_names]
#    print(item_ids)

    table = []
    for part in chunk(item_ids, CHUNK_SIZE):
        data = download_data(part)
        handle_data(table, data)

    formatter(table)

def make_poller():
    item_names = [s.strip() for s in open(ITEM_LIST)]
    item_ids = [name2item[name].id for name in item_names]
    print("item_ids = %s;" % str(item_ids))

def filter_input():
    for name in sys.stdin:
        name = name.strip()
        if name in name2item:
            print(name)

def main(args):
    load_items()

    if len(args) > 1 and args[1] == "--filter":
        filter_input()
    elif len(args) > 1 and args[1] == "--poller":
        make_poller()
    elif len(args) > 1 and args[1] == "--text":
        make_table(text_output)
    else:
        make_table(html_output)

if __name__ == '__main__':
    sys.exit(main(sys.argv))
<|endoftext|>


<commit_before>from datetime import datetime
import re

class BaseField(object):

    name = None

    class InvalidData(Exception):
        """
        Should be raised, when invalid data is passed to the fied for
        serialization or deserialization.
        """
        pass

    def __init__(self, value=None, query_field=None):
        self._evaluate(value)
        self._query_field = query_field

    def _is_string(self, value):
        is_string = ((type(value) is str) or (type(value) is unicode))
        return is_string

    def _evaluate(self, value):
        if (self._is_string(value)):
            self._value = self.serialize(value)
        else:
            self._value = value

    def __get__(self, instance, owner):
        if (instance is None):
            return self
        return self.serialize(instance._data.get(self.name))

    def __set__(self, instance, value):
        self._evaluate(value)

    def serialize(self, value):
        return value

    def deserialize(self):
        return self._value

    def __unicode__(self):
        return self.deserialize()

    def __str__(self):
        return self.__unicode__()

class StringField(BaseField):
    pass

class IntegerField(BaseField):
    def serialize(self, value):
        return int(value)

    def deserialize(self):
        return str(self._value)

class DateTimeField(BaseField):

    _pattern = r'^(\d\d\d\d)-(\d\d)-(\d\d)[\sT](\d\d):(\d\d):(\d\d)'

    def serialize(self, value):
        matches = re.search(self._pattern, value)
        if (matches):
            matches = matches.groups()
            year, month, day, hour, minute, seconds = (
                int(matches[0]), int(matches[1]), int(matches[2]),
                int(matches[3]), int(matches[4]), int(matches[5])
            )
        return datetime(year, month, day, hour, minute, seconds)

    def deserialize(self):
        if (self._value is None):
              return None
        value = '%d-%02d-%02dT%02d:%02d:%02d' % (self._value.year,
                                                 self._value.month,
                                                 self._value.day,
                                                 self._value.hour,
                                                 self._value.minute,
                                                 self._value.second)
        return value

class BooleanField(BaseField):
    """
    Implements field for serializing and desirializing boolean values.
    """
    def serialize(self, value):
        if type(value) is bool:
            return value
        elif type(value) in [str, unicode]:
            # Attempt to match case-insensitive string with True
            if re.match(r'^true$', value, re.IGNORECASE):
                return True
            # Attempt to match case-insensitive string with False
            if re.match(r'^false$', value, re.IGNORECASE):
                return False
        # Let the user know that the given value cannot be serialized into
        # boolean
        err = 'Value "%s" of type "%s", could not be serialized into boolean'
        err = err % (value, type(value))
        raise self.InvalidData(err)

    def deserialize(self):
        if self._value:
            return 'true'
        else:
            return 'false'
<commit_msg>Made `jason.fields.BaseField` raise `NotImplementedError` when accessing `serialize` and `deserialize`<commit_after>from datetime import datetime
import re

class BaseField(object):

    name = None

    class InvalidData(Exception):
        """
        Should be raised, when invalid data is passed to the fied for
        serialization or deserialization.
        """
        pass

    def __init__(self, value=None, query_field=None):
        self._evaluate(value)
        self._query_field = query_field

    def _is_string(self, value):
        is_string = ((type(value) is str) or (type(value) is unicode))
        return is_string

    def _evaluate(self, value):
        if (self._is_string(value)):
            self._value = self.serialize(value)
        else:
            self._value = value

    def __get__(self, instance, owner):
        if (instance is None):
            return self
        return self.serialize(instance._data.get(self.name))

    def __set__(self, instance, value):
        self._evaluate(value)

    def serialize(self, value):
        raise NotImplementedError()

    def deserialize(self):
        raise NotImplementedError()

    def __unicode__(self):
        return self.deserialize()

    def __str__(self):
        return self.__unicode__()

class StringField(BaseField):
    def serialize(self, value):
        return value

    def deserialize(self):
        return self._value

class IntegerField(BaseField):
    def serialize(self, value):
        return int(value)

    def deserialize(self):
        return str(self._value)

class DateTimeField(BaseField):

    _pattern = r'^(\d\d\d\d)-(\d\d)-(\d\d)[\sT](\d\d):(\d\d):(\d\d)'

    def serialize(self, value):
        matches = re.search(self._pattern, value)
        if (matches):
            matches = matches.groups()
            year, month, day, hour, minute, seconds = (
                int(matches[0]), int(matches[1]), int(matches[2]),
                int(matches[3]), int(matches[4]), int(matches[5])
            )
        return datetime(year, month, day, hour, minute, seconds)

    def deserialize(self):
        if (self._value is None):
              return None
        value = '%d-%02d-%02dT%02d:%02d:%02d' % (self._value.year,
                                                 self._value.month,
                                                 self._value.day,
                                                 self._value.hour,
                                                 self._value.minute,
                                                 self._value.second)
        return value

class BooleanField(BaseField):
    """
    Implements field for serializing and desirializing boolean values.
    """
    def serialize(self, value):
        if type(value) is bool:
            return value
        elif type(value) in [str, unicode]:
            # Attempt to match case-insensitive string with True
            if re.match(r'^true$', value, re.IGNORECASE):
                return True
            # Attempt to match case-insensitive string with False
            if re.match(r'^false$', value, re.IGNORECASE):
                return False
        # Let the user know that the given value cannot be serialized into
        # boolean
        err = 'Value "%s" of type "%s", could not be serialized into boolean'
        err = err % (value, type(value))
        raise self.InvalidData(err)

    def deserialize(self):
        if self._value:
            return 'true'
        else:
            return 'false'
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import psycopg2
from mosql.query import insert, select, update, delete
from mosql.db import Database, one_to_dict

class Person(dict):

    db = Database(psycopg2, host='127.0.0.1')

    table_info = {'table': 'person'}
    select = select.breed(table_info)
    insert = insert.breed(table_info)

    def __init__(self, *args, **kargs):

        dict.__init__(self, *args, **kargs)

        row_info = self.table_info.copy()
        row_info['where'] = {'person_id': self['person_id']}
        self.update = update.breed(row_info)
        self.delete = delete.breed(row_info)

    @classmethod
    def create(cls, *args, **kargs):

        person = cls(*args, **kargs)

        with cls.db as cur:
            cur.execute(cls.insert(set=person))

        return person

    @classmethod
    def fetch(cls, person_id):

        with cls.db as cur:

            cur.execute(cls.select(where={'person_id': person_id}))

            if cur.rowcount:
                person = cls(one_to_dict(cur))
            else:
                person = None

        return person

    def save(self):

        with self.db as cur:
            cur.execute(self.update(set=self))

    def remove(self):

        with self.db as cur:
            cur.execute(self.delete())

if __name__ == '__main__':

    dave = {
        'person_id': 'dave',
        'name'     : 'Dave',
    }

    # insert
    p = Person.create(dave)
    print p

    # select
    p = Person.fetch('dave')
    print p

    # update
    p['name'] = 'dave'
    p.save()
    #p = Person.fetch('dave') # if you insist
    print p

    # remove
    p.remove()
    p = Person.fetch('dave')
    print p

<commit_msg>removed a blank line<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import psycopg2
from mosql.query import insert, select, update, delete
from mosql.db import Database, one_to_dict

class Person(dict):

    db = Database(psycopg2, host='127.0.0.1')

    table_info = {'table': 'person'}
    select = select.breed(table_info)
    insert = insert.breed(table_info)

    def __init__(self, *args, **kargs):

        dict.__init__(self, *args, **kargs)

        row_info = self.table_info.copy()
        row_info['where'] = {'person_id': self['person_id']}
        self.update = update.breed(row_info)
        self.delete = delete.breed(row_info)

    @classmethod
    def create(cls, *args, **kargs):

        person = cls(*args, **kargs)

        with cls.db as cur:
            cur.execute(cls.insert(set=person))

        return person

    @classmethod
    def fetch(cls, person_id):

        with cls.db as cur:

            cur.execute(cls.select(where={'person_id': person_id}))

            if cur.rowcount:
                person = cls(one_to_dict(cur))
            else:
                person = None

        return person

    def save(self):

        with self.db as cur:
            cur.execute(self.update(set=self))

    def remove(self):

        with self.db as cur:
            cur.execute(self.delete())

if __name__ == '__main__':

    dave = {
        'person_id': 'dave',
        'name'     : 'Dave',
    }

    # insert
    p = Person.create(dave)
    print p

    # select
    p = Person.fetch('dave')
    print p

    # update
    p['name'] = 'dave'
    p.save()
    #p = Person.fetch('dave') # if you insist
    print p

    # remove
    p.remove()
    p = Person.fetch('dave')
    print p

<|endoftext|>