Skip to content

Commit

Permalink
Modules adventure in English
Browse files Browse the repository at this point in the history
  • Loading branch information
Ignacio Avas committed May 4, 2017
1 parent 2bf9b40 commit b5acd35
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 8 deletions.
13 changes: 13 additions & 0 deletions mymodule.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Szdef how_many_fib(n):
a = 0
b = 1
result = 0
while b < n:
temp = a
a = b
b = temp + b
result = result + 1
return result

def say_hello():
print("Say my name")
72 changes: 68 additions & 4 deletions py101/modules/README.rst
Original file line number Diff line number Diff line change
@@ -1,14 +1,78 @@
Boilerplate
Modules
-----------

Insert some introduction here.
Python has a way to put definitions in a file and use them in another script.
Such a file is called a module. Definitions from a module can be imported into
other modules or into the main program file.

A module is a file containing Python definitions and statements. The file name
is the module name with the suffix .py appended. Within a module, the module’s
name (as a string) is available as the value of the global variable __name__.
For instance, supposing there is file called mymodule.py in the current
directory with the following contents:

.. sourcecode:: python

# counts how many fibonacci numbers are less than n
def how_many_fib(n):
a = 0
b = 1
result = 0
while b < n:
temp = a
a = b
b = temp + b
result = result + 1
return result

def say_hello():
print("Say my name")

In other files mymodule can be imported using the following syntax:

.. sourcecode:: python

import mymodule
print(mymodule.how_many_fib(1000) # prints 16

Standard Modules
----------------

Python comes with a library of standard modules, called the Python Library
Reference. Some modules are built into the interpreter; these provide access to
operations that are not part of the core of the language but are nevertheless
built in, either for efficiency or to provide access to operating system
primitives such as system call.

Two very important functions come in handy when exploring modules in
Python: the "dir"and "help" functions. One can look for which functions are
implemented in each module by using the "dir" function. If help is needed,
then the "help" function may be used.

.. sourcecode:: python

print('Some python code here')
import http
dir(http)
# prints [ 'HTTPStatus','IntEnum','__all__','__builtins__','__cached__',
# '__doc__','__file__','__loader__','__name__','__package__','__path__',
# '__spec__']

help(http.HTTPStatus)
# prints a large description if this field


Writing modules
---------------

To create a module of your own, simply create a new .py file with the module
name, and then import it using the Python file name (without the .py extension)
using the import command.

Challenge
---------

Describe the challenge here
Create a module called "numbers" that defines a tangent() function that
computes the tangent using the functions "sin" and "cos" from the standard math
library, and then a program that prints the value of tangent(1) from the
numbers library. The program should print one line "1.557407724654902"

53 changes: 49 additions & 4 deletions py101/modules/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import unittest
from story.adventures import AdventureVerificationError, BaseAdventure
from story.translation import gettext as _
import ast


class TestOutput(unittest.TestCase):
Expand All @@ -31,10 +32,54 @@ def tearDown(self):
def runTest(self):
"""Makes a simple test of the output"""

# code = compile(self.candidate_code, self.file_name, 'exec',
# optimize=0)
# exec(code)
self.fail("Test not implemented")
body = ast.parse(self.candidate_code, self.file_name, 'exec')

import_statements = [
node
for node in ast.walk(body)
if isinstance(node, ast.Import) and
len(node.names) > 0 and
len([name for name in node.names if name.name == 'numbers']) > 0
]

self.assertGreater(
len(import_statements),
0,
"It should be at least one import statement for numbers"
)

call_statements = [
node
for node in ast.walk(body)
if isinstance(node, ast.Call) and
isinstance(node.func, ast.Attribute) and
isinstance(node.func.value, ast.Name) and
node.func.value.id == 'numbers' and
node.func.attr == 'tangent'
]

self.assertGreater(
len(call_statements),
0,
"It should be at least one call statement for numbers.tangent"
)

code = compile(self.candidate_code, self.file_name, 'exec', optimize=0)
exec(code)

self.assertEqual(
2,
len(self.__mockstdout.getvalue().split('\n')),
"Should have output one line"
)

returned_value = float(self.__mockstdout.getvalue())

self.assertAlmostEqual(
returned_value,
1.5574077246549025,
4,
"The output number should be near 1.557")


class Adventure(BaseAdventure):
Expand Down
6 changes: 6 additions & 0 deletions tests/numbers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""Auxiliary module used in the modules adventure"""
import math


def tangent(x):
return math.sin(x) / math.cos(x)
3 changes: 3 additions & 0 deletions tests/solutions/modules.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import numbers

print(numbers.tangent(1))
7 changes: 7 additions & 0 deletions tests/test_story.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import py101.functions
import py101.classes
import py101.dictionaries
import py101.modules
import unittest
from story.commands import PrintCommand, SolutionCommand, SelectCommand
from io import StringIO
Expand Down Expand Up @@ -115,6 +116,12 @@ def get_solution_path(solution_name):
get_solution_path('dictionaries.py'),
'dictionaries',
'diccionarios'
),
AdventureData(
py101.modules,
get_solution_path('modules.py'),
'modules',
'módulos'
)
]

Expand Down

0 comments on commit b5acd35

Please sign in to comment.