Skip to content

Commit

Permalink
Version 0.1.
Browse files Browse the repository at this point in the history
  • Loading branch information
omarish committed Feb 5, 2018
1 parent d5c0f29 commit 4eb2eaf
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 26 deletions.
22 changes: 12 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,21 @@ done before officially releasing on PyPI.
```python
import mutations

class EmailToBouncedMessage(mutations.Mutation):
class UserSignup(mutations.Mutation):
"""Define the inputs to your mutation here. """
email = mutations.fields.CharField(required=True)
send_welcome_email = mutations.fields.Boolean(required=False, default=False)
full_name = mutations.fields.CharField(required=True)
send_welcome_email = mutations.fields.Boolean(required=False, default=True)

def validate_email_object(self):
def validate_email_address(self):
"""Custom validation for a field.
If you encounter any validation errors and want to raise, you should
raise mutation.ValidationError or some sublcass thereof. Otherwise, it
assumes there were no problems.
Any function beginning with `validate_` is assumed to be a validator function.
Any function beginning with `validate_` is assumed to be a validator
function and will be run before the mutation can execute.
"""
if not self.email.is_valid():
raise mutations.ValidationError("email_not_valid", "Email is not valid.")
Expand All @@ -41,27 +44,26 @@ class EmailToBouncedMessage(mutations.Mutation):
This method does the heavy lifting. You can call it by calling .run() on
your mutation class.
"""
new_object = "this is the new object"
user = User.objects.create(email=self.email, name=self.full_name)
if self.send_welcome_email:
# You can access the inputs here, like this.
PersonalEmailServer.deliver(recipient = self.email)

return new_object
return user
```

## Calling Commands

```python
>>> result = EmailToBouncedMessage.run(email=email, send_welcome_email=True)
>>> result = EmailToBouncedMessage.run(email=email, full_name="Bob Boblob")
>>> result.success
True
>>> result.value
"this is the new object"
<User id=...>
>>> result.errors
```

```python
>>> result = EmailToBouncedMessage.run(email = None)
>>> result = EmailToBouncedMessage.run(email=None)
>>> result.success
False
>>> result.errors
Expand Down
31 changes: 31 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# TODO:

List of things we need to do/fix before releasing on PyPI:

### General

- [ ] Make sure you cannot create a field called "inputs"
- [ ] Make sure it raies if you give it a kwarg it doesn't know about.
- [ ] Think of a better way to pass exceptions. I don't like passing the
`nameduple` in the Exception.

- [ ] Support for Python 2.X.
- [ ] Update README and provide more useful examples.
- [ ] Put test requirements into `test-requirements.txt`
- [ ] Make execute an `@abstractmethod`, so that an error gets raised if
you don't define `execute` in your mutation subclass.
- [ ] Release on pypi.
- [ ] Support for running commands in an atomic (all or nothing) fashion,
perhaps using a contextmanager.
- [x] Create setup.py file
- [x] Add `__version__`
- [x] Test that exceptions can be raised when you `run`.


### Testing

- [ ] Make sure default values get overridden if there's a user-provided value.
- [ ] Make sure command fails if you provide unexpected inputs.
- [ ] Make sure `Mutation.__getattr__` raises if you ask it for something that does not exist.


2 changes: 1 addition & 1 deletion mutations/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from .core import Mutation

__version__ = '0.1.0'
__version__ = '0.1.0'
4 changes: 3 additions & 1 deletion mutations/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

Result = namedtuple('Result', ['success', 'return_value', 'errors'])


class MutationBase(type):
def __new__(mcs, name, bases, attrs):
attrs.update({
Expand All @@ -30,9 +31,10 @@ def __new__(mcs, name, bases, attrs):
for v in extra_validator_list:
validator = attrs.pop(v)
attrs['extra_validators'][v].extend(wrap(validator))

return super().__new__(mcs, name, bases, attrs)


class Mutation(metaclass=MutationBase):
def __init__(self, name, inputs=None):
self.name = name
Expand Down
12 changes: 8 additions & 4 deletions mutations/error.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
from collections import UserDict, namedtuple


class MutationError(Exception):
pass


class ErrorDict(UserDict):
def __init__(self, *args, default_factory=list, **kwargs):
self.default_factory = default_factory
Expand All @@ -11,6 +16,8 @@ def __getitem__(self, k):
return self.data[k]

def __add__(self, other):
if self.default_factory != other.default_factory:
raise MutationError("Cannot add two ErrorDicts with different default_factories.")
context = {}
context.update(self)
for key, val in other.items():
Expand All @@ -25,12 +32,9 @@ def is_empty(self):
return not bool(self.data)


class MutationError(Exception):
pass


ErrorBody = namedtuple('ErrorBody', ['err', 'msg'])


class ValidationError(MutationError):
def __init__(self, err=None, msg=None, *args, **kwargs):
self.err = err
Expand Down
2 changes: 1 addition & 1 deletion mutations/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@ def __init__(self, instance_of, *args, **kwargs):

@property
def validators(self):
return validators.InstanceValidator(instance_of=self.instance_of)
return validators.InstanceValidator(instance_of=self.instance_of)
7 changes: 0 additions & 7 deletions mutations/sample.py

This file was deleted.

2 changes: 1 addition & 1 deletion mutations/util.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
def wrap(item):
if not isinstance(item, (list, tuple)):
return [item]
return item
return item
2 changes: 1 addition & 1 deletion mutations/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@ def is_valid(self, *args, **kwargs):

class SavedObjectValidator(ValidatorBase):
def is_valid(self, obj):
return obj.pk is not None and obj.pk != ''
return obj.pk is not None and obj.pk != ''

0 comments on commit 4eb2eaf

Please sign in to comment.