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

"""This example demonstrates some of DictShield's validation abilities.
"""

from dictshield.base import DictPunch
from dictshield.document import Document
from dictshield.fields import MD5Field, StringField
import hashlib


###
### Basic User model
###

class User(Document):
    _public_fields = ['name', 'bio']
    
    secret = MD5Field()
    name = StringField(required=True, max_length=50)
    bio = StringField(max_length=100)

    def set_password(self, plaintext):
        hash_string = hashlib.md5(plaintext).hexdigest()
        self.secret = hash_string


###
### Manually create an instance
###

### Create instance with bogus password
u = User()
u.secret = 'whatevz'
u.name = 'test hash'

### Validation will fail because u.secret does not contain an MD5 hash
print '  Attempting validation on:\n\n    %s\n' % (u.to_json())
try:
    u.validate()
    print '  Validation passed\n'
except DictPunch, dp:
    print '  DictPunch caught: %s\n' % (dp)
    

### Set the password *correctly* using our `set_password` function
u.set_password('<PASSWORD>')
print '  Adjusted invalid data and trying again on:\n\n    %s\n' % (u.to_json())
try:
    u.validate()
    print '  Validation passed\n'
except DictPunch, dp:
    print '  DictPunch caught: %s (This section wont actually run)\n' % (dp)


###
### Instantiate an instance with this data
###
 
total_input = {
    'secret': '<KEY>',
    'name': 'J2D2',
    'bio': 'J2D2 loves music',
    'rogue_field': 'MWAHAHA',
}

### Checking for any failure. Exception thrown on first failure.
print '  Attempting validation on:\n\n    %s\n' % (total_input)
try:
    User.validate_class_fields(total_input)
    print 'Validation passed'
except DictPunch, dp:
    print('DictPunch caught: %s' % (dp))
print '  After validation:\n\n    %s\n' % (total_input)


### Check all fields and collect all failures
exceptions = User.validate_class_fields(total_input, validate_all=True)

if len(exceptions) == 0:
    print 'Validation passed\n'
else:
    print '%s exceptions found\n\n    %s\n' % (len(exceptions),
                                               [str(e) for e in exceptions])


###
### Field Security
###

# Add the rogue field back to `total_input`
total_input['rogue_field'] = 'MWAHAHA'

user_doc = User(**total_input)
print '  Document as Python:\n    %s\n' % (user_doc.to_python())
safe_doc = User.make_json_ownersafe(user_doc)
print '  Owner safe doc:\n    %s\n' % (safe_doc)
public_safe_doc = User.make_json_publicsafe(user_doc)
print '  Public safe doc:\n    %s\n' % (public_safe_doc)
<commit_msg>Finished up the validation demos documentation<commit_after>#!/usr/bin/env python

"""This example demonstrates some of DictShield's validation abilities.

Below is a `User` model that has a function for setting the secret field, which
is just an MD5.

Notice that the validation classmethod's remove rogue fields, similar to using
dictionary to instantiate instances.

This demo also introduces `_public_fields`.  Fields suitable for sharing with
the world can be listed here, making it a whitelist.

A blacklist is available by adding a list called `_private_fields`.  Any fields
listed will not be available to the owner of the document.  The concepts of
`public` and `owner` are implicit by the values in both the whitelist and the
blacklist.

Here is what the output looks like.

    Attempting validation on:
    
        {"_types": ["User"], "secret": "whatevz", "name": "test hash", "_cls": "User"}
    
    DictPunch caught: MD5 value is wrong length - secret(whatevz)
    
    Adjusted invalid data and trying again on:
    
        {"_types": ["User"], "secret": "<KEY>", "name": "test hash", "_cls": "User"}
    
    Validation passed
    
    Attempting validation on:
    
        {'rogue_field': 'MWAHAHA', 'bio': 'J2D2 loves music', 'secret': '<KEY>', 'name': 'J2D2'}
    
    Validation passed
    After validation:
    
        {'bio': 'J2D2 loves music', 'secret': '<KEY>', 'name': 'J2D2'}
    
    Validation passed
    
    Document as Python:
        {'_types': ['User'], 'bio': u'J2D2 loves music', 'secret': '<KEY>', 'name': u'J2D2', '_cls': 'User'}
    
    Owner safe doc:
        {"bio": "J2D2 loves music", "secret": "<KEY>", "name": "J2D2"}
    
    Public safe doc:
        {"bio": "J2D2 loves music", "name": "J2D2"}
"""

from dictshield.base import DictPunch
from dictshield.document import Document
from dictshield.fields import MD5Field, StringField
import hashlib


###
### Basic User model
###

class User(Document):
    _public_fields = ['name', 'bio']
    
    secret = MD5Field()
    name = StringField(required=True, max_length=50)
    bio = StringField(max_length=100)

    def set_password(self, plaintext):
        hash_string = hashlib.md5(plaintext).hexdigest()
        self.secret = hash_string


###
### Manually create an instance
###

### Create instance with bogus password
u = User()
u.secret = 'whatevz'
u.name = 'test hash'

### Validation will fail because u.secret does not contain an MD5 hash
print 'Attempting validation on:\n\n    %s\n' % (u.to_json())
try:
    u.validate()
    print 'Validation passed\n'
except DictPunch, dp:
    print 'DictPunch caught: %s\n' % (dp)
    

### Set the password *correctly* using our `set_password` function
u.set_password('<PASSWORD>')
print 'Adjusted invalid data and trying again on:\n\n    %s\n' % (u.to_json())
try:
    u.validate()
    print 'Validation passed\n'
except DictPunch, dp:
    print 'DictPunch caught: %s (This section wont actually run)\n' % (dp)


###
### Instantiate an instance with this data
###
 
total_input = {
    'secret': '<KEY>',
    'name': 'J2D2',
    'bio': 'J2D2 loves music',
    'rogue_field': 'MWAHAHA',
}

### Checking for any failure. Exception thrown on first failure.
print 'Attempting validation on:\n\n    %s\n' % (total_input)
try:
    User.validate_class_fields(total_input)
    print 'Validation passed'
except DictPunch, dp:
    print('DictPunch caught: %s' % (dp))
print 'After validation:\n\n    %s\n' % (total_input)


### Check all fields and collect all failures
exceptions = User.validate_class_fields(total_input, validate_all=True)

if len(exceptions) == 0:
    print 'Validation passed\n'
else:
    print '%s exceptions found\n\n    %s\n' % (len(exceptions),
                                               [str(e) for e in exceptions])


###
### Field Security
###

# Add the rogue field back to `total_input`
total_input['rogue_field'] = 'MWAHAHA'

user_doc = User(**total_input)
print 'Document as Python:\n    %s\n' % (user_doc.to_python())
safe_doc = User.make_json_ownersafe(user_doc)
print 'Owner safe doc:\n    %s\n' % (safe_doc)
public_safe_doc = User.make_json_publicsafe(user_doc)
print 'Public safe doc:\n    %s\n' % (public_safe_doc)

{'fraction_non_alphanumeric': 0.13225331369661267, 'fraction_numerical': 0.007363770250368188, 'mean_word_length': 3.539438502673797, 'pattern_counts': {'":': 13, '<': 12, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3470244', 'n_tokens_mistral': 2273, 'n_tokens_neox': 2202, 'n_words': 691}