Skip to content

Instantly share code, notes, and snippets.

@tiagopog
Last active February 28, 2021 12:23
Show Gist options
  • Select an option

  • Save tiagopog/9114513e3a1ce8e3d8dda76fa1ee492d to your computer and use it in GitHub Desktop.

Select an option

Save tiagopog/9114513e3a1ce8e3d8dda76fa1ee492d to your computer and use it in GitHub Desktop.

Revisions

  1. tiagopog revised this gist Feb 28, 2021. 1 changed file with 81 additions and 1 deletion.
    82 changes: 81 additions & 1 deletion decorators.py
    Original file line number Diff line number Diff line change
    @@ -59,4 +59,84 @@ def first_letter(word):
    # double = type_check(int)(double)

    print(first_letter('Hello World'))
    first_letter(['Not', 'A', 'String'])
    first_letter(['Not', 'A', 'String'])


    import time
    from datetime import datetime


    def log(func):
    print(f"logging: {func}")
    return func


    @log
    def foo():
    return "foo"


    foo()


    def double(func) -> int:
    def decorated(*args):
    return func(*args) * 2

    return decorated


    @double
    def calculate(x, y):
    return x + y


    @double
    def new_calculate(x, y, z):
    return x + y + z


    print(calculate(1, 2))
    print(new_calculate(1, 2, 3))


    def memoize(func):
    memoized = {}

    def decorated(*args, **kwargs):
    print(locals())
    if func in memoized:
    result = memoized.get(func)
    else:
    result = func(*args, **kwargs)
    memoized[func] = result

    return result

    return decorated


    @memoize
    def expensive_calculation():
    time.sleep(2)
    return 42


    print(datetime.now())
    print(expensive_calculation())
    print(datetime.now())
    print(expensive_calculation())
    print(datetime.now())


    @memoize
    def another_expensive_calculation():
    time.sleep(2)
    return 42


    print(datetime.now())
    print(another_expensive_calculation())
    print(datetime.now())
    print(another_expensive_calculation())
    print(datetime.now())
  2. tiagopog revised this gist Jun 22, 2020. 1 changed file with 11 additions and 0 deletions.
    11 changes: 11 additions & 0 deletions decorators.py
    Original file line number Diff line number Diff line change
    @@ -2,6 +2,17 @@
    # With no arguments
    ##

    def upcase(function):
    def decorate():
    return function().upper()
    return decorate

    @upcase
    def foo(): return 'foo'

    foo() #=>'FOO'


    def call_twice(old_function):
    def new_function(arg):
    for _ in range(2):
  3. tiagopog revised this gist Jun 15, 2020. 1 changed file with 79 additions and 0 deletions.
    79 changes: 79 additions & 0 deletions context_manages.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,79 @@
    ##
    # Example 1: simulate opening and closing resources after is usage.
    ##
    class Operation(object):
    def __init__(self):
    print('Initializing...')
    self.status = 'initial'

    def __enter__(self):
    print('Opening...')
    self.status = 'open'
    return self

    def __exit__(self, type, value, traceback):
    print('Closing...')
    self.status = 'closed'
    print('Status: {}'.format(self.status))
    # print('Type: {}'.format(type))
    # print('Traceback: {}'.format(traceback))
    # return True


    with Operation() as operation:
    print('Running...')
    print('Status: {}'.format(operation.status))
    # raise NotImplementedError('foo')


    ##
    # Example 2: imitate the TestCase.assertRaises() method.
    ##
    class UnitTest(object):
    def assertRaises(self, exception):
    self.exception = exception
    return self

    def __enter__(self):
    return self.exception

    def __exit__(self, type, value, traceback):
    if self.exception == type:
    print('Exception mached!')
    return True
    else:
    print('Exception not mached or not raised!')
    return False


    test = UnitTest()

    with test.assertRaises(NotImplementedError) as error:
    raise NotImplementedError

    with test.assertRaises(NotImplementedError) as error:
    print('Not raising any exception...')

    ##
    # Example 3: try using the contextmanager decorator + generator
    ##
    from contextlib import contextmanager


    class UnitTestPlus(object):
    @contextmanager
    def assertRaises(self, exception):
    try:
    yield exception
    print('Exception not mached or not raised!')
    except exception:
    print('Exception mached!')


    test = UnitTestPlus()

    with test.assertRaises(NotImplementedError) as error:
    raise NotImplementedError

    with test.assertRaises(NotImplementedError) as error:
    print('Not raising any exception...')
  4. tiagopog revised this gist Jun 5, 2019. 1 changed file with 168 additions and 0 deletions.
    168 changes: 168 additions & 0 deletions test_example.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,168 @@
    from unittest import TestCase
    from mock import Mock, patch

    from backend.common.services import BaseService, OperationResult


    class KnownError(Exception):
    pass


    class UnknownError(Exception):
    pass


    def raise_known_error():
    raise KnownError('You should catch me!')


    def raise_unknown_error():
    raise UnknownError('You will not catch me!')


    class ServiceMock(BaseService):
    known_exceptions = (KnownError)

    def process(self):
    return self.params


    class OperationResultTest(TestCase):

    def setUp(self):
    self.service = ServiceMock({ 'foo': 'bar' })
    self.data = self.service.process()

    def test_constructor(self):
    result = OperationResult(data=self.data, source=self.service)

    self.assertEqual(self.data, result.data)
    self.assertEqual(self.service, result.source)
    self.assertEqual(self.service.errors, result.errors)
    self.assertEqual(self.service.failed_objects, result.failed_objects)
    self.assertEqual(self.service.processed, result.processed)

    def test_when_not_processed(self):
    self.service.processed = False
    result = OperationResult(data=self.data, source=self.service)

    self.assertFalse(result.success())
    self.assertTrue(result.fail())

    def test_when_processed_without_errors(self):
    self.service.processed = True
    result = OperationResult(data=self.data, source=self.service)

    self.assertTrue(result.success())
    self.assertFalse(result.fail())
    self.assertFalse(result.source.errors)

    def test_when_processed_with_dict_errors(self):
    self.service.processed = True
    self.service.errors = { 'foo' : 'foo is not bar' }
    result = OperationResult(data=self.data, source=self.service)

    self.assertFalse(result.success())
    self.assertTrue(result.fail())
    self.assertTrue(result.source.errors)

    def test_when_processed_with_list_errors(self):
    self.service.processed = True
    self.service.errors = ['foo is not bar']
    result = OperationResult(data=self.data, source=self.service)

    self.assertFalse(result.success())
    self.assertTrue(result.fail())
    self.assertTrue(result.source.errors)


    class BaseServiceTest(TestCase):

    def setUp(self):
    self.service = ServiceMock(
    params={ 'foo': 'bar' },
    foo_required=True,
    bar_allowed=False
    )

    def test_constructor(self):
    self.assertEqual(None, self.service.raw_result)
    self.assertEqual(None, self.service.errors)
    self.assertEqual([], self.service.failed_objects)
    self.assertEqual('bar', self.service.params['foo'])

    self.assertFalse(self.service.processed)
    self.assertFalse(self.service.bar_allowed)
    self.assertTrue(self.service.foo_required)

    @patch('backend.common.tests.tests_services.ServiceMock.execute', Mock())
    def test_do_execute_call(self):
    ServiceMock.do_execute({ 'foo': 'bar' })
    ServiceMock.execute.assert_called_with()

    def test_do_process_return(self):
    result = ServiceMock.do_execute({ 'foo': 'bar' })
    self.assertIsInstance(result, OperationResult)

    @patch('backend.common.tests.tests_services.ServiceMock.process', Mock())
    def test_do_process_call(self):
    ServiceMock.do_process({ 'foo': 'bar' })
    ServiceMock.process.assert_called_with()

    def test_do_process_return(self):
    result = ServiceMock.do_process({ 'foo': 'bar' })
    self.assertIsNotNone(result)

    @patch('backend.common.tests.tests_services.ServiceMock.process', Mock())
    def test_process_call(self):
    ServiceMock().execute()
    ServiceMock.process.assert_called_with()

    def test_operation_result(self):
    result = self.service.execute()
    self.assertIsInstance(result, OperationResult)

    def test_processed(self):
    self.assertFalse(self.service.processed)
    self.service.execute()
    self.assertTrue(self.service.processed)


    class BaseServiceWithErrorsTest(TestCase):

    def setUp(self):
    self.service = ServiceMock(params={ 'foo': 'bar' })

    @patch('backend.common.tests.tests_services.ServiceMock.process', side_effect=raise_known_error)
    def test_execute_with_known_exceptions(self, _process):
    result = self.service.execute()
    self.assertFalse(result.success())
    self.assertEqual('You should catch me!', result.errors[0])
    self.assertIsInstance(result.failed_objects[0], KnownError)


    @patch('backend.common.tests.tests_services.ServiceMock.process', side_effect=raise_unknown_error)
    def test_execute_with_unknown_exceptions(self, _process):
    self.assertRaises(UnknownError, self.service.execute)
    self.assertTrue(self.service.processed)
    self.assertIsNone(self.service.errors)
    self.assertIsNone(self.service.raw_result)
    self.assertEqual([], self.service.failed_objects)

    @patch('backend.common.tests.tests_services.ServiceMock.process', side_effect=raise_known_error)
    def test_process_with_known_exceptions(self, _process):
    self.assertRaises(KnownError, self.service.process)
    self.assertFalse(self.service.processed)
    self.assertIsNone(self.service.errors)
    self.assertIsNone(self.service.raw_result)
    self.assertEqual([], self.service.failed_objects)

    @patch('backend.common.tests.tests_services.ServiceMock.process', side_effect=raise_unknown_error)
    def test_process_with_unknown_exceptions(self, _process):
    self.assertRaises(UnknownError, self.service.process)
    self.assertFalse(self.service.processed)
    self.assertIsNone(self.service.errors)
    self.assertIsNone(self.service.raw_result)
    self.assertEqual([], self.service.failed_objects)


  5. tiagopog revised this gist Jun 5, 2019. 1 changed file with 129 additions and 0 deletions.
    129 changes: 129 additions & 0 deletions code_documentation_sample.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,129 @@
    import abc


    class OperationResult(object):
    """
    Result object for structuring and standarizing the way the application
    interacts with service objects results.
    """

    def __init__(self, data, source):
    """
    Result object constructor.
    :param any data: the operation result of a service object.
    against the fields defined on the `Service` class
    :param Service, BaseService source: service object that
    originated the result.
    """
    self.data = data
    self.source = source
    self.errors = source.errors
    self.failed_objects = source.failed_objects
    self.processed = source.processed

    def success(self):
    """
    Returns whether the service object operation has succeed.
    :return: boolean
    """
    return self.processed and not self.source.errors

    def fail(self):
    """
    Returns whether the service object operation has failed.
    :return boolean:
    """
    return not self.success()


    class BaseService(object):
    """
    Extends and creates an abstraction for the :class:`Service` class so that
    base logic for service objects can be added here without needing to directly
    modify the `source` lib.
    """

    """
    :cvar tuple known_exceptions: static list of kown operation expections that
    can be raise while calling :meth:`process`. This class var is expected
    to be overridden in subclasses where custom operation errors can be
    raised.
    """
    known_exceptions = ()

    def __init__(self, params={}, **kwargs):
    """
    Service object constructor.
    :param dictionary params: data parameters for `Service`, checked
    against the fields defined on the `Service` class.
    :param dictionary **kwargs: any additional parameters `Service` may
    need, can be an empty dictionary.
    """
    self.raw_result = None
    self.processed = False
    self.errors = None
    self.failed_objects = []
    self.params = params

    for key, value in kwargs.iteritems():
    setattr(self, key, value)

    @classmethod
    def do_execute(cls, params={}, **kwargs):
    """
    Runs the service's main operation in a "safe" way i.e. all known
    expections will be catched.
    :param dictionary params: data parameters for `Service`, checked
    against the fields defined on the `Service` class.
    :param dictionary **kwargs: any additional parameters `Service` may
    need, can be an empty dictionary.
    :return OperationResult: the operation result object.
    """
    return cls(params, **kwargs).execute()

    @classmethod
    def do_process(cls, params={}, **kwargs):
    """
    Runs the service's main operation in a "dangerous" way i.e. it can raises known exceptions
    in case of operation failure.
    :param dictionary params: data parameters for `Service`, checked
    against the fields defined on the `Service` class.
    :param dictionary **kwargs: any additional parameters `Service` may
    need, can be an empty dictionary.
    :return OperationResult: the operation result object.
    """
    return cls(params, **kwargs).process()

    def execute(self):
    """
    Runs the service in a "safe" way i.e. all known expections will be catched.
    """
    try:
    self.raw_result = self.process()
    except type(self).known_exceptions as error:
    self.errors = [error.message]
    self.failed_objects.append(error)
    finally:
    self.processed = True

    return OperationResult(data=self.raw_result, source=self)

    @abc.abstractmethod
    def process(self):
    """
    Main method to be overridden, contains the business logic.
    """
    pass

  6. tiagopog revised this gist May 3, 2019. No changes.
  7. tiagopog renamed this gist Apr 1, 2019. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  8. tiagopog revised this gist Apr 1, 2019. 1 changed file with 16 additions and 0 deletions.
    16 changes: 16 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,16 @@
    # Be careful using mutable data structures in method definitions.
    #
    # The assignment of the "foo" argument's default value is made only the
    # first time the function is actually evaluated on the runtime.
    #
    # Then it uses the same memory address for the default argument value,
    # sharing it with all instances of that class.

    class Foo(object):
    def __init__(self, foo=[]):
    foo.append(1)
    self.foo = foo


    Foo().foo #=> [1]
    Foo().foo #=> [1, 1]
  9. tiagopog revised this gist Mar 18, 2019. 1 changed file with 153 additions and 0 deletions.
    153 changes: 153 additions & 0 deletions classes.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,153 @@
    # An usual class is a subclass of object
    class Human(object):
    # Defining class variables
    species = "H. Sapiens"

    def __init__(self, first_name, last_name):
    # Assign instance variables (also called attributes):
    self.__internal = "secret" # Private attribute (externally accessed via: human._Human_internal)
    self.first_name = first_name # Public attribute (externally accessed via human.first_name)
    self.last_name = last_name # Since last_name has not a getter/setter below
    # here the "=" will be dealing directly with
    # the instance variable

    # Define public instance method.
    # Instance method is any method that has "self" as its first argument.
    def say(self, speech):
    print(self.__build_say(speech))

    # Define private instance method
    def __build_say(self, speech):
    return "{} is saying \"{}\"".format(self.full_name, speech)

    # Define class methods.
    # The class itself is passed as the first argument so
    # class variable can be called for instance
    @classmethod
    def get_species(cls):
    return cls.species

    # Define static methods.
    # This kind of method has no references for classes or instances.
    @staticmethod
    def something():
    return "somthing"

    # Define a property for an instance variable.
    # It works as getter method.
    @property
    def first_name(self):
    return self._first_name

    # Define a setter method for the Human's first name.
    # This way when setting its value via "=", it will be using
    # this method rather than operating directly on the instance variable.
    @first_name.setter
    def first_name(self, name):
    self._first_name = name

    # Allow the first_name property to be deleted
    @first_name.deleter
    def first_name(self):
    del self._first_name

    # Define a virtual property (not backed by an instance variable).
    # This way human.full_name will be called rather than human.full_name().
    @property
    def full_name(self):
    return "{0} {1}".format(self.first_name, self.last_name)

    # Define a setter for full_name so some logic can be applied
    # to the instance variables first_name and last_name.
    @full_name.setter
    def full_name(self, full_name):
    if not full_name:
    self.first_name = ""
    self.last_name = ""
    elif isinstance(full_name, str):
    names = full_name.split()
    self.first_name = names[0]
    self.last_name = " ".join(names[1:])

    def __str__(self):
    return "First name: {}; Last name: {}".format(self.first_name, self.last_name)

    # Define a class (Developer) as subclass of other (Human)
    class Developer(Human):
    # Override the superclass method extending its behavior:
    def __init__(self, first_name, last_name, tech_skills=[]):
    # Human.__init__(self, first_name, last_name)
    super(Developer, self).__init__(first_name, last_name)
    self.tech_skills = tech_skills

    # Override the superclass method extending its behavior:
    def __str__(self):
    human_str = super(Developer, self).__str__()
    dev_str = ', '.join(self.tech_skills)
    return "{}; Tech skill: {}".format(human_str, dev_str)

    # Calling class methods:
    print(Human.get_species())

    # Calling static methods:
    print(Human.something())

    # Test constructor:
    human = Human(first_name="Tiago", last_name="Guedes")
    print(human.first_name)
    print(human.last_name)
    print("---")

    # Test virtual setter:
    human.full_name = "Foo Bar"

    print(human.first_name)
    print(human.last_name)
    print(human.full_name)
    print("---")

    # Test virtual setter(2):
    human.full_name = ""

    print(human.first_name)
    print(human.last_name)
    print(human.full_name)
    print("---")

    human.full_name = "Tiago Guedes"

    # Test public instance method:
    human.say("Travel the world they said!")
    # Test private instance method:
    print(human._Human__build_say("Travel the world they said! (private)"))
    # Test private attribute:
    print(human._Human__internal)
    print("---")

    # Test deleting a property
    print("After deleting human.first_name, let's try to call it again:")

    try:
    del human.first_name
    human.first_name
    except AttributeError as e:
    print("Error raised: {}".format(e))
    print("---")

    print("Instatiating a developer:")

    human = Human(first_name="Tiago", last_name="Guedes")
    dev = Developer(first_name="Tiago", last_name="Guedes", tech_skills=["Ruby", "Elixir", "Python"])

    print(dev.tech_skills)
    print(dev.first_name)
    print(dev.last_name)
    print(dev.full_name)

    print(human)
    print(dev)

    print("---")

    # Debugger:
    # import code; code.interact(local=dict(globals(), **locals()))
  10. tiagopog revised this gist Mar 15, 2019. 1 changed file with 19 additions and 0 deletions.
    19 changes: 19 additions & 0 deletions fuction_scope.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,19 @@
    # Function Scope
    x = 5


    def set_x(num):
    # Local var x not the same as global variable x
    x = num # => 43
    print x # => 43


    def set_global_x(num):
    global x
    print x # => 5
    x = num # global var x is now set to 6
    print x # => 6


    set_x(43)
    set_global_x(6)
  11. tiagopog revised this gist Mar 15, 2019. 1 changed file with 12 additions and 0 deletions.
    12 changes: 12 additions & 0 deletions try_except_finally.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,12 @@
    # Works on Python 2.6 and up:
    try:
    # Use "raise" to raise an error
    raise IndexError("This is an index error")
    except IndexError as e:
    pass # Pass is just a no-op. Usually you would do recovery here.
    except (TypeError, NameError):
    pass # Multiple exceptions can be handled together, if required.
    else: # Optional clause to the try/except block. Must follow all except blocks
    print "All good!" # Runs only if the code in try raises no exceptions
    finally: # Execute under all circumstances
    print "We can clean up resources here"
  12. tiagopog revised this gist Mar 15, 2019. 1 changed file with 51 additions and 0 deletions.
    51 changes: 51 additions & 0 deletions decorators.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,51 @@
    ##
    # With no arguments
    ##

    def call_twice(old_function):
    def new_function(arg):
    for _ in range(2):
    old_function(arg)
    return new_function

    def foo(arg):
    print(arg)

    # The upper def would be the equivalent of doing:
    # foo = call_twice(foo)

    foo('Foobar')

    ##
    # With arguments
    ##

    def type_check(correct_type):
    def type_check_generator(old_function):
    def new_function(arg):
    if isinstance(arg, correct_type):
    return old_function(arg)
    else:
    print("Bad Type")
    return new_function
    return type_check_generator

    @type_check(int)
    def double(num):
    return num * 2

    # The upper def would be the equivalent of doing:
    # double = type_check(int)(double)

    print(double(2))
    double('Not A Number')

    @type_check(str)
    def first_letter(word):
    return word[0]

    # That would be the equivalent of doing:
    # double = type_check(int)(double)

    print(first_letter('Hello World'))
    first_letter(['Not', 'A', 'String'])
  13. tiagopog revised this gist Mar 13, 2019. 1 changed file with 16 additions and 0 deletions.
    16 changes: 16 additions & 0 deletions fibonacci_generator.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,16 @@
    def fibonacci(size):
    a, b = 1, 1
    for x in range(size):
    if x in (0, 1): x = 1
    x = a + b
    a, b = b, x
    yield x

    # Called in a "for" loop
    for x in fibonacci(10):
    print(x)

    # Assigned to a variable
    foo = fibonacci(10)
    print(next(foo))
    print(next(foo))
  14. tiagopog created this gist Mar 11, 2019.
    7 changes: 7 additions & 0 deletions generators.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    def even_numbers(n):
    for number in range(1, n * 2 + 1):
    if number % 2 == 0:
    yield number

    for x in even_numbers(10):
    print(x)