class Talk(Model): id = UnicodeAttribute(hash_key=True) when = UTCDateTimeAttribute(range_key=True) description = UnicodeAttribute(null=True) speakers = ListAttribute(of=MapAttribute) sponsors = ListAttribute(of=MapAttribute) city = UnicodeAttribute() class Meta: table_name = os.environ['DYNAMO_TALK_TABLE'] host = os.environ['DYNAMO_HOST'] write_capacity_units = 1 read_capacity_units = 1 region = 'us-east-1' def save(self, *args, **kwargs): if self.id is None: self.id = str(uuid4()) if type(self.when) is str: self.when = datetime.datetime.strptime(self.when, '%Y-%m-%dT%H:%M:%S') super().save(*args, **kwargs) def get_json_serializable(self): result = deepcopy(self.attribute_values) result['when'] = self.when.isoformat() return result
class Users(Model): class Meta: read_capacity_units = 1 write_capacity_units = 1 table_name = settings.TABLE_NAME # host = "http://localhost:8000" region = os.getenv("AWS_REGION") aws_access_key_id = os.getenv("AWS_ACCESS_KEY_ID") aws_secret_access_key = os.getenv("AWS_SECRET_ACCESS_KEY") uuid = UnicodeAttribute(hash_key=True) userType = UnicodeAttribute() # userType = UnicodeAttribute(range_key=True) username = UnicodeAttribute(null=False) email = UnicodeAttribute(null=False) firstName = UnicodeAttribute(null=False) lastName = UnicodeAttribute(null=False) phone = UnicodeAttribute(null=False) address = UnicodeAttribute() area = UnicodeAttribute() city = UnicodeAttribute() # days = ListAttribute(default=list, null=True) days = ListAttribute(null=True) time = UnicodeAttribute(null=True) finalRating = UnicodeAttribute(null=True) image = UnicodeAttribute(null=True) skillSet = ListAttribute(of=SkillSet, null=True) appointments = ListAttribute(default=list, null=True) nameIndex = NameIndex() def save(self, **kwargs): return super(Users, self).save(**kwargs)
class Info(MapAttribute): """a example of info "info": { "actors": [ "Daniel VVH", "Chris VVH", "Olivia VVH" ], "release_date": "2017-11-03T11:39:44.659235+0000", "plot": "A re-creation of the merciless 1970s rivalry between Formula One rivals James Hunt and Niki Lauda.", "genres": [ "Action", "Biography", "Drama", "Sport" ], "image_url": "http://hong.com.vn/hong.jpg", "directors": [ "VVH" ], "rating": 8.3, "rank": 2, "running_time_secs": 7380 } """ directors = ListAttribute() release_date = UTCDateTimeAttribute() rating = NumberAttribute() genres = ListAttribute() image_url = UnicodeAttribute() plot = UnicodeAttribute() rank = NumberAttribute() running_time_secs = NumberAttribute() actors = ListAttribute()
class AppUser(Model): """ A user of the Hubmetrix app """ class Meta: table_name = 'hubmetrix-user' region = 'us-west-1' bc_store_hash = UnicodeAttribute(hash_key=True) bc_email = UnicodeAttribute() bc_id = NumberAttribute(range_key=True) bc_store_id = UnicodeAttribute(null=True) bc_access_token = UnicodeAttribute() bc_scope = UnicodeAttribute() bc_webhooks_registered = BooleanAttribute(default=False) bc_webhook_ids = ListAttribute(null=True) bc_deleted = BooleanAttribute(default=False) hs_refresh_token = UnicodeAttribute(null=True) hs_access_token = UnicodeAttribute(null=True) hs_expires_in = UnicodeAttribute(null=True) hs_app_id = UnicodeAttribute(null=True) hs_hub_domain = UnicodeAttribute(null=True) hs_hub_id = UnicodeAttribute(null=True) hs_token_type = UnicodeAttribute(null=True) hs_user = UnicodeAttribute(null=True) hs_user_id = UnicodeAttribute(null=True) hs_scopes = ListAttribute(null=True) hs_properties_exist = BooleanAttribute(default=False) hs_access_token_timestamp = UnicodeAttribute(null=True) cb_subscription_id = UnicodeAttribute(null=True) hm_last_sync_timestamp = UnicodeAttribute(null=True)
def test_untyped_list(self): untyped_list = [{ 'Hello': 'World' }, ['!'], {'foo', 'bar'}, None, "", 0, False] serialized = ListAttribute().serialize(untyped_list) # set attributes are serialized as lists untyped_list[2] = list(untyped_list[2]) assert ListAttribute().deserialize(serialized) == untyped_list
class RetrospectiveV2(Retrospective): class Meta: table_name = 'retrospective-{}'.format(ENVIRONMENT) if ENVIRONMENT == 'test': host = "http://localhost:8008" issues = ListAttribute(of=IssueAttributeV2) groups = ListAttribute(of=GroupAttribute) version = UnicodeAttribute()
class ReceiptLinesModel(Model): class Meta: region = config.AWS_REGION_DEFAULT table_name = 'receipt_lines' host = config.DYNAMODB_LOCAL_URL if is_lambda_local() else None image_hash = UnicodeAttribute(hash_key=True) receipt_lines = ListAttribute(default=None) receipt_lines_tokens = ListAttribute(default=None)
class UserReminder(Model): class Meta: table_name = TABLE_USER_REMINDER region = 'us-east-2' user_id = NumberAttribute(hash_key=True) registration_time = NumberAttribute() time_delta = NumberAttribute(default=DEFAULT_DELTA) active_reminders = ListAttribute(default=list, of=ReminderMap) passive_reminders = ListAttribute(default=list, of=ReminderMap) temp_reminder = ReminderMap(default=ReminderMap)
class Retrospective(Model): class Meta: table_name = 'retrospective-{}'.format(ENVIRONMENT) if ENVIRONMENT == 'test': host = "http://localhost:8008" id = UnicodeAttribute(hash_key=True) name = UnicodeAttribute() current_step = UnicodeAttribute() issues = ListAttribute(of=IssueAttribute) participants = ListAttribute(of=ParticipantAttribute) version = UnicodeAttribute()
class Doc(MapAttribute): aliases = ListAttribute(attr_name="aliases", default=[]) status = UnicodeAttribute(attr_name="status", default="ready") columns = ListAttribute(attr_name="columns", of=Column, default=[]) bucket = UnicodeAttribute(attr_name="bucket", default="") database = UnicodeAttribute(attr_name="database", default="") tablename = UnicodeAttribute(attr_name="tablename", default="") field = UnicodeAttribute(attr_name="field", default="") crawler = UnicodeAttribute(attr_name="crawler", default="") prefix = UnicodeAttribute(attr_name="prefix", default="") replacements = ListAttribute(attr_name="replacements", default=[]) sql = UnicodeAttribute(attr_name="sql", default="") reply = ListAttribute(attr_name="reply", default=[])
class LogMessage(Model): class Meta: table_name = 'hakkuu_message' guild = NumberAttribute(hash_key=True) snowflake = NumberAttribute(range_key=True) author = NumberAttribute() channel = NumberAttribute() revisions = ListAttribute(of=LogRevision) embeds = ListAttribute(of=LogEmbed) attachments = ListAttribute(of=LogAttachment) tts = BooleanAttribute(null=True) deleted = BooleanAttribute(null=True) deleted_by = BooleanAttribute(null=True)
class Office(Model): class Meta: table_name = "OfficeModel" host = "http://localhost:{}".format(environ.get("DOCKER_PORT", 8000)) aws_access_key_id = "my_access_key_id" aws_secret_access_key = "my_secret_access_key" office_id = UUIDAttribute(hash_key=True) address = Location() employees = ListAttribute(of=OfficeEmployeeMap) departments = UnicodeSetAttribute() numbers = NumberSetAttribute() security_number = UnicodeAttribute(null=True) office_times = ListAttribute() cls = DiscriminatorAttribute()
class Poll(Model): """ A DynamoDB User """ class Meta: table_name = DYNAMO_DB_TABLE_NAME key = UnicodeAttribute(hash_key=True) question = UnicodeAttribute() author = JSONAttribute() # option_id is index of the option in the list options = ListAttribute(default=list) votes = MapAttribute(default=dict) # user_id -> option_id users = MapAttribute(default=dict) # user_id -> data # see https://pynamodb.readthedocs.io/en/latest/optimistic_locking.html version = VersionAttribute() # information about poll message in telegram telegram_version = NumberAttribute() telegram_datetime = UTCDateTimeAttribute() def get_users_by_option_id(self): users_by_option_id = {} for user_id in self.votes: option_id = self.votes[user_id] users_by_option_id.setdefault(option_id, []) users_by_option_id[option_id].append(self.users[user_id]) return users_by_option_id
def test_list_comparison(self): condition = ListAttribute(attr_name='foo') == ['bar', 'baz'] placeholder_names, expression_attribute_values = {}, {} expression = condition.serialize(placeholder_names, expression_attribute_values) assert expression == "#0 = :0" assert placeholder_names == {'foo': '#0'} assert expression_attribute_values == {':0': {'L': [{'S' : 'bar'}, {'S': 'baz'}]}}
def test_double_indexing(self): condition = ListAttribute(attr_name='foo')[0][1] == 'bar' placeholder_names, expression_attribute_values = {}, {} expression = condition.serialize(placeholder_names, expression_attribute_values) assert expression == "#0[0][1] = :0" assert placeholder_names == {'foo': '#0'} assert expression_attribute_values == {':0': {'S' : 'bar'}}
class VPCModel(object): VpcId = UnicodeAttribute() State = UnicodeAttribute() CidrBlock = UnicodeAttribute() Tags = ListAttribute() IsDefault = BooleanAttribute() Name = UnicodeAttribute(null=True)
class UserQuestionsModel(BaseModel): class Meta: table_name = gen_table_name("qanda-user-qs-ddb") region = env.AWS_REGION uid = UnicodeAttribute(hash_key=True) qs = ListAttribute(of=UserQuestionLogEntry, default=list)
class BaseTestModel(BaseModel): __update_action_hooks__ = { 'set': { 'non_key_value': 'test_hook_action_generation' } } class Meta(BaseMeta): table_name = 'base' def __init__(self, hash_key=None, range_key=None, **attributes): self.assign_or_update('update_action_hooks', __class__.__update_action_hooks__) super().__init__(hash_key, range_key, **attributes) hash_key = UnicodeAttribute(hash_key=True) range_key = UnicodeAttribute(range_key=True) hook_attribute = UnicodeAttribute(null=True) list_attribute = ListAttribute(default=list()) non_key_value = UnicodeAttribute() numeric_value = NumberAttribute(null=True) unicode_set = UnicodeSetAttribute(default=set()) def test_hook_action_generation(self, value): return [BaseTestModel.hook_attribute.set(value)]
def test_contains_list(self): condition = ListAttribute(attr_name='foo').contains('bar') placeholder_names, expression_attribute_values = {}, {} expression = condition.serialize(placeholder_names, expression_attribute_values) assert expression == "contains (#0, :0)" assert placeholder_names == {'foo': '#0'} assert expression_attribute_values == {':0': {'S' : 'bar'}}
class ReplyIdsByQid(BaseModel): class Meta: table_name = gen_table_name("qanda-reply-ids-ddb") region = env.AWS_REGION qid = UnicodeAttribute(hash_key=True) rids = ListAttribute(of=GenericPointer, default=list)
def test_contains_attribute(self): condition = ListAttribute(attr_name='foo').contains(Path('bar')) placeholder_names, expression_attribute_values = {}, {} expression = condition.serialize(placeholder_names, expression_attribute_values) assert expression == "contains (#0, #1)" assert placeholder_names == {'foo': '#0', 'bar': '#1'} assert expression_attribute_values == {}
class TrackMap(MapAttribute): id = UnicodeAttribute() name = UnicodeAttribute() album_id = UnicodeAttribute() album_name = UnicodeAttribute() artist_id = UnicodeAttribute() artist_name = UnicodeAttribute() duration = NumberAttribute() listeners = NumberAttribute() playback_date = UnicodeAttribute() playcount = UnicodeAttribute() reproduction = NumberAttribute() total_tracks = NumberAttribute() tags = ListAttribute() genres = ListAttribute() release_date = UnicodeAttribute()
class RumorModel(Model): class Meta: region = setting.region if setting.region else 'ap-northeast-1' table_name = setting.rumor_ddb_table if setting.rumor_ddb_table else 'stg-rumor_source' if setting.role: credentials = gen_sts_credentials(setting) aws_access_key_id = credentials["AccessKeyId"] aws_secret_access_key = credentials["SecretAccessKey"] aws_session_token = credentials["SessionToken"] id = UnicodeAttribute(hash_key=True) clarification = UnicodeAttribute(null=True) preface = UnicodeAttribute(null=True) create_date = UnicodeAttribute(null=True) link = UnicodeAttribute(null=True) rumors = ListAttribute(null=True) source = UnicodeAttribute(null=True) title = UnicodeAttribute(null=True) original_title = UnicodeAttribute(null=True) image_link = UnicodeAttribute(null=True) tags = UnicodeAttribute(null=True) sensitive_categories = UnicodeAttribute(null=True) rating = UnicodeAttribute(null=True) source_create_date_index = SourceCreateDateIndex()
def test_list_of_map_with_of_and_custom_attribute(self, mocker): class CustomMapAttribute(MapAttribute): custom = NumberAttribute() def __eq__(self, other): return self.custom == other.custom serialize_mock = mocker.spy( CustomMapAttribute.custom, 'serialize', ) deserialize_mock = mocker.spy(CustomMapAttribute.custom, 'deserialize') attribute1 = CustomMapAttribute() attribute1.custom = 1 attribute2 = CustomMapAttribute() attribute2.custom = 2 inp = [attribute1, attribute2] list_attribute = ListAttribute(default=[], of=CustomMapAttribute) serialized = list_attribute.serialize(inp) deserialized = list_attribute.deserialize(serialized) assert deserialized == inp assert serialize_mock.call_args_list == [call(1), call(2)] assert deserialize_mock.call_args_list == [call('1'), call('2')]
def test_should_list_convert_list_of_map(): class Address(MapAttribute): latitude = NumberAttribute(null=False) longitude = NumberAttribute(null=False) address = UnicodeAttribute() assert_attribute_conversion(ListAttribute(of=Address), ListOfMapToObject)
def test_list_of_map_with_of(self): class Person(MapAttribute): name = UnicodeAttribute() age = NumberAttribute() def __lt__(self, other): return self.name < other.name def __eq__(self, other): return (self.name == other.name and self.age == other.age) person1 = Person() person1.name = 'john' person1.age = 40 person2 = Person() person2.name = 'Dana' person2.age = 41 inp = [person1, person2] list_attribute = ListAttribute(default=[], of=Person) serialized = list_attribute.serialize(inp) deserialized = list_attribute.deserialize(serialized) assert sorted(deserialized) == sorted(inp)
class PaintingModel(Model): class Meta: table_name = "painting" episode = UnicodeAttribute(hash_key=True) title = UnicodeAttribute() colors = ListAttribute()
def test_serialize_null(self): string_set_list_attribute = ListAttribute(of=UnicodeSetAttribute) list_with_empty_set = [{'foo'}, {}, None] serialized = string_set_list_attribute.serialize(list_with_empty_set) assert string_set_list_attribute.deserialize(serialized) == [{'foo'}, None, None]
class Game(BaseModel): class Meta(BaseModel.Meta): pass game_id = UnicodeAttribute( hash_key=True, attr_name="pk", default_for_new=str(uuid4()) ) secret = UnicodeAttribute(default_for_new="".join(choices(COLORS, k=TOTAL_LETTERS))) tries_left = NumberAttribute(default_for_new=MAX_TRIES) created_at = UTCDateTimeAttribute(default_for_new=datetime.utcnow()) is_solved = BooleanAttribute(default_for_new=False) guesses = ListAttribute(of=Guess, null=True, default=[]) def check_win_condition(self, guess: Guess) -> None: if guess.combination == self.secret: self.is_solved = True def get_info(self) -> dict: return {k: v for k, v in self.to_dict().items() if k != "secret"} def save_guess(self, guess: Guess): self.update( actions=[ Game.guesses.set((Game.guesses | []).append([guess])), Game.tries_left.set(Game.tries_left - 1), Game.is_solved.set(self.is_solved), ] ) def is_playable(self) -> bool: if not self.is_solved and self.tries_left: return True return False def get_black_and_white_pegs(self, guess: Guess) -> Tuple[int, int]: combination_cp = guess.combination secret_cp = self.secret black_pegs_counter = 0 black_pegs_indexes = [] white_pegs_counter = 0 for i, letter in enumerate(self.secret): if guess.combination[i] == letter: black_pegs_counter += 1 black_pegs_indexes.append(i) black_pegs_indexes.reverse() for index in black_pegs_indexes: combination_cp = combination_cp[:index] + combination_cp[index + 1 :] secret_cp = secret_cp[:index] + secret_cp[index + 1 :] for letter in combination_cp: if letter in secret_cp: white_pegs_counter += 1 return black_pegs_counter, white_pegs_counter
def test_list_type_error(self): string_list_attribute = ListAttribute(of=UnicodeAttribute) with pytest.raises(ValueError): string_list_attribute.serialize([MapAttribute(foo='bar')]) with pytest.raises(TypeError): string_list_attribute.deserialize([{'M': {'foo': {'S': 'bar'}}}])