Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
lettuce
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
lettuce
Commits
86dd4e89
Commit
86dd4e89
authored
Jul 31, 2011
by
Gabriel Falcão
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #161 from chris-morgan/master
Code style improvements
parents
4e5d9e59
37d5a910
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
199 additions
and
239 deletions
+199
-239
lettuce/core.py
+31
-33
lettuce/decorators.py
+1
-0
lettuce/django/apps.py
+7
-0
lettuce/django/management/commands/harvest.py
+3
-1
lettuce/django/server.py
+4
-10
lettuce/exceptions.py
+4
-2
lettuce/fs.py
+3
-2
lettuce/lettuce_cli.py
+3
-3
lettuce/plugins/colored_shell_output.py
+16
-18
lettuce/plugins/dots.py
+10
-17
lettuce/plugins/non_verbose.py
+10
-12
lettuce/plugins/scenario_names.py
+13
-21
lettuce/plugins/shell_output.py
+12
-17
lettuce/plugins/xunit_output.py
+3
-3
lettuce/registry.py
+24
-43
lettuce/strings.py
+23
-5
lettuce/terminal.py
+9
-6
lettuce/terrain.py
+23
-46
No files found.
lettuce/core.py
View file @
86dd4e89
...
@@ -32,6 +32,7 @@ from lettuce.exceptions import LettuceSyntaxError
...
@@ -32,6 +32,7 @@ from lettuce.exceptions import LettuceSyntaxError
fs
=
FileSystem
()
fs
=
FileSystem
()
class
HashList
(
list
):
class
HashList
(
list
):
__base_msg
=
'The step "
%
s" have no table defined, so '
\
__base_msg
=
'The step "
%
s" have no table defined, so '
\
'that you can
\'
t use step.hashes.
%
s'
'that you can
\'
t use step.hashes.
%
s'
...
@@ -64,6 +65,7 @@ class HashList(list):
...
@@ -64,6 +65,7 @@ class HashList(list):
raise
AssertionError
(
self
.
__base_msg
%
(
self
.
step
.
sentence
,
'last'
))
raise
AssertionError
(
self
.
__base_msg
%
(
self
.
step
.
sentence
,
'last'
))
class
Language
(
object
):
class
Language
(
object
):
code
=
'en'
code
=
'en'
name
=
'English'
name
=
'English'
...
@@ -73,6 +75,7 @@ class Language(object):
...
@@ -73,6 +75,7 @@ class Language(object):
examples
=
'Examples|Scenarios'
examples
=
'Examples|Scenarios'
scenario_outline
=
'Scenario Outline'
scenario_outline
=
'Scenario Outline'
scenario_separator
=
'Scenario( Outline)?'
scenario_separator
=
'Scenario( Outline)?'
def
__init__
(
self
,
code
=
u'en'
):
def
__init__
(
self
,
code
=
u'en'
):
self
.
code
=
code
self
.
code
=
code
for
attr
,
value
in
languages
.
LANGUAGES
[
code
]
.
items
():
for
attr
,
value
in
languages
.
LANGUAGES
[
code
]
.
items
():
...
@@ -98,6 +101,7 @@ class Language(object):
...
@@ -98,6 +101,7 @@ class Language(object):
return
instance
return
instance
class
StepDefinition
(
object
):
class
StepDefinition
(
object
):
"""A step definition is a wrapper for user-defined callbacks. It
"""A step definition is a wrapper for user-defined callbacks. It
gets a few metadata from file, such as filename and line number"""
gets a few metadata from file, such as filename and line number"""
...
@@ -122,6 +126,7 @@ class StepDefinition(object):
...
@@ -122,6 +126,7 @@ class StepDefinition(object):
return
ret
return
ret
class
StepDescription
(
object
):
class
StepDescription
(
object
):
"""A simple object that holds filename and line number of a step
"""A simple object that holds filename and line number of a step
description (step within feature file)"""
description (step within feature file)"""
...
@@ -132,6 +137,7 @@ class StepDescription(object):
...
@@ -132,6 +137,7 @@ class StepDescription(object):
self
.
line
=
line
self
.
line
=
line
class
ScenarioDescription
(
object
):
class
ScenarioDescription
(
object
):
"""A simple object that holds filename and line number of a scenario
"""A simple object that holds filename and line number of a scenario
description (scenario within feature file)"""
description (scenario within feature file)"""
...
@@ -146,6 +152,7 @@ class ScenarioDescription(object):
...
@@ -146,6 +152,7 @@ class ScenarioDescription(object):
self
.
line
=
pline
+
1
self
.
line
=
pline
+
1
break
break
class
FeatureDescription
(
object
):
class
FeatureDescription
(
object
):
"""A simple object that holds filename and line number of a feature
"""A simple object that holds filename and line number of a feature
description"""
description"""
...
@@ -168,6 +175,7 @@ class FeatureDescription(object):
...
@@ -168,6 +175,7 @@ class FeatureDescription(object):
self
.
description_at
=
tuple
(
described_at
)
self
.
description_at
=
tuple
(
described_at
)
class
Step
(
object
):
class
Step
(
object
):
""" Object that represents each step on feature files."""
""" Object that represents each step on feature files."""
has_definition
=
False
has_definition
=
False
...
@@ -198,8 +206,8 @@ class Step(object):
...
@@ -198,8 +206,8 @@ class Step(object):
method_name
=
sentence
method_name
=
sentence
groups
=
[
groups
=
[
(
'"'
,
re
.
compile
(
r'("[^"]+")'
)),
# double quotes
(
'"'
,
re
.
compile
(
r'("[^"]+")'
)),
# double quotes
(
"'"
,
re
.
compile
(
r"('[^']+')"
)),
# single quotes
(
"'"
,
re
.
compile
(
r"('[^']+')"
)),
# single quotes
]
]
attribute_names
=
[]
attribute_names
=
[]
...
@@ -217,14 +225,11 @@ class Step(object):
...
@@ -217,14 +225,11 @@ class Step(object):
method_name
=
method_name
.
replace
(
match
,
group_name
)
method_name
=
method_name
.
replace
(
match
,
group_name
)
attribute_names
.
append
(
group_name
)
attribute_names
.
append
(
group_name
)
method_name
=
unicodedata
.
normalize
(
'NFKD'
,
method_name
)
\
method_name
=
unicodedata
.
normalize
(
'NFKD'
,
method_name
)
\
.
encode
(
'ascii'
,
'ignore'
)
.
encode
(
'ascii'
,
'ignore'
)
method_name
=
'
%
s(step
%
s)'
%
(
method_name
=
'
%
s(step
%
s)'
%
(
"_"
.
join
(
re
.
findall
(
"
\
w+"
,
method_name
))
.
lower
(),
"_"
.
join
(
re
.
findall
(
"
\
w+"
,
method_name
))
.
lower
(),
attribute_names
and
(
",
%
s"
%
", "
.
join
(
attribute_names
))
or
""
attribute_names
and
(
",
%
s"
%
", "
.
join
(
attribute_names
))
or
""
)
)
return
method_name
,
sentence
return
method_name
,
sentence
...
@@ -232,6 +237,7 @@ class Step(object):
...
@@ -232,6 +237,7 @@ class Step(object):
sentence
=
self
.
sentence
sentence
=
self
.
sentence
hashes
=
self
.
hashes
[:]
# deep copy
hashes
=
self
.
hashes
[:]
# deep copy
for
k
,
v
in
data
.
items
():
for
k
,
v
in
data
.
items
():
def
evaluate
(
stuff
):
def
evaluate
(
stuff
):
return
stuff
.
replace
(
u'<
%
s>'
%
unicode
(
k
),
unicode
(
v
))
return
stuff
.
replace
(
u'<
%
s>'
%
unicode
(
k
),
unicode
(
v
))
...
@@ -387,7 +393,7 @@ class Step(object):
...
@@ -387,7 +393,7 @@ class Step(object):
return
True
return
True
@staticmethod
@staticmethod
def
run_all
(
steps
,
outline
=
None
,
run_callbacks
=
False
,
ignore_case
=
True
):
def
run_all
(
steps
,
outline
=
None
,
run_callbacks
=
False
,
ignore_case
=
True
):
"""Runs each step in the given list of steps.
"""Runs each step in the given list of steps.
Returns a tuple of five lists:
Returns a tuple of five lists:
...
@@ -434,7 +440,7 @@ class Step(object):
...
@@ -434,7 +440,7 @@ class Step(object):
return
(
all_steps
,
steps_passed
,
steps_failed
,
steps_undefined
,
reasons_to_fail
)
return
(
all_steps
,
steps_passed
,
steps_failed
,
steps_undefined
,
reasons_to_fail
)
@classmethod
@classmethod
def
many_from_lines
(
klass
,
lines
,
filename
=
None
,
original_string
=
None
):
def
many_from_lines
(
klass
,
lines
,
filename
=
None
,
original_string
=
None
):
"""Parses a set of steps from lines of input.
"""Parses a set of steps from lines of input.
This will correctly parse and produce a list of steps from lines without
This will correctly parse and produce a list of steps from lines without
...
@@ -652,9 +658,8 @@ class Scenario(object):
...
@@ -652,9 +658,8 @@ class Scenario(object):
steps_skipped
=
filter
(
skip
,
all_steps
)
steps_skipped
=
filter
(
skip
,
all_steps
)
if
outline
:
if
outline
:
call_hook
(
call_hook
(
'outline'
,
'scenario'
,
self
,
order
,
outline
,
'outline'
,
'scenario'
,
self
,
order
,
outline
,
reasons_to_fail
reasons_to_fail
)
)
return
ScenarioResult
(
return
ScenarioResult
(
self
,
self
,
...
@@ -662,8 +667,7 @@ class Scenario(object):
...
@@ -662,8 +667,7 @@ class Scenario(object):
steps_failed
,
steps_failed
,
steps_skipped
,
steps_skipped
,
steps_undefined
,
steps_undefined
,
True
True
)
)
if
self
.
outlines
:
if
self
.
outlines
:
first
=
True
first
=
True
...
@@ -757,14 +761,15 @@ class Scenario(object):
...
@@ -757,14 +761,15 @@ class Scenario(object):
with_file
=
with_file
,
with_file
=
with_file
,
original_string
=
original_string
,
original_string
=
original_string
,
language
=
language
,
language
=
language
,
tags
=
tags
tags
=
tags
)
)
return
scenario
return
scenario
class
Feature
(
object
):
class
Feature
(
object
):
""" Object that represents a feature."""
""" Object that represents a feature."""
described_at
=
None
described_at
=
None
def
__init__
(
self
,
name
,
remaining_lines
,
with_file
,
original_string
,
def
__init__
(
self
,
name
,
remaining_lines
,
with_file
,
original_string
,
language
=
None
,
tags
=
None
):
language
=
None
,
tags
=
None
):
...
@@ -778,8 +783,7 @@ class Feature(object):
...
@@ -778,8 +783,7 @@ class Feature(object):
self
.
scenarios
,
self
.
description
=
self
.
_parse_remaining_lines
(
self
.
scenarios
,
self
.
description
=
self
.
_parse_remaining_lines
(
remaining_lines
,
remaining_lines
,
original_string
,
original_string
,
with_file
with_file
)
)
self
.
original_string
=
original_string
self
.
original_string
=
original_string
...
@@ -841,17 +845,12 @@ class Feature(object):
...
@@ -841,17 +845,12 @@ class Feature(object):
found
=
len
(
re
.
findall
(
r'
%
s:[ ]*\w+'
%
language
.
feature
,
"
\n
"
.
join
(
lines
),
re
.
U
))
found
=
len
(
re
.
findall
(
r'
%
s:[ ]*\w+'
%
language
.
feature
,
"
\n
"
.
join
(
lines
),
re
.
U
))
if
found
>
1
:
if
found
>
1
:
raise
LettuceSyntaxError
(
raise
LettuceSyntaxError
(
with_file
,
with_file
,
'A feature file must contain ONLY ONE feature!'
)
'A feature file must contain ONLY ONE feature!'
)
elif
found
==
0
:
elif
found
==
0
:
raise
LettuceSyntaxError
(
raise
LettuceSyntaxError
(
with_file
,
with_file
,
'Features must have a name. e.g: "Feature: This is my name"'
)
'Features must have a name. e.g: "Feature: This is my name"'
)
while
lines
:
while
lines
:
matched
=
re
.
search
(
r'
%
s:(.*)'
%
language
.
feature
,
lines
[
0
],
re
.
I
)
matched
=
re
.
search
(
r'
%
s:(.*)'
%
language
.
feature
,
lines
[
0
],
re
.
I
)
...
@@ -898,15 +897,12 @@ class Feature(object):
...
@@ -898,15 +897,12 @@ class Feature(object):
parts
=
strings
.
split_scenarios
(
lines
,
scenario_prefix
)
parts
=
strings
.
split_scenarios
(
lines
,
scenario_prefix
)
scenario_strings
=
[
scenario_strings
=
[
u"
%
s"
%
(
s
)
for
s
in
parts
if
s
.
strip
()]
u"
%
s"
%
(
s
)
for
s
in
parts
if
s
.
strip
()
]
kw
=
dict
(
kw
=
dict
(
original_string
=
original_string
,
original_string
=
original_string
,
with_file
=
with_file
,
with_file
=
with_file
,
language
=
self
.
language
,
language
=
self
.
language
,
tags
=
self
.
tags
tags
=
self
.
tags
)
)
scenarios
=
[
Scenario
.
from_string
(
s
,
**
kw
)
for
s
in
scenario_strings
]
scenarios
=
[
Scenario
.
from_string
(
s
,
**
kw
)
for
s
in
scenario_strings
]
...
@@ -932,6 +928,7 @@ class Feature(object):
...
@@ -932,6 +928,7 @@ class Feature(object):
call_hook
(
'after_each'
,
'feature'
,
self
)
call_hook
(
'after_each'
,
'feature'
,
self
)
return
FeatureResult
(
self
,
*
scenarios_ran
)
return
FeatureResult
(
self
,
*
scenarios_ran
)
class
FeatureResult
(
object
):
class
FeatureResult
(
object
):
"""Object that holds results of each scenario ran from within a feature"""
"""Object that holds results of each scenario ran from within a feature"""
def
__init__
(
self
,
feature
,
*
scenario_results
):
def
__init__
(
self
,
feature
,
*
scenario_results
):
...
@@ -942,6 +939,7 @@ class FeatureResult(object):
...
@@ -942,6 +939,7 @@ class FeatureResult(object):
def
passed
(
self
):
def
passed
(
self
):
return
all
([
result
.
passed
for
result
in
self
.
scenario_results
])
return
all
([
result
.
passed
for
result
in
self
.
scenario_results
])
class
ScenarioResult
(
object
):
class
ScenarioResult
(
object
):
"""Object that holds results of each step ran from within a scenario"""
"""Object that holds results of each step ran from within a scenario"""
def
__init__
(
self
,
scenario
,
steps_passed
,
steps_failed
,
steps_skipped
,
def
__init__
(
self
,
scenario
,
steps_passed
,
steps_failed
,
steps_skipped
,
...
@@ -966,6 +964,7 @@ class ScenarioResult(object):
...
@@ -966,6 +964,7 @@ class ScenarioResult(object):
def
failed
(
self
):
def
failed
(
self
):
return
len
(
self
.
steps_failed
)
>
0
return
len
(
self
.
steps_failed
)
>
0
class
TotalResult
(
object
):
class
TotalResult
(
object
):
def
__init__
(
self
,
feature_results
):
def
__init__
(
self
,
feature_results
):
self
.
feature_results
=
feature_results
self
.
feature_results
=
feature_results
...
@@ -973,7 +972,7 @@ class TotalResult(object):
...
@@ -973,7 +972,7 @@ class TotalResult(object):
self
.
steps_passed
=
0
self
.
steps_passed
=
0
self
.
steps_failed
=
0
self
.
steps_failed
=
0
self
.
steps_skipped
=
0
self
.
steps_skipped
=
0
self
.
steps_undefined
=
0
self
.
steps_undefined
=
0
self
.
_proposed_definitions
=
[]
self
.
_proposed_definitions
=
[]
self
.
steps
=
0
self
.
steps
=
0
for
feature_result
in
self
.
feature_results
:
for
feature_result
in
self
.
feature_results
:
...
@@ -986,7 +985,6 @@ class TotalResult(object):
...
@@ -986,7 +985,6 @@ class TotalResult(object):
self
.
steps
+=
scenario_result
.
total_steps
self
.
steps
+=
scenario_result
.
total_steps
self
.
_proposed_definitions
.
extend
(
scenario_result
.
steps_undefined
)
self
.
_proposed_definitions
.
extend
(
scenario_result
.
steps_undefined
)
def
_filter_proposed_definitions
(
self
):
def
_filter_proposed_definitions
(
self
):
sentences
=
[]
sentences
=
[]
for
step
in
self
.
_proposed_definitions
:
for
step
in
self
.
_proposed_definitions
:
...
...
lettuce/decorators.py
View file @
86dd4e89
...
@@ -18,6 +18,7 @@ import re
...
@@ -18,6 +18,7 @@ import re
from
lettuce.core
import
STEP_REGISTRY
from
lettuce.core
import
STEP_REGISTRY
from
lettuce.exceptions
import
StepLoadingError
from
lettuce.exceptions
import
StepLoadingError
def
step
(
regex
):
def
step
(
regex
):
"""Decorates a function, so that it will become a new step
"""Decorates a function, so that it will become a new step
definition.
definition.
...
...
lettuce/django/apps.py
View file @
86dd4e89
...
@@ -19,11 +19,13 @@ from os.path import join, dirname
...
@@ -19,11 +19,13 @@ from os.path import join, dirname
from
django.utils.importlib
import
import_module
from
django.utils.importlib
import
import_module
from
django.conf
import
settings
from
django.conf
import
settings
def
_filter_bultins
(
module
):
def
_filter_bultins
(
module
):
"returns only those apps that are not builtin django.contrib"
"returns only those apps that are not builtin django.contrib"
name
=
module
.
__name__
name
=
module
.
__name__
return
not
name
.
startswith
(
"django.contrib"
)
and
name
!=
'lettuce.django'
return
not
name
.
startswith
(
"django.contrib"
)
and
name
!=
'lettuce.django'
def
_filter_configured_apps
(
module
):
def
_filter_configured_apps
(
module
):
"returns only those apps that are in django.conf.settings.LETTUCE_APPS"
"returns only those apps that are in django.conf.settings.LETTUCE_APPS"
app_found
=
True
app_found
=
True
...
@@ -35,6 +37,7 @@ def _filter_configured_apps(module):
...
@@ -35,6 +37,7 @@ def _filter_configured_apps(module):
return
app_found
return
app_found
def
_filter_configured_avoids
(
module
):
def
_filter_configured_avoids
(
module
):
"returns apps that are not within django.conf.settings.LETTUCE_AVOID_APPS"
"returns apps that are not within django.conf.settings.LETTUCE_AVOID_APPS"
run_app
=
False
run_app
=
False
...
@@ -45,9 +48,11 @@ def _filter_configured_avoids(module):
...
@@ -45,9 +48,11 @@ def _filter_configured_avoids(module):
return
not
run_app
return
not
run_app
def
get_apps
():
def
get_apps
():
return
map
(
import_module
,
settings
.
INSTALLED_APPS
)
return
map
(
import_module
,
settings
.
INSTALLED_APPS
)
def
harvest_lettuces
(
only_the_apps
=
None
,
avoid_apps
=
None
,
path
=
"features"
):
def
harvest_lettuces
(
only_the_apps
=
None
,
avoid_apps
=
None
,
path
=
"features"
):
"""gets all installed apps that are not from django.contrib
"""gets all installed apps that are not from django.contrib
returns a list of tuples with (path_to_app, app_module)
returns a list of tuples with (path_to_app, app_module)
...
@@ -56,6 +61,7 @@ def harvest_lettuces(only_the_apps=None, avoid_apps=None, path="features"):
...
@@ -56,6 +61,7 @@ def harvest_lettuces(only_the_apps=None, avoid_apps=None, path="features"):
apps
=
get_apps
()
apps
=
get_apps
()
if
isinstance
(
only_the_apps
,
tuple
)
and
any
(
only_the_apps
):
if
isinstance
(
only_the_apps
,
tuple
)
and
any
(
only_the_apps
):
def
_filter_only_specified
(
module
):
def
_filter_only_specified
(
module
):
return
module
.
__name__
in
only_the_apps
return
module
.
__name__
in
only_the_apps
apps
=
filter
(
_filter_only_specified
,
apps
)
apps
=
filter
(
_filter_only_specified
,
apps
)
...
@@ -65,6 +71,7 @@ def harvest_lettuces(only_the_apps=None, avoid_apps=None, path="features"):
...
@@ -65,6 +71,7 @@ def harvest_lettuces(only_the_apps=None, avoid_apps=None, path="features"):
apps
=
filter
(
_filter_configured_avoids
,
apps
)
apps
=
filter
(
_filter_configured_avoids
,
apps
)
if
isinstance
(
avoid_apps
,
tuple
)
and
any
(
avoid_apps
):
if
isinstance
(
avoid_apps
,
tuple
)
and
any
(
avoid_apps
):
def
_filter_avoid
(
module
):
def
_filter_avoid
(
module
):
return
module
.
__name__
not
in
avoid_apps
return
module
.
__name__
not
in
avoid_apps
...
...
lettuce/django/management/commands/harvest.py
View file @
86dd4e89
...
@@ -28,6 +28,7 @@ from lettuce import registry
...
@@ -28,6 +28,7 @@ from lettuce import registry
from
lettuce.django
import
server
from
lettuce.django
import
server
from
lettuce.django
import
harvest_lettuces
from
lettuce.django
import
harvest_lettuces
class
Command
(
BaseCommand
):
class
Command
(
BaseCommand
):
help
=
u'Run lettuce tests all along installed apps'
help
=
u'Run lettuce tests all along installed apps'
args
=
'[PATH to feature file or folder]'
args
=
'[PATH to feature file or folder]'
...
@@ -59,6 +60,7 @@ class Command(BaseCommand):
...
@@ -59,6 +60,7 @@ class Command(BaseCommand):
make_option
(
'--xunit-file'
,
action
=
'store'
,
dest
=
'xunit_file'
,
default
=
None
,
make_option
(
'--xunit-file'
,
action
=
'store'
,
dest
=
'xunit_file'
,
default
=
None
,
help
=
'Write JUnit XML to this file. Defaults to lettucetests.xml'
),
help
=
'Write JUnit XML to this file. Defaults to lettucetests.xml'
),
)
)
def
stopserver
(
self
,
failed
=
False
):
def
stopserver
(
self
,
failed
=
False
):
raise
SystemExit
(
int
(
failed
))
raise
SystemExit
(
int
(
failed
))
...
@@ -71,7 +73,7 @@ class Command(BaseCommand):
...
@@ -71,7 +73,7 @@ class Command(BaseCommand):
else
:
else
:
paths
=
args
paths
=
args
else
:
else
:
paths
=
harvest_lettuces
(
apps_to_run
,
apps_to_avoid
)
# list of tuples with (path, app_module)
paths
=
harvest_lettuces
(
apps_to_run
,
apps_to_avoid
)
# list of tuples with (path, app_module)
return
paths
return
paths
...
...
lettuce/django/server.py
View file @
86dd4e89
...
@@ -128,18 +128,12 @@ class ThreadedServer(multiprocessing.Process):
...
@@ -128,18 +128,12 @@ class ThreadedServer(multiprocessing.Process):
self
.
lock
.
acquire
()
self
.
lock
.
acquire
()
def
should_serve_static_files
(
self
):
def
should_serve_static_files
(
self
):
conditions
=
[
return
(
StaticFilesHandler
is
not
None
and
StaticFilesHandler
is
not
None
,
getattr
(
settings
,
'STATIC_URL'
,
False
))
getattr
(
settings
,
'STATIC_URL'
,
False
),
]
return
all
(
conditions
)
def
should_serve_admin_media
(
self
):
def
should_serve_admin_media
(
self
):
conditions
=
[
return
(
'django.contrib.admin'
in
settings
.
INSTALLED_APPS
or
'django.contrib.admin'
in
settings
.
INSTALLED_APPS
,
getattr
(
settings
,
'LETTUCE_SERVE_ADMIN_MEDIA'
,
False
))
getattr
(
settings
,
'LETTUCE_SERVE_ADMIN_MEDIA'
,
False
),
]
return
any
(
conditions
)
def
run
(
self
):
def
run
(
self
):
self
.
lock
.
acquire
()
self
.
lock
.
acquire
()
...
...
lettuce/exceptions.py
View file @
86dd4e89
...
@@ -16,6 +16,7 @@
...
@@ -16,6 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import
traceback
import
traceback
class
NoDefinitionFound
(
Exception
):
class
NoDefinitionFound
(
Exception
):
""" Exception raised by lettuce.core.Step, when trying to solve a
""" Exception raised by lettuce.core.Step, when trying to solve a
Step, but does not find a suitable step definition.
Step, but does not find a suitable step definition.
...
@@ -26,8 +27,8 @@ class NoDefinitionFound(Exception):
...
@@ -26,8 +27,8 @@ class NoDefinitionFound(Exception):
def
__init__
(
self
,
step
):
def
__init__
(
self
,
step
):
self
.
step
=
step
self
.
step
=
step
super
(
NoDefinitionFound
,
self
)
.
__init__
(
super
(
NoDefinitionFound
,
self
)
.
__init__
(
'The step r"
%
s" is not defined'
%
self
.
step
.
sentence
'The step r"
%
s" is not defined'
%
self
.
step
.
sentence
)
)
class
ReasonToFail
(
object
):
class
ReasonToFail
(
object
):
""" Exception that contains detailed information about a
""" Exception that contains detailed information about a
...
@@ -39,6 +40,7 @@ class ReasonToFail(object):
...
@@ -39,6 +40,7 @@ class ReasonToFail(object):
self
.
cause
=
unicode
(
exc
)
self
.
cause
=
unicode
(
exc
)
self
.
traceback
=
traceback
.
format_exc
(
exc
)
self
.
traceback
=
traceback
.
format_exc
(
exc
)
class
LettuceSyntaxError
(
SyntaxError
):
class
LettuceSyntaxError
(
SyntaxError
):
def
__init__
(
self
,
filename
,
string
):
def
__init__
(
self
,
filename
,
string
):
self
.
filename
=
filename
self
.
filename
=
filename
...
...
lettuce/fs.py
View file @
86dd4e89
...
@@ -25,6 +25,7 @@ import zipfile
...
@@ -25,6 +25,7 @@ import zipfile
from
glob
import
glob
from
glob
import
glob
from
os.path
import
abspath
,
join
,
dirname
,
curdir
,
exists
from
os.path
import
abspath
,
join
,
dirname
,
curdir
,
exists
class
FeatureLoader
(
object
):
class
FeatureLoader
(
object
):
"""Loader class responsible for findind features and step
"""Loader class responsible for findind features and step
definitions along a given path on filesystem"""
definitions along a given path on filesystem"""
...
@@ -47,13 +48,14 @@ class FeatureLoader(object):
...
@@ -47,13 +48,14 @@ class FeatureLoader(object):
else
:
else
:
raise
e
raise
e
reload
(
module
)
# always take fresh meat :)
reload
(
module
)
# always take fresh meat :)
sys
.
path
.
remove
(
root
)
sys
.
path
.
remove
(
root
)
def
find_feature_files
(
self
):
def
find_feature_files
(
self
):
paths
=
FileSystem
.
locate
(
self
.
base_dir
,
"*.feature"
)
paths
=
FileSystem
.
locate
(
self
.
base_dir
,
"*.feature"
)
return
paths
return
paths
class
FileSystem
(
object
):
class
FileSystem
(
object
):
"""File system abstraction, mainly used for indirection, so that
"""File system abstraction, mainly used for indirection, so that
lettuce can be well unit-tested :)
lettuce can be well unit-tested :)
...
@@ -229,4 +231,3 @@ class FileSystem(object):
...
@@ -229,4 +231,3 @@ class FileSystem(object):
path
=
cls
.
current_dir
(
name
)
path
=
cls
.
current_dir
(
name
)
return
open
(
path
,
mode
)
return
open
(
path
,
mode
)
lettuce/lettuce_cli.py
View file @
86dd4e89
...
@@ -21,12 +21,12 @@ import optparse
...
@@ -21,12 +21,12 @@ import optparse
import
lettuce
import
lettuce
def
main
(
args
=
sys
.
argv
[
1
:]):
def
main
(
args
=
sys
.
argv
[
1
:]):
base_path
=
os
.
path
.
join
(
os
.
path
.
dirname
(
os
.
curdir
),
'features'
)
base_path
=
os
.
path
.
join
(
os
.
path
.
dirname
(
os
.
curdir
),
'features'
)
parser
=
optparse
.
OptionParser
(
parser
=
optparse
.
OptionParser
(
usage
=
"
%
prog or type
%
prog -h (--help) for help"
,
usage
=
"
%
prog or type
%
prog -h (--help) for help"
,
version
=
lettuce
.
version
version
=
lettuce
.
version
)
)
parser
.
add_option
(
"-v"
,
"--verbosity"
,
parser
.
add_option
(
"-v"
,
"--verbosity"
,
dest
=
"verbosity"
,
dest
=
"verbosity"
,
...
@@ -74,7 +74,7 @@ def main(args=sys.argv[1:]):
...
@@ -74,7 +74,7 @@ def main(args=sys.argv[1:]):
verbosity
=
options
.
verbosity
,
verbosity
=
options
.
verbosity
,
enable_xunit
=
options
.
enable_xunit
,
enable_xunit
=
options
.
enable_xunit
,
xunit_filename
=
options
.
xunit_file
,
xunit_filename
=
options
.
xunit_file
,
run_controller
=
run_controller
)
run_controller
=
run_controller
)
result
=
runner
.
run
()
result
=
runner
.
run
()
if
not
result
or
result
.
steps
!=
result
.
steps_passed
:
if
not
result
or
result
.
steps
!=
result
.
steps_passed
:
...
...
lettuce/plugins/colored_shell_output.py
View file @
86dd4e89
...
@@ -17,8 +17,6 @@
...
@@ -17,8 +17,6 @@
import
os
import
os
import
re
import
re
import
sys
import
sys
import
platform
import
struct
from
lettuce
import
core
from
lettuce
import
core
from
lettuce
import
strings
from
lettuce
import
strings
...
@@ -27,12 +25,15 @@ from lettuce import terminal
...
@@ -27,12 +25,15 @@ from lettuce import terminal
from
lettuce.terrain
import
after
from
lettuce.terrain
import
after
from
lettuce.terrain
import
before
from
lettuce.terrain
import
before
def
wrt
(
what
):
def
wrt
(
what
):
sys
.
stdout
.
write
(
what
.
encode
(
'utf-8'
))
sys
.
stdout
.
write
(
what
.
encode
(
'utf-8'
))
def
wrap_file_and_line
(
string
,
start
,
end
):
def
wrap_file_and_line
(
string
,
start
,
end
):
return
re
.
sub
(
r'([#] [^:]+[:]\d+)'
,
'
%
s
\
g<1>
%
s'
%
(
start
,
end
),
string
)
return
re
.
sub
(
r'([#] [^:]+[:]\d+)'
,
'
%
s
\
g<1>
%
s'
%
(
start
,
end
),
string
)
def
wp
(
l
):
def
wp
(
l
):
if
l
.
startswith
(
"
\033
[1;32m"
):
if
l
.
startswith
(
"
\033
[1;32m"
):
l
=
l
.
replace
(
" |"
,
"
\033
[1;37m |
\033
[1;32m"
)
l
=
l
.
replace
(
" |"
,
"
\033
[1;37m |
\033
[1;32m"
)
...
@@ -47,9 +48,11 @@ def wp(l):
...
@@ -47,9 +48,11 @@ def wp(l):
return
l
return
l
def
write_out
(
what
):
def
write_out
(
what
):
wrt
(
wp
(
what
))
wrt
(
wp
(
what
))
@before.each_step
@before.each_step
def
print_step_running
(
step
):
def
print_step_running
(
step
):
if
not
step
.
defined_at
:
if
not
step
.
defined_at
:
...
@@ -67,6 +70,7 @@ def print_step_running(step):
...
@@ -67,6 +70,7 @@ def print_step_running(step):
for
line
in
step
.
represent_hashes
()
.
splitlines
():
for
line
in
step
.
represent_hashes
()
.
splitlines
():
write_out
(
"
\033
[1;30m
%
s
\033
[0m
\n
"
%
line
)
write_out
(
"
\033
[1;30m
%
s
\033
[0m
\n
"
%
line
)
@after.each_step
@after.each_step
def
print_step_ran
(
step
):
def
print_step_ran
(
step
):
if
step
.
scenario
.
outlines
:
if
step
.
scenario
.
outlines
:
...
@@ -80,7 +84,6 @@ def print_step_ran(step):
...
@@ -80,7 +84,6 @@ def print_step_ran(step):
if
not
step
.
failed
:
if
not
step
.
failed
:
string
=
wrap_file_and_line
(
string
,
'
\033
[1;30m'
,
'
\033
[0m'
)
string
=
wrap_file_and_line
(
string
,
'
\033
[1;30m'
,
'
\033
[0m'
)
prefix
=
'
\033
[A'
prefix
=
'
\033
[A'
width
,
height
=
terminal
.
get_size
()
width
,
height
=
terminal
.
get_size
()
lines_up
=
len
(
string
)
/
float
(
width
)
lines_up
=
len
(
string
)
/
float
(
width
)
...
@@ -123,12 +126,14 @@ def print_step_ran(step):
...
@@ -123,12 +126,14 @@ def print_step_ran(step):
wrt
(
"
\033
[0m
\n
"
)
wrt
(
"
\033
[0m
\n
"
)
@before.each_scenario
@before.each_scenario
def
print_scenario_running
(
scenario
):
def
print_scenario_running
(
scenario
):
string
=
scenario
.
represented
()
string
=
scenario
.
represented
()
string
=
wrap_file_and_line
(
string
,
'
\033
[1;30m'
,
'
\033
[0m'
)
string
=
wrap_file_and_line
(
string
,
'
\033
[1;30m'
,
'
\033
[0m'
)
write_out
(
"
\n\033
[1;37m
%
s"
%
string
)
write_out
(
"
\n\033
[1;37m
%
s"
%
string
)
@after.outline
@after.outline
def
print_outline
(
scenario
,
order
,
outline
,
reasons_to_fail
):
def
print_outline
(
scenario
,
order
,
outline
,
reasons_to_fail
):
table
=
strings
.
dicts_to_string
(
scenario
.
outlines
,
scenario
.
keys
)
table
=
strings
.
dicts_to_string
(
scenario
.
outlines
,
scenario
.
keys
)
...
@@ -155,6 +160,7 @@ def print_outline(scenario, order, outline, reasons_to_fail):
...
@@ -155,6 +160,7 @@ def print_outline(scenario, order, outline, reasons_to_fail):
wrt
(
"
\033
[0m
\n
"
)
wrt
(
"
\033
[0m
\n
"
)
@before.each_feature
@before.each_feature
def
print_feature_running
(
feature
):
def
print_feature_running
(
feature
):
string
=
feature
.
represented
()
string
=
feature
.
represented
()
...
@@ -165,6 +171,7 @@ def print_feature_running(feature):
...
@@ -165,6 +171,7 @@ def print_feature_running(feature):
line
=
wrap_file_and_line
(
line
,
'
\033
[1;30m'
,
'
\033
[0m'
)
line
=
wrap_file_and_line
(
line
,
'
\033
[1;30m'
,
'
\033
[0m'
)
write_out
(
"
\033
[1;37m
%
s
\n
"
%
line
)
write_out
(
"
\033
[1;37m
%
s
\n
"
%
line
)
@after.all
@after.all
def
print_end
(
total
):
def
print_end
(
total
):
write_out
(
"
\n
"
)
write_out
(
"
\n
"
)
...
@@ -179,9 +186,7 @@ def print_end(total):
...
@@ -179,9 +186,7 @@ def print_end(total):
total
.
features_ran
,
total
.
features_ran
,
word
,
word
,
color
,
color
,
total
.
features_passed
total
.
features_passed
))
)
)
color
=
"
\033
[1;32m"
color
=
"
\033
[1;32m"
if
total
.
scenarios_passed
is
0
:
if
total
.
scenarios_passed
is
0
:
...
@@ -192,9 +197,7 @@ def print_end(total):
...
@@ -192,9 +197,7 @@ def print_end(total):
total
.
scenarios_ran
,
total
.
scenarios_ran
,
word
,
word
,
color
,
color
,
total
.
scenarios_passed
total
.
scenarios_passed
))
)
)
steps_details
=
[]
steps_details
=
[]
kinds_and_colors
=
{
kinds_and_colors
=
{
...
@@ -203,14 +206,11 @@ def print_end(total):
...
@@ -203,14 +206,11 @@ def print_end(total):
'undefined'
:
'
\033
[0;33m'
'undefined'
:
'
\033
[0;33m'
}
}
for
kind
,
color
in
kinds_and_colors
.
items
():
for
kind
,
color
in
kinds_and_colors
.
items
():
attr
=
'steps_
%
s'
%
kind
attr
=
'steps_
%
s'
%
kind
stotal
=
getattr
(
total
,
attr
)
stotal
=
getattr
(
total
,
attr
)
if
stotal
:
if
stotal
:
steps_details
.
append
(
steps_details
.
append
(
"
%
s
%
d
%
s"
%
(
color
,
stotal
,
kind
))
"
%
s
%
d
%
s"
%
(
color
,
stotal
,
kind
)
)
steps_details
.
append
(
"
\033
[1;32m
%
d passed
\033
[1;37m"
%
total
.
steps_passed
)
steps_details
.
append
(
"
\033
[1;32m
%
d passed
\033
[1;37m"
%
total
.
steps_passed
)
word
=
total
.
steps
>
1
and
"steps"
or
"step"
word
=
total
.
steps
>
1
and
"steps"
or
"step"
...
@@ -220,9 +220,7 @@ def print_end(total):
...
@@ -220,9 +220,7 @@ def print_end(total):
write_out
(
"
\033
[1;37m
%
d
%
s (
%
s)
\033
[0m
\n
"
%
(
write_out
(
"
\033
[1;37m
%
d
%
s (
%
s)
\033
[0m
\n
"
%
(
total
.
steps
,
total
.
steps
,
word
,
word
,
content
content
))
)
)
if
total
.
proposed_definitions
:
if
total
.
proposed_definitions
:
wrt
(
"
\n\033
[0;33mYou can implement step definitions for undefined steps with these snippets:
\n\n
"
)
wrt
(
"
\n\033
[0;33mYou can implement step definitions for undefined steps with these snippets:
\n\n
"
)
...
@@ -240,6 +238,7 @@ def print_end(total):
...
@@ -240,6 +238,7 @@ def print_end(total):
wrt
(
"
\n
"
)
wrt
(
"
\n
"
)
def
print_no_features_found
(
where
):
def
print_no_features_found
(
where
):
where
=
core
.
fs
.
relpath
(
where
)
where
=
core
.
fs
.
relpath
(
where
)
if
not
where
.
startswith
(
os
.
sep
):
if
not
where
.
startswith
(
os
.
sep
):
...
@@ -248,5 +247,4 @@ def print_no_features_found(where):
...
@@ -248,5 +247,4 @@ def print_no_features_found(where):
write_out
(
'
\033
[1;31mOops!
\033
[0m
\n
'
)
write_out
(
'
\033
[1;31mOops!
\033
[0m
\n
'
)
write_out
(
write_out
(
'
\033
[1;37mcould not find features at '
'
\033
[1;37mcould not find features at '
'
\033
[1;33m
%
s
\033
[0m
\n
'
%
where
'
\033
[1;33m
%
s
\033
[0m
\n
'
%
where
)
)
lettuce/plugins/dots.py
View file @
86dd4e89
...
@@ -23,9 +23,11 @@ from lettuce.terrain import after
...
@@ -23,9 +23,11 @@ from lettuce.terrain import after
failed_scenarios
=
[]
failed_scenarios
=
[]
scenarios_and_its_fails
=
{}
scenarios_and_its_fails
=
{}
def
wrt
(
string
):
def
wrt
(
string
):
sys
.
stdout
.
write
(
string
)
sys
.
stdout
.
write
(
string
)
@after.each_step
@after.each_step
def
print_scenario_ran
(
step
):
def
print_scenario_ran
(
step
):
if
not
step
.
failed
:
if
not
step
.
failed
:
...
@@ -40,6 +42,7 @@ def print_scenario_ran(step):
...
@@ -40,6 +42,7 @@ def print_scenario_ran(step):
else
:
else
:
wrt
(
"E"
)
wrt
(
"E"
)
@after.all
@after.all
def
print_end
(
total
):
def
print_end
(
total
):
if
total
.
scenarios_passed
<
total
.
scenarios_ran
:
if
total
.
scenarios_passed
<
total
.
scenarios_ran
:
...
@@ -54,35 +57,28 @@ def print_end(total):
...
@@ -54,35 +57,28 @@ def print_end(total):
wrt
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
wrt
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
total
.
features_ran
,
total
.
features_ran
,
word
,
word
,
total
.
features_passed
total
.
features_passed
))
)
)
word
=
total
.
scenarios_ran
>
1
and
"scenarios"
or
"scenario"
word
=
total
.
scenarios_ran
>
1
and
"scenarios"
or
"scenario"
wrt
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
wrt
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
total
.
scenarios_ran
,
total
.
scenarios_ran
,
word
,
word
,
total
.
scenarios_passed
total
.
scenarios_passed
))
)
)
steps_details
=
[]
steps_details
=
[]
for
kind
in
(
"failed"
,
"skipped"
,
"undefined"
)
:
for
kind
in
"failed"
,
"skipped"
,
"undefined"
:
attr
=
'steps_
%
s'
%
kind
attr
=
'steps_
%
s'
%
kind
stotal
=
getattr
(
total
,
attr
)
stotal
=
getattr
(
total
,
attr
)
if
stotal
:
if
stotal
:
steps_details
.
append
(
steps_details
.
append
(
"
%
d
%
s"
%
(
stotal
,
kind
))
"
%
d
%
s"
%
(
stotal
,
kind
)
)
steps_details
.
append
(
"
%
d passed"
%
total
.
steps_passed
)
steps_details
.
append
(
"
%
d passed"
%
total
.
steps_passed
)
word
=
total
.
steps
>
1
and
"steps"
or
"step"
word
=
total
.
steps
>
1
and
"steps"
or
"step"
wrt
(
"
%
d
%
s (
%
s)
\n
"
%
(
wrt
(
"
%
d
%
s (
%
s)
\n
"
%
(
total
.
steps
,
total
.
steps
,
word
,
word
,
", "
.
join
(
steps_details
)
", "
.
join
(
steps_details
)))
)
)
def
print_no_features_found
(
where
):
def
print_no_features_found
(
where
):
where
=
core
.
fs
.
relpath
(
where
)
where
=
core
.
fs
.
relpath
(
where
)
...
@@ -90,7 +86,4 @@ def print_no_features_found(where):
...
@@ -90,7 +86,4 @@ def print_no_features_found(where):
where
=
'.
%
s
%
s'
%
(
os
.
sep
,
where
)
where
=
'.
%
s
%
s'
%
(
os
.
sep
,
where
)
wrt
(
'Oops!
\n
'
)
wrt
(
'Oops!
\n
'
)
wrt
(
wrt
(
'could not find features at
%
s
\n
'
%
where
)
'could not find features at '
'
%
s
\n
'
%
where
)
lettuce/plugins/non_verbose.py
View file @
86dd4e89
...
@@ -20,24 +20,29 @@ from lettuce import core
...
@@ -20,24 +20,29 @@ from lettuce import core
from
lettuce.terrain
import
after
from
lettuce.terrain
import
after
from
lettuce.terrain
import
before
from
lettuce.terrain
import
before
@before.each_step
@before.each_step
def
print_step_running
(
step
):
def
print_step_running
(
step
):
logging
.
info
(
step
.
represent_string
(
step
.
sentence
))
logging
.
info
(
step
.
represent_string
(
step
.
sentence
))
@after.each_step
@after.each_step
def
print_step_ran
(
step
):
def
print_step_ran
(
step
):
logging
.
info
(
"
\033
[A"
+
step
.
represent_string
(
step
.
sentence
))
logging
.
info
(
"
\033
[A"
+
step
.
represent_string
(
step
.
sentence
))
@before.each_scenario
@before.each_scenario
def
print_scenario_running
(
scenario
):
def
print_scenario_running
(
scenario
):
logging
.
info
(
scenario
.
represented
())
logging
.
info
(
scenario
.
represented
())
@before.each_feature
@before.each_feature
def
print_feature_running
(
feature
):
def
print_feature_running
(
feature
):
logging
.
info
(
"
\n
"
)
logging
.
info
(
"
\n
"
)
logging
.
info
(
feature
.
represented
())
logging
.
info
(
feature
.
represented
())
logging
.
info
(
"
\n
"
)
logging
.
info
(
"
\n
"
)
@after.all
@after.all
def
print_end
(
total
):
def
print_end
(
total
):
logging
.
info
(
"
\n
"
)
logging
.
info
(
"
\n
"
)
...
@@ -45,25 +50,20 @@ def print_end(total):
...
@@ -45,25 +50,20 @@ def print_end(total):
logging
.
info
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
logging
.
info
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
total
.
features_ran
,
total
.
features_ran
,
word
,
word
,
total
.
features_passed
total
.
features_passed
))
)
)
word
=
total
.
scenarios_ran
>
1
and
"scenarios"
or
"scenario"
word
=
total
.
scenarios_ran
>
1
and
"scenarios"
or
"scenario"
logging
.
info
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
logging
.
info
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
total
.
scenarios_ran
,
total
.
scenarios_ran
,
word
,
word
,
total
.
scenarios_passed
total
.
scenarios_passed
))
)
)
word
=
total
.
steps
>
1
and
"steps"
or
"step"
word
=
total
.
steps
>
1
and
"steps"
or
"step"
logging
.
info
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
logging
.
info
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
total
.
steps
,
total
.
steps
,
word
,
word
,
total
.
steps_passed
total
.
steps_passed
))
)
)
def
print_no_features_found
(
where
):
def
print_no_features_found
(
where
):
where
=
core
.
fs
.
relpath
(
where
)
where
=
core
.
fs
.
relpath
(
where
)
...
@@ -73,6 +73,4 @@ def print_no_features_found(where):
...
@@ -73,6 +73,4 @@ def print_no_features_found(where):
logging
.
info
(
'
\033
[1;31mOops!
\033
[0m
\n
'
)
logging
.
info
(
'
\033
[1;31mOops!
\033
[0m
\n
'
)
logging
.
info
(
logging
.
info
(
'
\033
[1;37mcould not find features at '
'
\033
[1;37mcould not find features at '
'
\033
[1;33m
%
s
\033
[0m
\n
'
%
where
'
\033
[1;33m
%
s
\033
[0m
\n
'
%
where
)
)
lettuce/plugins/scenario_names.py
View file @
86dd4e89
...
@@ -24,13 +24,16 @@ from lettuce.terrain import before
...
@@ -24,13 +24,16 @@ from lettuce.terrain import before
failed_scenarios
=
[]
failed_scenarios
=
[]
scenarios_and_its_fails
=
{}
scenarios_and_its_fails
=
{}
def
wrt
(
string
):
def
wrt
(
string
):
sys
.
stdout
.
write
(
string
.
encode
(
'utf-8'
))
sys
.
stdout
.
write
(
string
.
encode
(
'utf-8'
))
@before.each_scenario
@before.each_scenario
def
print_scenario_running
(
scenario
):
def
print_scenario_running
(
scenario
):
wrt
(
'
%
s ... '
%
scenario
.
name
)
wrt
(
'
%
s ... '
%
scenario
.
name
)
@after.each_scenario
@after.each_scenario
def
print_scenario_ran
(
scenario
):
def
print_scenario_ran
(
scenario
):
if
scenario
.
passed
:
if
scenario
.
passed
:
...
@@ -42,16 +45,18 @@ def print_scenario_ran(scenario):
...
@@ -42,16 +45,18 @@ def print_scenario_ran(scenario):
else
:
else
:
print
"ERROR"
print
"ERROR"
@after.each_step
@after.each_step
def
save_step_failed
(
step
):
def
save_step_failed
(
step
):
if
step
.
failed
and
step
.
scenario
not
in
failed_scenarios
:
if
step
.
failed
and
step
.
scenario
not
in
failed_scenarios
:
scenarios_and_its_fails
[
step
.
scenario
]
=
step
.
why
scenarios_and_its_fails
[
step
.
scenario
]
=
step
.
why
failed_scenarios
.
append
(
step
.
scenario
)
failed_scenarios
.
append
(
step
.
scenario
)
@after.all
@after.all
def
print_end
(
total
):
def
print_end
(
total
):
if
total
.
scenarios_passed
<
total
.
scenarios_ran
:
if
total
.
scenarios_passed
<
total
.
scenarios_ran
:
print
# just a line to separate things here
print
# just a line to separate things here
for
scenario
in
failed_scenarios
:
for
scenario
in
failed_scenarios
:
reason
=
scenarios_and_its_fails
[
scenario
]
reason
=
scenarios_and_its_fails
[
scenario
]
wrt
(
reason
.
traceback
)
wrt
(
reason
.
traceback
)
...
@@ -61,35 +66,25 @@ def print_end(total):
...
@@ -61,35 +66,25 @@ def print_end(total):
wrt
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
wrt
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
total
.
features_ran
,
total
.
features_ran
,
word
,
word
,
total
.
features_passed
total
.
features_passed
))
)
)
word
=
total
.
scenarios_ran
>
1
and
"scenarios"
or
"scenario"
word
=
total
.
scenarios_ran
>
1
and
"scenarios"
or
"scenario"
wrt
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
wrt
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
total
.
scenarios_ran
,
total
.
scenarios_ran
,
word
,
word
,
total
.
scenarios_passed
total
.
scenarios_passed
))
)
)
steps_details
=
[]
steps_details
=
[]
for
kind
in
(
"failed"
,
"skipped"
,
"undefined"
)
:
for
kind
in
"failed"
,
"skipped"
,
"undefined"
:
attr
=
'steps_
%
s'
%
kind
attr
=
'steps_
%
s'
%
kind
stotal
=
getattr
(
total
,
attr
)
stotal
=
getattr
(
total
,
attr
)
if
stotal
:
if
stotal
:
steps_details
.
append
(
steps_details
.
append
(
"
%
d
%
s"
%
(
stotal
,
kind
))
"
%
d
%
s"
%
(
stotal
,
kind
)
)
steps_details
.
append
(
"
%
d passed"
%
total
.
steps_passed
)
steps_details
.
append
(
"
%
d passed"
%
total
.
steps_passed
)
word
=
total
.
steps
>
1
and
"steps"
or
"step"
word
=
total
.
steps
>
1
and
"steps"
or
"step"
wrt
(
"
%
d
%
s (
%
s)
\n
"
%
(
wrt
(
"
%
d
%
s (
%
s)
\n
"
%
(
total
.
steps
,
word
,
", "
.
join
(
steps_details
)))
total
.
steps
,
word
,
", "
.
join
(
steps_details
)
)
)
def
print_no_features_found
(
where
):
def
print_no_features_found
(
where
):
where
=
core
.
fs
.
relpath
(
where
)
where
=
core
.
fs
.
relpath
(
where
)
...
@@ -97,7 +92,4 @@ def print_no_features_found(where):
...
@@ -97,7 +92,4 @@ def print_no_features_found(where):
where
=
'.
%
s
%
s'
%
(
os
.
sep
,
where
)
where
=
'.
%
s
%
s'
%
(
os
.
sep
,
where
)
wrt
(
'Oops!
\n
'
)
wrt
(
'Oops!
\n
'
)
wrt
(
wrt
(
'could not find features at
%
s
\n
'
%
where
)
'could not find features at '
'
%
s
\n
'
%
where
)
lettuce/plugins/shell_output.py
View file @
86dd4e89
...
@@ -22,9 +22,11 @@ from lettuce import strings
...
@@ -22,9 +22,11 @@ from lettuce import strings
from
lettuce.terrain
import
after
from
lettuce.terrain
import
after
from
lettuce.terrain
import
before
from
lettuce.terrain
import
before
def
wrt
(
what
):
def
wrt
(
what
):
sys
.
stdout
.
write
(
what
.
encode
(
'utf-8'
))
sys
.
stdout
.
write
(
what
.
encode
(
'utf-8'
))
@after.each_step
@after.each_step
def
print_step_running
(
step
):
def
print_step_running
(
step
):
wrt
(
step
.
represent_string
(
step
.
original_sentence
)
.
rstrip
())
wrt
(
step
.
represent_string
(
step
.
original_sentence
)
.
rstrip
())
...
@@ -41,11 +43,13 @@ def print_step_running(step):
...
@@ -41,11 +43,13 @@ def print_step_running(step):
for
line
in
step
.
why
.
traceback
.
splitlines
():
for
line
in
step
.
why
.
traceback
.
splitlines
():
print_spaced
(
line
)
print_spaced
(
line
)
@before.each_scenario
@before.each_scenario
def
print_scenario_running
(
scenario
):
def
print_scenario_running
(
scenario
):
wrt
(
'
\n
'
)
wrt
(
'
\n
'
)
wrt
(
scenario
.
represented
())
wrt
(
scenario
.
represented
())
@after.outline
@after.outline
def
print_outline
(
scenario
,
order
,
outline
,
reasons_to_fail
):
def
print_outline
(
scenario
,
order
,
outline
,
reasons_to_fail
):
table
=
strings
.
dicts_to_string
(
scenario
.
outlines
,
scenario
.
keys
)
table
=
strings
.
dicts_to_string
(
scenario
.
outlines
,
scenario
.
keys
)
...
@@ -66,11 +70,13 @@ def print_outline(scenario, order, outline, reasons_to_fail):
...
@@ -66,11 +70,13 @@ def print_outline(scenario, order, outline, reasons_to_fail):
for
line
in
elines
:
for
line
in
elines
:
print_spaced
(
line
)
print_spaced
(
line
)
@before.each_feature
@before.each_feature
def
print_feature_running
(
feature
):
def
print_feature_running
(
feature
):
wrt
(
"
\n
"
)
wrt
(
"
\n
"
)
wrt
(
feature
.
represented
())
wrt
(
feature
.
represented
())
@after.all
@after.all
def
print_end
(
total
):
def
print_end
(
total
):
wrt
(
"
\n
"
)
wrt
(
"
\n
"
)
...
@@ -78,35 +84,27 @@ def print_end(total):
...
@@ -78,35 +84,27 @@ def print_end(total):
wrt
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
wrt
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
total
.
features_ran
,
total
.
features_ran
,
word
,
word
,
total
.
features_passed
total
.
features_passed
))
)
)
word
=
total
.
scenarios_ran
>
1
and
"scenarios"
or
"scenario"
word
=
total
.
scenarios_ran
>
1
and
"scenarios"
or
"scenario"
wrt
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
wrt
(
"
%
d
%
s (
%
d passed)
\n
"
%
(
total
.
scenarios_ran
,
total
.
scenarios_ran
,
word
,
word
,
total
.
scenarios_passed
total
.
scenarios_passed
))
)
)
steps_details
=
[]
steps_details
=
[]
for
kind
in
(
"failed"
,
"skipped"
,
"undefined"
):
for
kind
in
(
"failed"
,
"skipped"
,
"undefined"
):
attr
=
'steps_
%
s'
%
kind
attr
=
'steps_
%
s'
%
kind
stotal
=
getattr
(
total
,
attr
)
stotal
=
getattr
(
total
,
attr
)
if
stotal
:
if
stotal
:
steps_details
.
append
(
steps_details
.
append
(
"
%
d
%
s"
%
(
stotal
,
kind
))
"
%
d
%
s"
%
(
stotal
,
kind
)
)
steps_details
.
append
(
"
%
d passed"
%
total
.
steps_passed
)
steps_details
.
append
(
"
%
d passed"
%
total
.
steps_passed
)
word
=
total
.
steps
>
1
and
"steps"
or
"step"
word
=
total
.
steps
>
1
and
"steps"
or
"step"
wrt
(
"
%
d
%
s (
%
s)
\n
"
%
(
wrt
(
"
%
d
%
s (
%
s)
\n
"
%
(
total
.
steps
,
total
.
steps
,
word
,
word
,
", "
.
join
(
steps_details
)
", "
.
join
(
steps_details
)))
)
)
if
total
.
proposed_definitions
:
if
total
.
proposed_definitions
:
wrt
(
"
\n
You can implement step definitions for undefined steps with these snippets:
\n\n
"
)
wrt
(
"
\n
You can implement step definitions for undefined steps with these snippets:
\n\n
"
)
...
@@ -118,14 +116,11 @@ def print_end(total):
...
@@ -118,14 +116,11 @@ def print_end(total):
wrt
(
"def
%
s:
\n
"
%
method_name
)
wrt
(
"def
%
s:
\n
"
%
method_name
)
wrt
(
" assert False, 'This step must be implemented'
\n
"
)
wrt
(
" assert False, 'This step must be implemented'
\n
"
)
def
print_no_features_found
(
where
):
def
print_no_features_found
(
where
):
where
=
core
.
fs
.
relpath
(
where
)
where
=
core
.
fs
.
relpath
(
where
)
if
not
where
.
startswith
(
os
.
sep
):
if
not
where
.
startswith
(
os
.
sep
):
where
=
'.
%
s
%
s'
%
(
os
.
sep
,
where
)
where
=
'.
%
s
%
s'
%
(
os
.
sep
,
where
)
wrt
(
'Oops!
\n
'
)
wrt
(
'Oops!
\n
'
)
wrt
(
wrt
(
'could not find features at
%
s
\n
'
%
where
)
'could not find features at '
'
%
s
\n
'
%
where
)
lettuce/plugins/xunit_output.py
View file @
86dd4e89
...
@@ -15,7 +15,6 @@
...
@@ -15,7 +15,6 @@
# You should have received a copy of the GNU General Public License
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import
sys
from
datetime
import
datetime
from
datetime
import
datetime
from
lettuce.terrain
import
after
from
lettuce.terrain
import
after
from
lettuce.terrain
import
before
from
lettuce.terrain
import
before
...
@@ -27,9 +26,11 @@ def wrt_output(filename, content):
...
@@ -27,9 +26,11 @@ def wrt_output(filename, content):
f
.
write
(
content
.
encode
(
'utf-8'
))
f
.
write
(
content
.
encode
(
'utf-8'
))
f
.
close
()
f
.
close
()
def
total_seconds
(
td
):
def
total_seconds
(
td
):
return
(
td
.
microseconds
+
(
td
.
seconds
+
td
.
days
*
24
*
3600
)
*
1e6
)
/
1e6
return
(
td
.
microseconds
+
(
td
.
seconds
+
td
.
days
*
24
*
3600
)
*
1e6
)
/
1e6
def
enable
(
filename
=
None
):
def
enable
(
filename
=
None
):
doc
=
minidom
.
Document
()
doc
=
minidom
.
Document
()
...
@@ -51,7 +52,7 @@ def enable(filename=None):
...
@@ -51,7 +52,7 @@ def enable(filename=None):
if
step
.
failed
:
if
step
.
failed
:
cdata
=
doc
.
createCDATASection
(
step
.
why
.
traceback
)
cdata
=
doc
.
createCDATASection
(
step
.
why
.
traceback
)
failure
=
doc
.
createElement
(
"failure"
)
failure
=
doc
.
createElement
(
"failure"
)
failure
.
setAttribute
(
"message"
,
step
.
why
.
cause
)
failure
.
setAttribute
(
"message"
,
step
.
why
.
cause
)
failure
.
appendChild
(
cdata
)
failure
.
appendChild
(
cdata
)
tc
.
appendChild
(
failure
)
tc
.
appendChild
(
failure
)
...
@@ -63,4 +64,3 @@ def enable(filename=None):
...
@@ -63,4 +64,3 @@ def enable(filename=None):
root
.
setAttribute
(
"failed"
,
str
(
total
.
steps_failed
))
root
.
setAttribute
(
"failed"
,
str
(
total
.
steps_failed
))
doc
.
appendChild
(
root
)
doc
.
appendChild
(
root
)
wrt_output
(
output_filename
,
doc
.
toxml
())
wrt_output
(
output_filename
,
doc
.
toxml
())
lettuce/registry.py
View file @
86dd4e89
...
@@ -22,76 +22,57 @@ world = threading.local()
...
@@ -22,76 +22,57 @@ world = threading.local()
world
.
_set
=
False
world
.
_set
=
False
class
CleanableDict
(
dict
):
def
_function_matches
(
one
,
other
):
def
clear
(
self
):
return
(
one
.
func_code
.
co_filename
==
other
.
func_code
.
co_filename
and
for
k
in
self
.
keys
():
one
.
func_code
.
co_firstlineno
==
other
.
func_code
.
co_firstlineno
)
del
self
[
k
]
class
CallbackDict
(
CleanableDict
):
def
_function_matches
(
self
,
one
,
other
):
params
=
'co_filename'
,
'co_firstlineno'
matches
=
list
()
for
param
in
params
:
one_got
=
getattr
(
one
.
func_code
,
param
)
other_got
=
getattr
(
other
.
func_code
,
param
)
matches
.
append
(
one_got
==
other_got
)
return
all
(
matches
)
class
CallbackDict
(
dict
):
def
append_to
(
self
,
where
,
when
,
function
):
def
append_to
(
self
,
where
,
when
,
function
):
found
=
False
if
not
any
(
_function_matches
(
o
,
function
)
for
o
in
self
[
where
][
when
]):
for
other_function
in
self
[
where
][
when
]:
if
self
.
_function_matches
(
other_function
,
function
):
found
=
True
if
not
found
:
self
[
where
][
when
]
.
append
(
function
)
self
[
where
][
when
]
.
append
(
function
)
def
clear
(
self
):
def
clear
(
self
):
for
name
,
action_dict
in
self
.
items
():
for
name
,
action_dict
in
self
.
items
():
for
callback_list
in
action_dict
.
values
():
for
callback_list
in
action_dict
.
values
():
while
callback_list
:
callback_list
[:]
=
[]
callback_list
.
pop
()
STEP_REGISTRY
=
CleanableDict
()
STEP_REGISTRY
=
{}
CALLBACK_REGISTRY
=
CallbackDict
(
CALLBACK_REGISTRY
=
CallbackDict
(
{
{
'all'
:
{
'all'
:
{
'before'
:
list
()
,
'before'
:
[]
,
'after'
:
list
()
,
'after'
:
[]
,
},
},
'step'
:
{
'step'
:
{
'before_each'
:
list
()
,
'before_each'
:
[]
,
'after_each'
:
list
()
,
'after_each'
:
[]
,
},
},
'scenario'
:
{
'scenario'
:
{
'before_each'
:
list
()
,
'before_each'
:
[]
,
'after_each'
:
list
()
,
'after_each'
:
[]
,
'outline'
:
list
()
,
'outline'
:
[]
,
},
},
'feature'
:
{
'feature'
:
{
'before_each'
:
list
()
,
'before_each'
:
[]
,
'after_each'
:
list
()
,
'after_each'
:
[]
,
},
},
'app'
:
{
'app'
:
{
'before_each'
:
list
()
,
'before_each'
:
[]
,
'after_each'
:
list
()
,
'after_each'
:
[]
,
},
},
'harvest'
:
{
'harvest'
:
{
'before'
:
list
()
,
'before'
:
[]
,
'after'
:
list
()
,
'after'
:
[]
,
},
},
'handle_request'
:
{
'handle_request'
:
{
'before'
:
list
()
,
'before'
:
[]
,
'after'
:
list
()
,
'after'
:
[]
,
},
},
'runserver'
:
{
'runserver'
:
{
'before'
:
list
()
,
'before'
:
[]
,
'after'
:
list
()
,
'after'
:
[]
,
},
},
},
},
)
)
...
...
lettuce/strings.py
View file @
86dd4e89
...
@@ -17,9 +17,9 @@
...
@@ -17,9 +17,9 @@
import
re
import
re
import
time
import
time
import
string
import
unicodedata
import
unicodedata
def
escape_if_necessary
(
what
):
def
escape_if_necessary
(
what
):
what
=
unicode
(
what
)
what
=
unicode
(
what
)
if
len
(
what
)
is
1
:
if
len
(
what
)
is
1
:
...
@@ -27,6 +27,7 @@ def escape_if_necessary(what):
...
@@ -27,6 +27,7 @@ def escape_if_necessary(what):
return
what
return
what
def
get_stripped_lines
(
string
,
ignore_lines_starting_with
=
''
):
def
get_stripped_lines
(
string
,
ignore_lines_starting_with
=
''
):
string
=
unicode
(
string
)
string
=
unicode
(
string
)
lines
=
[
unicode
(
l
.
strip
())
for
l
in
string
.
splitlines
()]
lines
=
[
unicode
(
l
.
strip
())
for
l
in
string
.
splitlines
()]
...
@@ -39,12 +40,13 @@ def get_stripped_lines(string, ignore_lines_starting_with=''):
...
@@ -39,12 +40,13 @@ def get_stripped_lines(string, ignore_lines_starting_with=''):
return
lines
return
lines
def
split_wisely
(
string
,
sep
,
strip
=
False
):
def
split_wisely
(
string
,
sep
,
strip
=
False
):
string
=
unicode
(
string
)
string
=
unicode
(
string
)
if
strip
:
if
strip
:
string
=
string
.
strip
()
string
=
string
.
strip
()
else
:
else
:
string
=
string
.
strip
(
"
\n
"
)
string
=
string
.
strip
(
"
\n
"
)
sep
=
unicode
(
sep
)
sep
=
unicode
(
sep
)
regex
=
re
.
compile
(
escape_if_necessary
(
sep
),
re
.
UNICODE
|
re
.
M
|
re
.
I
)
regex
=
re
.
compile
(
escape_if_necessary
(
sep
),
re
.
UNICODE
|
re
.
M
|
re
.
I
)
...
@@ -57,15 +59,18 @@ def split_wisely(string, sep, strip=False):
...
@@ -57,15 +59,18 @@ def split_wisely(string, sep, strip=False):
return
[
unicode
(
i
)
for
i
in
items
]
return
[
unicode
(
i
)
for
i
in
items
]
def
wise_startswith
(
string
,
seed
):
def
wise_startswith
(
string
,
seed
):
string
=
unicode
(
string
)
.
strip
()
string
=
unicode
(
string
)
.
strip
()
seed
=
unicode
(
seed
)
seed
=
unicode
(
seed
)
regex
=
u"^
%
s"
%
re
.
escape
(
seed
)
regex
=
u"^
%
s"
%
re
.
escape
(
seed
)
return
bool
(
re
.
search
(
regex
,
string
,
re
.
I
))
return
bool
(
re
.
search
(
regex
,
string
,
re
.
I
))
def
remove_it
(
string
,
what
):
def
remove_it
(
string
,
what
):
return
unicode
(
re
.
sub
(
unicode
(
what
),
""
,
unicode
(
string
))
.
strip
())
return
unicode
(
re
.
sub
(
unicode
(
what
),
""
,
unicode
(
string
))
.
strip
())
def
column_width
(
string
):
def
column_width
(
string
):
l
=
0
l
=
0
for
c
in
string
:
for
c
in
string
:
...
@@ -75,6 +80,7 @@ def column_width(string):
...
@@ -75,6 +80,7 @@ def column_width(string):
l
+=
1
l
+=
1
return
l
return
l
def
rfill
(
string
,
times
,
char
=
u" "
,
append
=
u""
):
def
rfill
(
string
,
times
,
char
=
u" "
,
append
=
u""
):
string
=
unicode
(
string
)
string
=
unicode
(
string
)
missing
=
times
-
column_width
(
string
)
missing
=
times
-
column_width
(
string
)
...
@@ -83,13 +89,17 @@ def rfill(string, times, char=u" ", append=u""):
...
@@ -83,13 +89,17 @@ def rfill(string, times, char=u" ", append=u""):
return
unicode
(
string
)
+
unicode
(
append
)
return
unicode
(
string
)
+
unicode
(
append
)
def
getlen
(
string
):
def
getlen
(
string
):
return
column_width
(
unicode
(
string
))
+
1
return
column_width
(
unicode
(
string
))
+
1
def
dicts_to_string
(
dicts
,
order
):
def
dicts_to_string
(
dicts
,
order
):
escape
=
"#{
%
s}"
%
str
(
time
.
time
())
escape
=
"#{
%
s}"
%
str
(
time
.
time
())
def
enline
(
line
):
def
enline
(
line
):
return
unicode
(
line
)
.
replace
(
"|"
,
escape
)
return
unicode
(
line
)
.
replace
(
"|"
,
escape
)
def
deline
(
line
):
def
deline
(
line
):
return
line
.
replace
(
escape
,
'
\\
|'
)
return
line
.
replace
(
escape
,
'
\\
|'
)
...
@@ -120,12 +130,16 @@ def dicts_to_string(dicts, order):
...
@@ -120,12 +130,16 @@ def dicts_to_string(dicts, order):
return
deline
(
u"
\n
"
.
join
(
table
)
+
u"
\n
"
)
return
deline
(
u"
\n
"
.
join
(
table
)
+
u"
\n
"
)
def
parse_hashes
(
lines
):
def
parse_hashes
(
lines
):
escape
=
"#{
%
s}"
%
str
(
time
.
time
())
escape
=
"#{
%
s}"
%
str
(
time
.
time
())
def
enline
(
line
):
def
enline
(
line
):
return
unicode
(
line
.
replace
(
"
\\
|"
,
escape
))
.
strip
()
return
unicode
(
line
.
replace
(
"
\\
|"
,
escape
))
.
strip
()
def
deline
(
line
):
def
deline
(
line
):
return
line
.
replace
(
escape
,
'|'
)
return
line
.
replace
(
escape
,
'|'
)
def
discard_comments
(
lines
):
def
discard_comments
(
lines
):
return
[
line
for
line
in
lines
if
not
line
.
startswith
(
'#'
)]
return
[
line
for
line
in
lines
if
not
line
.
startswith
(
'#'
)]
...
@@ -146,6 +160,7 @@ def parse_hashes(lines):
...
@@ -146,6 +160,7 @@ def parse_hashes(lines):
return
keys
,
hashes
return
keys
,
hashes
def
parse_multiline
(
lines
):
def
parse_multiline
(
lines
):
multilines
=
[]
multilines
=
[]
in_multiline
=
False
in_multiline
=
False
...
@@ -163,11 +178,11 @@ def parse_multiline(lines):
...
@@ -163,11 +178,11 @@ def parse_multiline(lines):
def
extract_tags_from_line
(
given_line
):
def
extract_tags_from_line
(
given_line
):
"""returns tags_array if given_line contains tags, else None"""
"""returns tags_array if given_line contains tags, else None"""
line
=
string
.
rstrip
(
given_line
)
line
=
given_line
.
rstrip
(
)
tags
=
[]
tags
=
[]
if
re
.
match
(
"
\
s*?
\
@"
,
line
):
if
re
.
match
(
"
\
s*?
\
@"
,
line
):
tags
=
[
tag
for
tag
in
re
.
split
(
"
\
s*
\
@"
,
line
)
if
len
(
tag
)
>
0
]
tags
=
[
tag
for
tag
in
re
.
split
(
"
\
s*
\
@"
,
line
)
if
len
(
tag
)
>
0
]
if
len
(
tags
)
==
0
or
[
tag
for
tag
in
tags
if
string
.
find
(
tag
,
" "
)
!=
-
1
]
:
if
len
(
tags
)
==
0
or
any
(
' '
in
tag
for
tag
in
tags
)
:
return
None
return
None
return
tags
return
tags
...
@@ -185,6 +200,7 @@ def consume_tags_lines(lines, tags):
...
@@ -185,6 +200,7 @@ def consume_tags_lines(lines, tags):
else
:
else
:
break
break
def
consume_scenario
(
lines
,
scenario_prefix
):
def
consume_scenario
(
lines
,
scenario_prefix
):
"""return string of scenario text
"""return string of scenario text
and reduce lines array by that much"""
and reduce lines array by that much"""
...
@@ -205,6 +221,7 @@ def consume_scenario(lines, scenario_prefix):
...
@@ -205,6 +221,7 @@ def consume_scenario(lines, scenario_prefix):
scenario_lines
.
extend
(
get_lines_till_next_scenario
(
lines
,
scenario_prefix
))
scenario_lines
.
extend
(
get_lines_till_next_scenario
(
lines
,
scenario_prefix
))
return
unicode
(
"
\n
"
.
join
(
scenario_lines
))
return
unicode
(
"
\n
"
.
join
(
scenario_lines
))
def
get_lines_till_next_scenario
(
lines
,
scenario_prefix
):
def
get_lines_till_next_scenario
(
lines
,
scenario_prefix
):
"""returns array of lines up till next scenario block"""
"""returns array of lines up till next scenario block"""
sep
=
unicode
(
scenario_prefix
)
sep
=
unicode
(
scenario_prefix
)
...
@@ -222,6 +239,7 @@ def get_lines_till_next_scenario(lines, scenario_prefix):
...
@@ -222,6 +239,7 @@ def get_lines_till_next_scenario(lines, scenario_prefix):
scenario_lines
.
append
(
lines
.
pop
(
0
))
scenario_lines
.
append
(
lines
.
pop
(
0
))
return
scenario_lines
return
scenario_lines
def
split_scenarios
(
lines
,
scenario_prefix
):
def
split_scenarios
(
lines
,
scenario_prefix
):
"""returns array of strings, one per scenario"""
"""returns array of strings, one per scenario"""
scenario_strings
=
[]
scenario_strings
=
[]
...
...
lettuce/terminal.py
View file @
86dd4e89
...
@@ -18,6 +18,7 @@ import os
...
@@ -18,6 +18,7 @@ import os
import
platform
import
platform
import
struct
import
struct
def
get_size
():
def
get_size
():
if
platform
.
system
()
==
"Windows"
:
if
platform
.
system
()
==
"Windows"
:
size
=
get_terminal_size_win
()
size
=
get_terminal_size_win
()
...
@@ -29,6 +30,7 @@ def get_size():
...
@@ -29,6 +30,7 @@ def get_size():
return
size
return
size
def
get_terminal_size_win
():
def
get_terminal_size_win
():
#Windows specific imports
#Windows specific imports
from
ctypes
import
windll
,
create_string_buffer
from
ctypes
import
windll
,
create_string_buffer
...
@@ -41,20 +43,21 @@ def get_terminal_size_win():
...
@@ -41,20 +43,21 @@ def get_terminal_size_win():
res
=
windll
.
kernel32
.
GetConsoleScreenBufferInfo
(
h
,
csbi
)
res
=
windll
.
kernel32
.
GetConsoleScreenBufferInfo
(
h
,
csbi
)
if
res
:
if
res
:
import
struct
(
bufx
,
bufy
,
curx
,
cury
,
wattr
,
left
,
top
,
right
,
bottom
,
(
bufx
,
bufy
,
curx
,
cury
,
wattr
,
maxx
,
maxy
)
=
struct
.
unpack
(
"hhhhHhhhhhh"
,
csbi
.
raw
)
left
,
top
,
right
,
bottom
,
maxx
,
maxy
)
=
struct
.
unpack
(
"hhhhHhhhhhh"
,
csbi
.
raw
)
sizex
=
right
-
left
+
1
sizex
=
right
-
left
+
1
sizey
=
bottom
-
top
+
1
sizey
=
bottom
-
top
+
1
else
:
else
:
# can't determine actual size - return default values
sizex
,
sizey
=
80
,
25
# can't determine actual size - return default values
sizex
,
sizey
=
80
,
25
return
sizex
,
sizey
return
sizex
,
sizey
def
get_terminal_size_unix
():
def
get_terminal_size_unix
():
# Unix/Posix specific imports
# Unix/Posix specific imports
import
fcntl
,
termios
import
fcntl
import
termios
def
ioctl_GWINSZ
(
fd
):
def
ioctl_GWINSZ
(
fd
):
try
:
try
:
cr
=
struct
.
unpack
(
'hh'
,
fcntl
.
ioctl
(
fd
,
termios
.
TIOCGWINSZ
,
cr
=
struct
.
unpack
(
'hh'
,
fcntl
.
ioctl
(
fd
,
termios
.
TIOCGWINSZ
,
...
...
lettuce/terrain.py
View file @
86dd4e89
...
@@ -18,6 +18,7 @@ from lettuce.registry import world
...
@@ -18,6 +18,7 @@ from lettuce.registry import world
from
lettuce.registry
import
CALLBACK_REGISTRY
from
lettuce.registry
import
CALLBACK_REGISTRY
world
.
_set
=
True
world
.
_set
=
True
def
absorb
(
thing
,
name
=
None
):
def
absorb
(
thing
,
name
=
None
):
if
not
isinstance
(
name
,
basestring
):
if
not
isinstance
(
name
,
basestring
):
name
=
thing
.
__name__
name
=
thing
.
__name__
...
@@ -27,6 +28,7 @@ def absorb(thing, name=None):
...
@@ -27,6 +28,7 @@ def absorb(thing, name=None):
world
.
absorb
=
absorb
world
.
absorb
=
absorb
@world.absorb
@world.absorb
def
spew
(
name
):
def
spew
(
name
):
if
hasattr
(
world
,
name
):
if
hasattr
(
world
,
name
):
...
@@ -34,54 +36,29 @@ def spew(name):
...
@@ -34,54 +36,29 @@ def spew(name):
delattr
(
world
,
name
)
delattr
(
world
,
name
)
return
item
return
item
class
main
(
object
):
@classmethod
def
all
(
cls
,
function
):
CALLBACK_REGISTRY
.
append_to
(
'all'
,
cls
.
__name__
,
function
)
return
function
@classmethod
def
each_step
(
cls
,
function
):
CALLBACK_REGISTRY
.
append_to
(
'step'
,
"
%
s_each"
%
cls
.
__name__
,
function
)
return
function
@classmethod
def
each_scenario
(
cls
,
function
):
CALLBACK_REGISTRY
.
append_to
(
'scenario'
,
"
%
s_each"
%
cls
.
__name__
,
function
)
return
function
@classmethod
def
each_feature
(
cls
,
function
):
CALLBACK_REGISTRY
.
append_to
(
'feature'
,
"
%
s_each"
%
cls
.
__name__
,
function
)
return
function
@classmethod
def
harvest
(
cls
,
function
):
CALLBACK_REGISTRY
.
append_to
(
'harvest'
,
cls
.
__name__
,
function
)
return
function
@classmethod
def
each_app
(
cls
,
function
):
CALLBACK_REGISTRY
.
append_to
(
'app'
,
"
%
s_each"
%
cls
.
__name__
,
function
)
return
function
@classmethod
def
runserver
(
cls
,
function
):
CALLBACK_REGISTRY
.
append_to
(
'runserver'
,
cls
.
__name__
,
function
)
return
function
@classmethod
class
Main
(
object
):
def
handle_request
(
cls
,
function
):
def
__init__
(
self
,
callback
):
CALLBACK_REGISTRY
.
append_to
(
'handle_request'
,
cls
.
__name__
,
function
)
self
.
name
=
callback
return
function
@classmethod
@classmethod
def
outline
(
cls
,
function
):
def
_add_method
(
cls
,
name
,
where
,
when
):
CALLBACK_REGISTRY
.
append_to
(
'scenario'
,
"outline"
,
function
)
def
method
(
self
,
fn
):
return
function
CALLBACK_REGISTRY
.
append_to
(
where
,
when
.
format
(
self
.
name
),
fn
)
method
.
__name__
=
method
.
fn_name
=
name
setattr
(
cls
,
name
,
method
)
class
before
(
main
):
for
name
,
where
,
when
in
(
pass
(
'all'
,
'all'
,
'{0}'
),
(
'each_step'
,
'step'
,
'{0}_each'
),
(
'each_scenario'
,
'scenario'
,
'{0}_each'
),
(
'each_feature'
,
'feature'
,
'{0}_each'
),
(
'harvest'
,
'harvest'
,
'{0}'
),
(
'each_app'
,
'app'
,
'{0}_each'
),
(
'runserver'
,
'runserver'
,
'{0}'
),
(
'handle_request'
,
'handle_request'
,
'{0}'
),
(
'outline'
,
'scenario'
,
'outline'
)):
Main
.
_add_method
(
name
,
where
,
when
)
class
after
(
main
):
before
=
Main
(
'before'
)
pass
after
=
Main
(
'after'
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment