How to use option method in Pytest

Best Python code snippet using pytest

test_util_open_ended.py

Source:test_util_open_ended.py Github

copy

Full Screen

1import json2from textwrap import dedent3from xmodule.modulestore.xml import XMLModuleStore4from xmodule.tests import DATA_DIR, get_test_system5from StringIO import StringIO6OPEN_ENDED_GRADING_INTERFACE = {7 'url': 'blah/',8 'username': 'incorrect',9 'password': 'incorrect',10 'staff_grading': 'staff_grading',11 'peer_grading': 'peer_grading',12 'grading_controller': 'grading_controller'13}14S3_INTERFACE = {15 'access_key': "",16 'secret_access_key': "",17 "storage_bucket_name": "",18}19class MockS3Key(object):20 """21 Mock an S3 Key object from boto. Used for file upload testing.22 """23 def __init__(self, bucket):24 pass25 def set_metadata(self, key, value):26 setattr(self, key, value)27 def set_contents_from_file(self, fileobject):28 self.data = fileobject.read()29 def set_acl(self, acl):30 self.set_metadata("acl", acl)31 def generate_url(self, timeout):32 return "http://www.edx.org/sample_url"33class MockS3Connection(object):34 """35 Mock boto S3Connection for testing image uploads.36 """37 def __init__(self, access_key, secret_key, **kwargs):38 """39 Mock the init call. S3Connection has a lot of arguments, but we don't need them.40 """41 pass42 def create_bucket(self, bucket_name, **kwargs):43 return "edX Bucket"44 def lookup(self, bucket_name):45 return None46class MockUploadedFile(object):47 """48 Create a mock uploaded file for image submission tests.49 value - String data to place into the mock file.50 return - A StringIO object that behaves like a file.51 """52 def __init__(self, name, value):53 self.mock_file = StringIO()54 self.mock_file.write(value)55 self.name = name56 def seek(self, index):57 return self.mock_file.seek(index)58 def read(self):59 return self.mock_file.read()60class DummyModulestore(object):61 """62 A mixin that allows test classes to have convenience functions to get a module given a location63 """64 def get_module_system(self, descriptor):65 raise NotImplementedError("Sub-tests must specify how to generate a module-system")66 def setup_modulestore(self, name):67 self.modulestore = XMLModuleStore(DATA_DIR, course_dirs=[name])68 def get_course(self, _):69 """Get a test course by directory name. If there's more than one, error."""70 courses = self.modulestore.get_courses()71 return courses[0]72 def get_module_from_location(self, usage_key):73 descriptor = self.modulestore.get_item(usage_key, depth=None)74 descriptor.xmodule_runtime = self.get_module_system(descriptor)75 return descriptor76def serialize_child_history(task_state):77 """78 To json serialize feedback and post_assessment in child_history of task state.79 """80 child_history = task_state.get("child_history", [])81 for i, attempt in enumerate(child_history):82 if "post_assessment" in attempt:83 if "feedback" in attempt["post_assessment"]:84 attempt["post_assessment"]["feedback"] = json.dumps(attempt["post_assessment"].get("feedback"))85 task_state["child_history"][i]["post_assessment"] = json.dumps(attempt["post_assessment"])86def serialize_open_ended_instance_state(json_str):87 """88 To json serialize task_states and old_task_states in instance state.89 """90 json_data = json.loads(json_str)91 task_states = json_data.get('task_states', [])92 for i, task_state in enumerate(task_states):93 serialize_child_history(task_state)94 json_data['task_states'][i] = json.dumps(task_state)95 old_task_states = json_data.get('old_task_states', [])96 for i, old_task in enumerate(old_task_states):97 for j, task_state in enumerate(old_task):98 old_task[j] = json.dumps(task_state)99 json_data['old_task_states'][i] = old_task100 return json.dumps(json_data)101# Task state for a module with self assessment then instructor assessment.102TEST_STATE_SA_IN = ["{\"child_created\": false, \"child_attempts\": 2, \"version\": 1, \"child_history\": [{\"answer\": \"However venture pursuit he am mr cordial. Forming musical am hearing studied be luckily. Ourselves for determine attending how led gentleman sincerity. Valley afford uneasy joy she thrown though bed set. In me forming general prudent on country carried. Behaved an or suppose justice. Seemed whence how son rather easily and change missed. Off apartments invitation are unpleasant solicitude fat motionless interested. Hardly suffer wisdom wishes valley as an. As friendship advantages resolution it alteration stimulated he or increasing. \\r<br><br>Now led tedious shy lasting females off. Dashwood marianne in of entrance be on wondered possible building. Wondered sociable he carriage in speedily margaret. Up devonshire of he thoroughly insensible alteration. An mr settling occasion insisted distance ladyship so. Not attention say frankness intention out dashwoods now curiosity. Stronger ecstatic as no judgment daughter speedily thoughts. Worse downs nor might she court did nay forth these. \", \"post_assessment\": \"[3, 3, 2, 2, 2]\", \"score\": 12}, {\"answer\": \"Delightful remarkably mr on announcing themselves entreaties favourable. About to in so terms voice at. Equal an would is found seems of. The particular friendship one sufficient terminated frequently themselves. It more shed went up is roof if loud case. Delay music in lived noise an. Beyond genius really enough passed is up. \\r<br><br>John draw real poor on call my from. May she mrs furnished discourse extremely. Ask doubt noisy shade guest did built her him. Ignorant repeated hastened it do. Consider bachelor he yourself expenses no. Her itself active giving for expect vulgar months. Discovery commanded fat mrs remaining son she principle middleton neglected. Be miss he in post sons held. No tried is defer do money scale rooms. \", \"post_assessment\": \"[3, 3, 2, 2, 2]\", \"score\": 12}], \"max_score\": 12, \"child_state\": \"done\"}", "{\"child_created\": false, \"child_attempts\": 0, \"version\": 1, \"child_history\": [{\"answer\": \"However venture pursuit he am mr cordial. Forming musical am hearing studied be luckily. Ourselves for determine attending how led gentleman sincerity. Valley afford uneasy joy she thrown though bed set. In me forming general prudent on country carried. Behaved an or suppose justice. Seemed whence how son rather easily and change missed. Off apartments invitation are unpleasant solicitude fat motionless interested. Hardly suffer wisdom wishes valley as an. As friendship advantages resolution it alteration stimulated he or increasing. \\r<br><br>Now led tedious shy lasting females off. Dashwood marianne in of entrance be on wondered possible building. Wondered sociable he carriage in speedily margaret. Up devonshire of he thoroughly insensible alteration. An mr settling occasion insisted distance ladyship so. Not attention say frankness intention out dashwoods now curiosity. Stronger ecstatic as no judgment daughter speedily thoughts. Worse downs nor might she court did nay forth these. \", \"post_assessment\": \"{\\\"submission_id\\\": 1460, \\\"score\\\": 12, \\\"feedback\\\": \\\"{\\\\\\\"feedback\\\\\\\": \\\\\\\"\\\\\\\"}\\\", \\\"success\\\": true, \\\"grader_id\\\": 5413, \\\"grader_type\\\": \\\"IN\\\", \\\"rubric_scores_complete\\\": true, \\\"rubric_xml\\\": \\\"<rubric><category><description>\\\\nIdeas\\\\n</description><score>3</score><option points='0'>\\\\nDifficult for the reader to discern the main idea. Too brief or too repetitive to establish or maintain a focus.\\\\n</option><option points='1'>\\\\nAttempts a main idea. Sometimes loses focus or ineffectively displays focus.\\\\n</option><option points='2'>\\\\nPresents a unifying theme or main idea, but may include minor tangents. Stays somewhat focused on topic and task.\\\\n</option><option points='3'>\\\\nPresents a unifying theme or main idea without going off on tangents. Stays completely focused on topic and task.\\\\n</option></category><category><description>\\\\nContent\\\\n</description><score>3</score><option points='0'>\\\\nIncludes little information with few or no details or unrelated details. Unsuccessful in attempts to explore any facets of the topic.\\\\n</option><option points='1'>\\\\nIncludes little information and few or no details. Explores only one or two facets of the topic.\\\\n</option><option points='2'>\\\\nIncludes sufficient information and supporting details. (Details may not be fully developed; ideas may be listed.) Explores some facets of the topic.\\\\n</option><option points='3'>\\\\nIncludes in-depth information and exceptional supporting details that are fully developed. Explores all facets of the topic.\\\\n</option></category><category><description>\\\\nOrganization\\\\n</description><score>2</score><option points='0'>\\\\nIdeas organized illogically, transitions weak, and response difficult to follow.\\\\n</option><option points='1'>\\\\nAttempts to logically organize ideas. Attempts to progress in an order that enhances meaning, and demonstrates use of transitions.\\\\n</option><option points='2'>\\\\nIdeas organized logically. Progresses in an order that enhances meaning. Includes smooth transitions.\\\\n</option></category><category><description>\\\\nStyle\\\\n</description><score>2</score><option points='0'>\\\\nContains limited vocabulary, with many words used incorrectly. Demonstrates problems with sentence patterns.\\\\n</option><option points='1'>\\\\nContains basic vocabulary, with words that are predictable and common. Contains mostly simple sentences (although there may be an attempt at more varied sentence patterns).\\\\n</option><option points='2'>\\\\nIncludes vocabulary to make explanations detailed and precise. Includes varied sentence patterns, including complex sentences.\\\\n</option></category><category><description>\\\\nVoice\\\\n</description><score>2</score><option points='0'>\\\\nDemonstrates language and tone that may be inappropriate to task and reader.\\\\n</option><option points='1'>\\\\nDemonstrates an attempt to adjust language and tone to task and reader.\\\\n</option><option points='2'>\\\\nDemonstrates effective adjustment of language and tone to task and reader.\\\\n</option></category></rubric>\\\"}\", \"score\": 12}, {\"answer\": \"Delightful remarkably mr on announcing themselves entreaties favourable. About to in so terms voice at. Equal an would is found seems of. The particular friendship one sufficient terminated frequently themselves. It more shed went up is roof if loud case. Delay music in lived noise an. Beyond genius really enough passed is up. \\r<br><br>John draw real poor on call my from. May she mrs furnished discourse extremely. Ask doubt noisy shade guest did built her him. Ignorant repeated hastened it do. Consider bachelor he yourself expenses no. Her itself active giving for expect vulgar months. Discovery commanded fat mrs remaining son she principle middleton neglected. Be miss he in post sons held. No tried is defer do money scale rooms. \", \"post_assessment\": \"{\\\"submission_id\\\": 1462, \\\"score\\\": 12, \\\"feedback\\\": \\\"{\\\\\\\"feedback\\\\\\\": \\\\\\\"\\\\\\\"}\\\", \\\"success\\\": true, \\\"grader_id\\\": 5418, \\\"grader_type\\\": \\\"IN\\\", \\\"rubric_scores_complete\\\": true, \\\"rubric_xml\\\": \\\"<rubric><category><description>\\\\nIdeas\\\\n</description><score>3</score><option points='0'>\\\\nDifficult for the reader to discern the main idea. Too brief or too repetitive to establish or maintain a focus.\\\\n</option><option points='1'>\\\\nAttempts a main idea. Sometimes loses focus or ineffectively displays focus.\\\\n</option><option points='2'>\\\\nPresents a unifying theme or main idea, but may include minor tangents. Stays somewhat focused on topic and task.\\\\n</option><option points='3'>\\\\nPresents a unifying theme or main idea without going off on tangents. Stays completely focused on topic and task.\\\\n</option></category><category><description>\\\\nContent\\\\n</description><score>3</score><option points='0'>\\\\nIncludes little information with few or no details or unrelated details. Unsuccessful in attempts to explore any facets of the topic.\\\\n</option><option points='1'>\\\\nIncludes little information and few or no details. Explores only one or two facets of the topic.\\\\n</option><option points='2'>\\\\nIncludes sufficient information and supporting details. (Details may not be fully developed; ideas may be listed.) Explores some facets of the topic.\\\\n</option><option points='3'>\\\\nIncludes in-depth information and exceptional supporting details that are fully developed. Explores all facets of the topic.\\\\n</option></category><category><description>\\\\nOrganization\\\\n</description><score>2</score><option points='0'>\\\\nIdeas organized illogically, transitions weak, and response difficult to follow.\\\\n</option><option points='1'>\\\\nAttempts to logically organize ideas. Attempts to progress in an order that enhances meaning, and demonstrates use of transitions.\\\\n</option><option points='2'>\\\\nIdeas organized logically. Progresses in an order that enhances meaning. Includes smooth transitions.\\\\n</option></category><category><description>\\\\nStyle\\\\n</description><score>2</score><option points='0'>\\\\nContains limited vocabulary, with many words used incorrectly. Demonstrates problems with sentence patterns.\\\\n</option><option points='1'>\\\\nContains basic vocabulary, with words that are predictable and common. Contains mostly simple sentences (although there may be an attempt at more varied sentence patterns).\\\\n</option><option points='2'>\\\\nIncludes vocabulary to make explanations detailed and precise. Includes varied sentence patterns, including complex sentences.\\\\n</option></category><category><description>\\\\nVoice\\\\n</description><score>2</score><option points='0'>\\\\nDemonstrates language and tone that may be inappropriate to task and reader.\\\\n</option><option points='1'>\\\\nDemonstrates an attempt to adjust language and tone to task and reader.\\\\n</option><option points='2'>\\\\nDemonstrates effective adjustment of language and tone to task and reader.\\\\n</option></category></rubric>\\\"}\", \"score\": 12}], \"max_score\": 12, \"child_state\": \"post_assessment\"}"]103# Mock instance state. Should receive a score of 15.104MOCK_INSTANCE_STATE = r"""{"ready_to_reset": false, "skip_spelling_checks": true, "current_task_number": 1, "weight": 5.0, "graceperiod": "1 day 12 hours 59 minutes 59 seconds", "graded": "True", "task_states": ["{\"child_created\": false, \"child_attempts\": 4, \"version\": 1, \"child_history\": [{\"answer\": \"After 24 hours, remove the samples from the containers and rinse each sample with distilled water.\\r\\nAllow the samples to sit and dry for 30 minutes.\\r\\nDetermine the mass of each sample.\\r\\nThe students\\u2019 data are recorded in the table below.\\r\\n\\r\\nStarting Mass (g)\\tEnding Mass (g)\\tDifference in Mass (g)\\r\\nMarble\\t 9.8\\t 9.4\\t\\u20130.4\\r\\nLimestone\\t10.4\\t 9.1\\t\\u20131.3\\r\\nWood\\t11.2\\t11.2\\t 0.0\\r\\nPlastic\\t 7.2\\t 7.1\\t\\u20130.1\\r\\nAfter reading the\", \"post_assessment\": \"[3]\", \"score\": 3}, {\"answer\": \"To replicate the experiment, the procedure would require more detail. One piece of information that is omitted is the amount of vinegar used in the experiment. It is also important to know what temperature the experiment was kept at during the 24 hours. Finally, the procedure needs to include details about the experiment, for example if the whole sample must be submerged.\", \"post_assessment\": \"[3]\", \"score\": 3}, {\"answer\": \"e the mass of four different samples.\\r\\nPour vinegar in each of four separate, but identical, containers.\\r\\nPlace a sample of one material into one container and label. Repeat with remaining samples, placing a single sample into a single container.\\r\\nAfter 24 hours, remove the samples from the containers and rinse each sample with distilled water.\\r\\nAllow the samples to sit and dry for 30 minutes.\\r\\nDetermine the mass of each sample.\\r\\nThe students\\u2019 data are recorded in the table below.\\r\\n\", \"post_assessment\": \"[3]\", \"score\": 3}, {\"answer\": \"\", \"post_assessment\": \"[3]\", \"score\": 3}], \"max_score\": 3, \"child_state\": \"done\"}", "{\"child_created\": false, \"child_attempts\": 0, \"version\": 1, \"child_history\": [{\"answer\": \"The students\\u2019 data are recorded in the table below.\\r\\n\\r\\nStarting Mass (g)\\tEnding Mass (g)\\tDifference in Mass (g)\\r\\nMarble\\t 9.8\\t 9.4\\t\\u20130.4\\r\\nLimestone\\t10.4\\t 9.1\\t\\u20131.3\\r\\nWood\\t11.2\\t11.2\\t 0.0\\r\\nPlastic\\t 7.2\\t 7.1\\t\\u20130.1\\r\\nAfter reading the group\\u2019s procedure, describe what additional information you would need in order to replicate the expe\", \"post_assessment\": \"{\\\"submission_id\\\": 3097, \\\"score\\\": 0, \\\"feedback\\\": \\\"{\\\\\\\"spelling\\\\\\\": \\\\\\\"Spelling: Ok.\\\\\\\", \\\\\\\"grammar\\\\\\\": \\\\\\\"Grammar: More grammar errors than average.\\\\\\\", \\\\\\\"markup-text\\\\\\\": \\\\\\\"the students data are recorded in the <bg>table below . starting mass</bg> g ending mass g difference in mass g marble . . . limestone . . . wood . . . plastic . . . after reading the groups <bg>procedure , describe what additional</bg> information you would need in order to replicate the <bs>expe</bs>\\\\\\\"}\\\", \\\"success\\\": true, \\\"grader_id\\\": 3233, \\\"grader_type\\\": \\\"ML\\\", \\\"rubric_scores_complete\\\": true, \\\"rubric_xml\\\": \\\"<rubric><category><description>Response Quality</description><score>0</score><option points='0'>The response is not a satisfactory answer to the question. It either fails to address the question or does so in a limited way, with no evidence of higher-order thinking.</option><option points='1'>The response is a marginal answer to the question. It may contain some elements of a proficient response, but it is inaccurate or incomplete.</option><option points='2'>The response is a proficient answer to the question. It is generally correct, although it may contain minor inaccuracies. There is limited evidence of higher-order thinking.</option><option points='3'>The response is correct, complete, and contains evidence of higher-order thinking.</option></category></rubric>\\\"}\", \"score\": 0}, {\"answer\": \"After 24 hours, remove the samples from the containers and rinse each sample with distilled water.\\r\\nAllow the samples to sit and dry for 30 minutes.\\r\\nDetermine the mass of each sample.\\r\\nThe students\\u2019 data are recorded in the table below.\\r\\n\\r\\nStarting Mass (g)\\tEnding Mass (g)\\tDifference in Mass (g)\\r\\nMarble\\t 9.8\\t 9.4\\t\\u20130.4\\r\\nLimestone\\t10.4\\t 9.1\\t\\u20131.3\\r\\nWood\\t11.2\\t11.2\\t 0.0\\r\\nPlastic\\t 7.2\\t 7.1\\t\\u20130.1\\r\\nAfter reading the\", \"post_assessment\": \"{\\\"submission_id\\\": 3098, \\\"score\\\": 0, \\\"feedback\\\": \\\"{\\\\\\\"spelling\\\\\\\": \\\\\\\"Spelling: Ok.\\\\\\\", \\\\\\\"grammar\\\\\\\": \\\\\\\"Grammar: Ok.\\\\\\\", \\\\\\\"markup-text\\\\\\\": \\\\\\\"after hours , remove the samples from the containers and rinse each sample with distilled water . allow the samples to sit and dry for minutes . determine the mass of each sample . the students data are recorded in the <bg>table below . starting mass</bg> g ending mass g difference in mass g marble . . . limestone . . . wood . . . plastic . . . after reading the\\\\\\\"}\\\", \\\"success\\\": true, \\\"grader_id\\\": 3235, \\\"grader_type\\\": \\\"ML\\\", \\\"rubric_scores_complete\\\": true, \\\"rubric_xml\\\": \\\"<rubric><category><description>Response Quality</description><score>0</score><option points='0'>The response is not a satisfactory answer to the question. It either fails to address the question or does so in a limited way, with no evidence of higher-order thinking.</option><option points='1'>The response is a marginal answer to the question. It may contain some elements of a proficient response, but it is inaccurate or incomplete.</option><option points='2'>The response is a proficient answer to the question. It is generally correct, although it may contain minor inaccuracies. There is limited evidence of higher-order thinking.</option><option points='3'>The response is correct, complete, and contains evidence of higher-order thinking.</option></category></rubric>\\\"}\", \"score\": 0}, {\"answer\": \"To replicate the experiment, the procedure would require more detail. One piece of information that is omitted is the amount of vinegar used in the experiment. It is also important to know what temperature the experiment was kept at during the 24 hours. Finally, the procedure needs to include details about the experiment, for example if the whole sample must be submerged.\", \"post_assessment\": \"{\\\"submission_id\\\": 3099, \\\"score\\\": 3, \\\"feedback\\\": \\\"{\\\\\\\"spelling\\\\\\\": \\\\\\\"Spelling: Ok.\\\\\\\", \\\\\\\"grammar\\\\\\\": \\\\\\\"Grammar: Ok.\\\\\\\", \\\\\\\"markup-text\\\\\\\": \\\\\\\"to replicate the experiment , the procedure would require <bg>more detail . one</bg> piece of information <bg>that is omitted is the</bg> amount of vinegar used in the experiment . it is also important to know what temperature the experiment was kept at during the hours . finally , the procedure needs to include details about the experiment , for example if the whole sample must be submerged .\\\\\\\"}\\\", \\\"success\\\": true, \\\"grader_id\\\": 3237, \\\"grader_type\\\": \\\"ML\\\", \\\"rubric_scores_complete\\\": true, \\\"rubric_xml\\\": \\\"<rubric><category><description>Response Quality</description><score>3</score><option points='0'>The response is not a satisfactory answer to the question. It either fails to address the question or does so in a limited way, with no evidence of higher-order thinking.</option><option points='1'>The response is a marginal answer to the question. It may contain some elements of a proficient response, but it is inaccurate or incomplete.</option><option points='2'>The response is a proficient answer to the question. It is generally correct, although it may contain minor inaccuracies. There is limited evidence of higher-order thinking.</option><option points='3'>The response is correct, complete, and contains evidence of higher-order thinking.</option></category></rubric>\\\"}\", \"score\": 3}, {\"answer\": \"e the mass of four different samples.\\r\\nPour vinegar in each of four separate, but identical, containers.\\r\\nPlace a sample of one material into one container and label. Repeat with remaining samples, placing a single sample into a single container.\\r\\nAfter 24 hours, remove the samples from the containers and rinse each sample with distilled water.\\r\\nAllow the samples to sit and dry for 30 minutes.\\r\\nDetermine the mass of each sample.\\r\\nThe students\\u2019 data are recorded in the table below.\\r\\n\", \"post_assessment\": \"{\\\"submission_id\\\": 3100, \\\"score\\\": 0, \\\"feedback\\\": \\\"{\\\\\\\"spelling\\\\\\\": \\\\\\\"Spelling: Ok.\\\\\\\", \\\\\\\"grammar\\\\\\\": \\\\\\\"Grammar: Ok.\\\\\\\", \\\\\\\"markup-text\\\\\\\": \\\\\\\"e the mass of four different samples . pour vinegar in <bg>each of four separate</bg> , but identical , containers . place a sample of one material into one container and label . repeat with remaining samples , placing a single sample into a single container . after hours , remove the samples from the containers and rinse each sample with distilled water . allow the samples to sit and dry for minutes . determine the mass of each sample . the students data are recorded in the table below . \\\\\\\"}\\\", \\\"success\\\": true, \\\"grader_id\\\": 3239, \\\"grader_type\\\": \\\"ML\\\", \\\"rubric_scores_complete\\\": true, \\\"rubric_xml\\\": \\\"<rubric><category><description>Response Quality</description><score>0</score><option points='0'>The response is not a satisfactory answer to the question. It either fails to address the question or does so in a limited way, with no evidence of higher-order thinking.</option><option points='1'>The response is a marginal answer to the question. It may contain some elements of a proficient response, but it is inaccurate or incomplete.</option><option points='2'>The response is a proficient answer to the question. It is generally correct, although it may contain minor inaccuracies. There is limited evidence of higher-order thinking.</option><option points='3'>The response is correct, complete, and contains evidence of higher-order thinking.</option></category></rubric>\\\"}\", \"score\": 0}, {\"answer\": \"\", \"post_assessment\": \"{\\\"submission_id\\\": 3101, \\\"score\\\": 0, \\\"feedback\\\": \\\"{\\\\\\\"spelling\\\\\\\": \\\\\\\"Spelling: Ok.\\\\\\\", \\\\\\\"grammar\\\\\\\": \\\\\\\"Grammar: Ok.\\\\\\\", \\\\\\\"markup-text\\\\\\\": \\\\\\\"invalid essay .\\\\\\\"}\\\", \\\"success\\\": true, \\\"grader_id\\\": 3241, \\\"grader_type\\\": \\\"ML\\\", \\\"rubric_scores_complete\\\": true, \\\"rubric_xml\\\": \\\"<rubric><category><description>Response Quality</description><score>0</score><option points='0'>The response is not a satisfactory answer to the question. It either fails to address the question or does so in a limited way, with no evidence of higher-order thinking.</option><option points='1'>The response is a marginal answer to the question. It may contain some elements of a proficient response, but it is inaccurate or incomplete.</option><option points='2'>The response is a proficient answer to the question. It is generally correct, although it may contain minor inaccuracies. There is limited evidence of higher-order thinking.</option><option points='3'>The response is correct, complete, and contains evidence of higher-order thinking.</option></category></rubric>\\\"}\", \"score\": 0}], \"max_score\": 3, \"child_state\": \"done\"}"], "attempts": "10000", "student_attempts": 0, "due": null, "state": "done", "accept_file_upload": false, "display_name": "Science Question -- Machine Assessed"}"""105# Instance state. To test the rubric scores are consistent. Should receive a score of 15.106INSTANCE_INCONSISTENT_STATE = serialize_open_ended_instance_state("""107{ "accept_file_upload" : false,108 "attempts" : "10000",109 "current_task_number" : 1,110 "display_name" : "Science Question -- Machine Assessed",111 "due" : null,112 "graceperiod" : "1 day 12 hours 59 minutes 59 seconds",113 "graded" : "True",114 "ready_to_reset" : false,115 "skip_spelling_checks" : true,116 "state" : "done",117 "student_attempts" : 0,118 "task_states" : [ { "child_attempts" : 4,119 "child_created" : false,120 "child_history" : [ { "answer" : "Student answer 1st attempt.",121 "post_assessment" : [ 3 ],122 "score" : 1123 },124 { "answer" : "Student answer 2nd attempt.",125 "post_assessment" : [ 3 ],126 "score" : 1127 },128 { "answer" : "Student answer 3rd attempt.",129 "post_assessment" : [ 3 ],130 "score" : 1131 },132 { "answer" : "",133 "post_assessment" : [ 3 ],134 "score" : 1135 }136 ],137 "child_state" : "done",138 "max_score" : 3,139 "version" : 1140 },141 { "child_attempts" : 0,142 "child_created" : false,143 "child_history" : [ { "answer" : "Student answer 1st attempt.",144 "post_assessment" : { "feedback" : { "grammar" : "Grammar: More grammar errors than average.",145 "markup-text" : "valid essay",146 "spelling" : "Spelling: Ok."147 },148 "grader_id" : 3233,149 "grader_type" : "ML",150 "rubric_scores_complete" : true,151 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",152 "score" : 0,153 "submission_id" : 3097,154 "success" : true155 },156 "score" : 0157 },158 { "answer" : "Student answer 2nd attempt.",159 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",160 "markup-text" : "valid essay",161 "spelling" : "Spelling: Ok."162 },163 "grader_id" : 3235,164 "grader_type" : "ML",165 "rubric_scores_complete" : true,166 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",167 "score" : 0,168 "submission_id" : 3098,169 "success" : true170 },171 "score" : 0172 },173 { "answer" : "Student answer 3rd attempt.",174 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",175 "markup-text" : "valid essay",176 "spelling" : "Spelling: Ok."177 },178 "grader_id" : 3237,179 "grader_type" : "ML",180 "rubric_scores_complete" : true,181 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>3</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",182 "score" : 2,183 "submission_id" : 3099,184 "success" : true185 },186 "score" : 2187 },188 { "answer" : "Student answer 4th attempt.",189 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",190 "markup-text" : "valid essay",191 "spelling" : "Spelling: Ok."192 },193 "grader_id" : 3239,194 "grader_type" : "ML",195 "rubric_scores_complete" : true,196 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",197 "score" : 0,198 "submission_id" : 3100,199 "success" : true200 },201 "score" : 0202 },203 { "answer" : "",204 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",205 "markup-text" : "invalid essay .",206 "spelling" : "Spelling: Ok."207 },208 "grader_id" : 3241,209 "grader_type" : "ML",210 "rubric_scores_complete" : true,211 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",212 "score" : 0,213 "submission_id" : 3101,214 "success" : true215 },216 "score" : 0217 }218 ],219 "child_state" : "done",220 "max_score" : 3,221 "version" : 1222 }223 ],224 "weight" : 5.0225}226 """)227# Instance state. Should receive a score of 10 if grader type is PE.228INSTANCE_INCONSISTENT_STATE2 = serialize_open_ended_instance_state("""229{ "accept_file_upload" : false,230 "attempts" : "10000",231 "current_task_number" : 1,232 "display_name" : "Science Question -- Machine Assessed",233 "due" : null,234 "graceperiod" : "1 day 12 hours 59 minutes 59 seconds",235 "graded" : "True",236 "ready_to_reset" : false,237 "skip_spelling_checks" : true,238 "state" : "done",239 "student_attempts" : 0,240 "task_states" : [ { "child_attempts" : 4,241 "child_created" : false,242 "child_history" : [ { "answer" : "Student answer 1st attempt.",243 "post_assessment" : [3],244 "score" : 1245 },246 { "answer" : "Student answer 2nd attempt.",247 "post_assessment" : [3],248 "score" : 1249 },250 { "answer" : "Student answer 3rd attempt.",251 "post_assessment" : [3],252 "score" : 1253 },254 { "answer" : "",255 "post_assessment" : [3],256 "score" : 1257 }258 ],259 "child_state" : "done",260 "max_score" : 3,261 "version" : 1262 },263 { "child_attempts" : 0,264 "child_created" : false,265 "child_history" : [ { "answer" : "Student answer 1st attempt.",266 "post_assessment" : { "feedback" : { "grammar" : "Grammar: More grammar errors than average.",267 "markup-text" : "valid essay",268 "spelling" : "Spelling: Ok."269 },270 "grader_id" : 3233,271 "grader_type" : "PE",272 "rubric_scores_complete" : true,273 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",274 "score" : 0,275 "submission_id" : 3097,276 "success" : true277 },278 "score" : 0279 },280 { "answer" : "Student answer 2nd attempt.",281 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",282 "markup-text" : "valid essay",283 "spelling" : "Spelling: Ok."284 },285 "grader_id" : 3235,286 "grader_type" : "PE",287 "rubric_scores_complete" : true,288 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",289 "score" : 0,290 "submission_id" : 3098,291 "success" : true292 },293 "score" : 0294 },295 { "answer" : "Student answer 3rd attempt.",296 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",297 "markup-text" : "valid essay",298 "spelling" : "Spelling: Ok."299 },300 "grader_id" : 3237,301 "grader_type" : "PE",302 "rubric_scores_complete" : true,303 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>5</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",304 "score" : 2,305 "submission_id" : 3099,306 "success" : true307 },308 "score" : 2309 },310 { "answer" : "Student answer 4th attempt.",311 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",312 "markup-text" : "valid essay",313 "spelling" : "Spelling: Ok."314 },315 "grader_id" : 3239,316 "grader_type" : "PE",317 "rubric_scores_complete" : true,318 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",319 "score" : 0,320 "submission_id" : 3100,321 "success" : true322 },323 "score" : 0324 },325 { "answer" : "",326 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",327 "markup-text" : "invalid essay .",328 "spelling" : "Spelling: Ok."329 },330 "grader_id" : 3241,331 "grader_type" : "PE",332 "rubric_scores_complete" : true,333 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",334 "score" : 0,335 "submission_id" : 3101,336 "success" : true337 },338 "score" : 0339 }340 ],341 "child_state" : "done",342 "max_score" : 3,343 "version" : 1344 }345 ],346 "weight" : 5.0347}348 """)349# Instance state. To test score if sum of rubric score is different from score value. Should receive score of 25.350INSTANCE_INCONSISTENT_STATE3 = serialize_open_ended_instance_state("""351{ "accept_file_upload" : false,352 "attempts" : "10000",353 "current_task_number" : 1,354 "display_name" : "Science Question -- Machine Assessed",355 "due" : null,356 "graceperiod" : "1 day 12 hours 59 minutes 59 seconds",357 "graded" : "True",358 "ready_to_reset" : false,359 "skip_spelling_checks" : true,360 "state" : "done",361 "student_attempts" : 0,362 "task_states" : [ { "child_attempts" : 4,363 "child_created" : false,364 "child_history" : [ { "answer" : "Student answer 1st attempt.",365 "post_assessment" : [3],366 "score" : 1367 },368 { "answer" : "Student answer 2nd attempt.",369 "post_assessment" : [3],370 "score" : 1371 },372 { "answer" : "Student answer 3rd attempt.",373 "post_assessment" : [3],374 "score" : 1375 },376 { "answer" : "",377 "post_assessment" : [3],378 "score" : 1379 }380 ],381 "child_state" : "done",382 "max_score" : 3,383 "version" : 1384 },385 { "child_attempts" : 0,386 "child_created" : false,387 "child_history" : [ { "answer" : "Student answer 1st attempt.",388 "post_assessment" : { "feedback" : { "grammar" : "Grammar: More grammar errors than average.",389 "markup-text" : "valid essay",390 "spelling" : "Spelling: Ok."391 },392 "grader_id" : 3233,393 "grader_type" : "ML",394 "rubric_scores_complete" : true,395 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>2</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",396 "score" : 0,397 "submission_id" : 3097,398 "success" : true399 },400 "score" : 0401 },402 { "answer" : "Student answer 2nd attempt.",403 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",404 "markup-text" : "valid essay",405 "spelling" : "Spelling: Ok."406 },407 "grader_id" : 3235,408 "grader_type" : "ML",409 "rubric_scores_complete" : true,410 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",411 "score" : 0,412 "submission_id" : 3098,413 "success" : true414 },415 "score" : 0416 },417 { "answer" : "Student answer 3rd attempt.",418 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",419 "markup-text" : "valid essay",420 "spelling" : "Spelling: Ok."421 },422 "grader_id" : 3237,423 "grader_type" : "ML",424 "rubric_scores_complete" : true,425 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>5</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",426 "score" : 2,427 "submission_id" : 3099,428 "success" : true429 },430 "score" : 2431 },432 { "answer" : "Student answer 4th attempt.",433 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",434 "markup-text" : "valid essay",435 "spelling" : "Spelling: Ok."436 },437 "grader_id" : 3239,438 "grader_type" : "ML",439 "rubric_scores_complete" : true,440 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",441 "score" : 0,442 "submission_id" : 3100,443 "success" : true444 },445 "score" : 0446 },447 { "answer" : "",448 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",449 "markup-text" : "invalid essay .",450 "spelling" : "Spelling: Ok."451 },452 "grader_id" : 3241,453 "grader_type" : "ML",454 "rubric_scores_complete" : true,455 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",456 "score" : 0,457 "submission_id" : 3101,458 "success" : true459 },460 "score" : 0461 }462 ],463 "child_state" : "done",464 "max_score" : 3,465 "version" : 1466 }467 ],468 "weight" : 5.0469}470""")471# Instance state. To test score if old task states are available. Should receive a score of 15.472INSTANCE_INCONSISTENT_STATE4 = serialize_open_ended_instance_state("""473{ "accept_file_upload" : false,474 "attempts" : "10000",475 "current_task_number" : 0,476 "display_name" : "Science Question -- Machine Assessed",477 "due" : null,478 "graceperiod" : "1 day 12 hours 59 minutes 59 seconds",479 "graded" : "True",480 "old_task_states" : [ [ { "child_attempts" : 4,481 "child_created" : false,482 "child_history" : [ { "answer" : "Student answer 1st attempt.",483 "post_assessment" : "[3]",484 "score" : 1485 },486 { "answer" : "Student answer 2nd attempt.",487 "post_assessment" : "[3]",488 "score" : 1489 },490 { "answer" : "Student answer 3rd attempt.",491 "post_assesssment" : "[3]",492 "score" : 1493 },494 { "answer" : "",495 "post_assessment" : "[3]",496 "score" : 1497 }498 ],499 "child_state" : "done",500 "max_score" : 3,501 "version" : 1502 } ] ],503 "ready_to_reset" : false,504 "skip_spelling_checks" : true,505 "state" : "assessing",506 "student_attempts" : 0,507 "task_states" : [ { "child_attempts" : 4,508 "child_created" : false,509 "child_history" : [ { "answer" : "Student answer 1st attempt.",510 "post_assessment" : [3],511 "score" : 1512 },513 { "answer" : "Student answer 2nd attempt.",514 "post_assessment" : [3],515 "score" : 1516 },517 { "answer" : "Student answer 3rd attempt.",518 "post_assessment" : [3],519 "score" : 1520 },521 { "answer" : "",522 "post_assessment" : [3],523 "score" : 1524 }525 ],526 "child_state" : "done",527 "max_score" : 3,528 "stored_answer" : null,529 "version" : 1530 },531 { "child_attempts" : 0,532 "child_created" : false,533 "child_history" : [ { "answer" : "Student answer 1st attempt.",534 "post_assessment" : { "feedback" : { "grammar" : "Grammar: More grammar errors than average.",535 "markup-text" : "valid essay",536 "spelling" : "Spelling: Ok."537 },538 "grader_id" : 3233,539 "grader_type" : "ML",540 "rubric_scores_complete" : true,541 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",542 "score" : 0,543 "submission_id" : 3097,544 "success" : true545 },546 "score" : 0547 },548 { "answer" : "Student answer 2nd attempt.",549 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",550 "markup-text" : "valid essay",551 "spelling" : "Spelling: Ok."552 },553 "grader_id" : 3235,554 "grader_type" : "ML",555 "rubric_scores_complete" : true,556 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",557 "score" : 0,558 "submission_id" : 3098,559 "success" : true560 },561 "score" : 0562 },563 { "answer" : "Student answer 3rd attempt.",564 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",565 "markup-text" : "valid essay",566 "spelling" : "Spelling: Ok."567 },568 "grader_id" : 3237,569 "grader_type" : "ML",570 "rubric_scores_complete" : true,571 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>3</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",572 "score" : 2,573 "submission_id" : 3099,574 "success" : true575 },576 "score" : 2577 },578 { "answer" : "Student answer 4th attempt.",579 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",580 "markup-text" : "valid essay",581 "spelling" : "Spelling: Ok."582 },583 "grader_id" : 3239,584 "grader_type" : "ML",585 "rubric_scores_complete" : true,586 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",587 "score" : 0,588 "submission_id" : 3100,589 "success" : true590 },591 "score" : 0592 },593 { "answer" : "",594 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",595 "markup-text" : "invalid essay .",596 "spelling" : "Spelling: Ok."597 },598 "grader_id" : 3241,599 "grader_type" : "ML",600 "rubric_scores_complete" : true,601 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",602 "score" : 0,603 "submission_id" : 3101,604 "success" : true605 },606 "score" : 0607 }608 ],609 "child_state" : "done",610 "max_score" : 3,611 "version" : 1612 }613 ],614 "weight" : 5.0615}616""")617# Instance state. To test score if rubric scores are available but score is missing. Should receive a score of 15.618INSTANCE_INCONSISTENT_STATE5 = serialize_open_ended_instance_state("""619{ "accept_file_upload" : false,620 "attempts" : "10000",621 "current_task_number" : 1,622 "display_name" : "Science Question -- Machine Assessed",623 "due" : null,624 "graceperiod" : "1 day 12 hours 59 minutes 59 seconds",625 "graded" : "True",626 "ready_to_reset" : false,627 "skip_spelling_checks" : true,628 "state" : "done",629 "student_attempts" : 0,630 "task_states" : [ { "child_attempts" : 4,631 "child_created" : false,632 "child_history" : [ { "answer" : "Student answer 1st attempt.",633 "post_assessment" : [3],634 "score" : 1635 },636 { "answer" : "Student answer 2nd attempt.",637 "post_assessment" : [3],638 "score" : 1639 },640 { "answer" : "Student answer 3rd attempt.",641 "post_assessment" : [3],642 "score" : 1643 },644 { "answer" : "",645 "post_assessment" : [3],646 "score" : 1647 }648 ],649 "child_state" : "done",650 "max_score" : 3,651 "version" : 1652 },653 { "child_attempts" : 0,654 "child_created" : false,655 "child_history" : [ { "answer" : "Student answer 1st attempt.",656 "post_assessment" : { "feedback" : { "grammar" : "Grammar: More grammar errors than average.",657 "markup-text" : "valid essay",658 "spelling" : "Spelling: Ok."659 },660 "grader_id" : 3233,661 "grader_type" : "ML",662 "rubric_scores_complete" : true,663 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",664 "score" : 0,665 "submission_id" : 3097,666 "success" : true667 },668 "score" : 0669 },670 { "answer" : "Student answer 2nd attempt.",671 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",672 "markup-text" : "valid essay",673 "spelling" : "Spelling: Ok."674 },675 "grader_id" : 3235,676 "grader_type" : "ML",677 "rubric_scores_complete" : true,678 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",679 "score" : 0,680 "submission_id" : 3098,681 "success" : true682 },683 "score" : 0684 },685 { "answer" : "Student answer 3rd attempt.",686 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",687 "markup-text" : "valid essay",688 "spelling" : "Spelling: Ok."689 },690 "grader_id" : 3237,691 "grader_type" : "ML",692 "rubric_scores_complete" : true,693 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>3</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",694 "score" : 2,695 "submission_id" : 3099,696 "success" : true697 }698 },699 { "answer" : "Student answer 4th attempt.",700 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",701 "markup-text" : "valid essay",702 "spelling" : "Spelling: Ok."703 },704 "grader_id" : 3239,705 "grader_type" : "ML",706 "rubric_scores_complete" : true,707 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",708 "score" : 0,709 "submission_id" : 3100,710 "success" : true711 },712 "score" : 0713 },714 { "answer" : "",715 "post_assessment" : { "feedback" : { "grammar" : "Grammar: Ok.",716 "markup-text" : "invalid essay .",717 "spelling" : "Spelling: Ok."718 },719 "grader_id" : 3241,720 "grader_type" : "ML",721 "rubric_scores_complete" : true,722 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>0</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",723 "score" : 0,724 "submission_id" : 3101,725 "success" : true726 },727 "score" : 0728 }729 ],730 "child_state" : "done",731 "max_score" : 3,732 "version" : 1733 }734 ],735 "weight" : 5.0736}737""")738# State Initial739STATE_INITIAL = serialize_open_ended_instance_state("""740{741 "ready_to_reset": false,742 "skip_spelling_checks": false,743 "current_task_number": 0,744 "old_task_states": [],745 "weight": 1,746 "task_states": [747 {748 "child_attempts" : 1,749 "child_created" : false,750 "child_history" : [],751 "child_state" : "done",752 "max_score" : 3,753 "version" : 1754 },755 {756 "child_created": false,757 "child_attempts": 0,758 "stored_answer": "A stored answer.",759 "version": 1,760 "child_history": [],761 "max_score": 3,762 "child_state": "initial"763 }764 ],765 "graded": true,766 "student_attempts": 0,767 "required_peer_grading": 3,768 "state": "initial",769 "accept_file_upload": false,770 "min_to_calibrate": 3,771 "max_to_calibrate": 6,772 "display_name": "Open Response Assessment",773 "peer_grader_count": 3,774 "max_attempts": 1775}""")776STATE_ACCESSING = serialize_open_ended_instance_state("""777{778 "ready_to_reset": false,779 "skip_spelling_checks": false,780 "current_task_number": 0,781 "old_task_states": [],782 "weight": 1,783 "task_states": [784 {785 "child_attempts" : 1,786 "child_created" : false,787 "child_history": [788 {789 "answer": "Here is an answer."790 }791 ],792 "child_state" : "done",793 "max_score" : 3,794 "version" : 1795 },796 {797 "child_created": false,798 "child_attempts": 0,799 "stored_answer": null,800 "version": 1,801 "child_history": [802 {803 "answer": "Here is an answer."804 }805 ],806 "max_score": 3,807 "child_state": "assessing"808 }809 ],810 "graded": true,811 "student_attempts": 0,812 "required_peer_grading": 3,813 "state": "assessing",814 "accept_file_upload": false,815 "min_to_calibrate": 3,816 "max_to_calibrate": 6,817 "display_name": "Open Response Assessment",818 "peer_grader_count": 3,819 "max_attempts": 1820}""")821STATE_POST_ASSESSMENT = serialize_open_ended_instance_state("""822{823 "ready_to_reset": false,824 "skip_spelling_checks": false,825 "current_task_number": 0,826 "old_task_states": [],827 "weight": 1,828 "task_states": [829 {830 "child_attempts" : 1,831 "child_created" : false,832 "child_history": [833 {834 "answer": "Here is an answer."835 }836 ],837 "child_state" : "done",838 "max_score" : 3,839 "version" : 1840 },841 {842 "child_created": false,843 "child_attempts": 0,844 "stored_answer": null,845 "version": 1,846 "child_history": [847 {848 "answer": "Here is an answer."849 }850 ],851 "max_score": 3,852 "post_assessment": {853 "feedback" : {854 "grammar" : "Grammar: Ok.",855 "markup-text" : "valid essay",856 "spelling" : "Spelling: Ok."857 },858 "grader_id" : 3237,859 "grader_type" : "ML",860 "rubric_scores_complete" : true,861 "rubric_xml" : "<rubric><category><description>Response Quality</description><score>3</score><option points='0'>Category one description.</option><option points='1'>Category two description.</option><option points='2'>Category three description.</option><option points='3'>Category four description.</option></category></rubric>",862 "score" : 2,863 "submission_id" : 3099,864 "success" : true865 },866 "child_state": "post_assessment"867 }868 ],869 "graded": true,870 "student_attempts": 0,871 "required_peer_grading": 3,872 "state": "done",873 "accept_file_upload": false,874 "min_to_calibrate": 3,875 "max_to_calibrate": 6,876 "display_name": "Open Response Assessment",877 "peer_grader_count": 3,878 "max_attempts": 1879}""")880# Task state with self assessment only.881TEST_STATE_SA = ["{\"child_created\": false, \"child_attempts\": 1, \"version\": 1, \"child_history\": [{\"answer\": \"Censorship in the Libraries\\r<br>'All of us can think of a book that we hope none of our children or any other children have taken off the shelf. But if I have the right to remove that book from the shelf -- that work I abhor -- then you also have exactly the same right and so does everyone else. And then we have no books left on the shelf for any of us.' --Katherine Paterson, Author\\r<br><br>Write a persuasive essay to a newspaper reflecting your views on censorship in libraries. Do you believe that certain materials, such as books, music, movies, magazines, etc., should be removed from the shelves if they are found offensive? Support your position with convincing arguments from your own experience, observations, and/or reading.\", \"post_assessment\": \"[3, 3, 2, 2, 2]\", \"score\": 12}], \"max_score\": 12, \"child_state\": \"done\"}", "{\"child_created\": false, \"child_attempts\": 0, \"version\": 1, \"child_history\": [{\"answer\": \"Censorship in the Libraries\\r<br>'All of us can think of a book that we hope none of our children or any other children have taken off the shelf. But if I have the right to remove that book from the shelf -- that work I abhor -- then you also have exactly the same right and so does everyone else. And then we have no books left on the shelf for any of us.' --Katherine Paterson, Author\\r<br><br>Write a persuasive essay to a newspaper reflecting your views on censorship in libraries. Do you believe that certain materials, such as books, music, movies, magazines, etc., should be removed from the shelves if they are found offensive? Support your position with convincing arguments from your own experience, observations, and/or reading.\", \"post_assessment\": \"{\\\"submission_id\\\": 1461, \\\"score\\\": 12, \\\"feedback\\\": \\\"{\\\\\\\"feedback\\\\\\\": \\\\\\\"\\\\\\\"}\\\", \\\"success\\\": true, \\\"grader_id\\\": 5414, \\\"grader_type\\\": \\\"IN\\\", \\\"rubric_scores_complete\\\": true, \\\"rubric_xml\\\": \\\"<rubric><category><description>\\\\nIdeas\\\\n</description><score>3</score><option points='0'>\\\\nDifficult for the reader to discern the main idea. Too brief or too repetitive to establish or maintain a focus.\\\\n</option><option points='1'>\\\\nAttempts a main idea. Sometimes loses focus or ineffectively displays focus.\\\\n</option><option points='2'>\\\\nPresents a unifying theme or main idea, but may include minor tangents. Stays somewhat focused on topic and task.\\\\n</option><option points='3'>\\\\nPresents a unifying theme or main idea without going off on tangents. Stays completely focused on topic and task.\\\\n</option></category><category><description>\\\\nContent\\\\n</description><score>3</score><option points='0'>\\\\nIncludes little information with few or no details or unrelated details. Unsuccessful in attempts to explore any facets of the topic.\\\\n</option><option points='1'>\\\\nIncludes little information and few or no details. Explores only one or two facets of the topic.\\\\n</option><option points='2'>\\\\nIncludes sufficient information and supporting details. (Details may not be fully developed; ideas may be listed.) Explores some facets of the topic.\\\\n</option><option points='3'>\\\\nIncludes in-depth information and exceptional supporting details that are fully developed. Explores all facets of the topic.\\\\n</option></category><category><description>\\\\nOrganization\\\\n</description><score>2</score><option points='0'>\\\\nIdeas organized illogically, transitions weak, and response difficult to follow.\\\\n</option><option points='1'>\\\\nAttempts to logically organize ideas. Attempts to progress in an order that enhances meaning, and demonstrates use of transitions.\\\\n</option><option points='2'>\\\\nIdeas organized logically. Progresses in an order that enhances meaning. Includes smooth transitions.\\\\n</option></category><category><description>\\\\nStyle\\\\n</description><score>2</score><option points='0'>\\\\nContains limited vocabulary, with many words used incorrectly. Demonstrates problems with sentence patterns.\\\\n</option><option points='1'>\\\\nContains basic vocabulary, with words that are predictable and common. Contains mostly simple sentences (although there may be an attempt at more varied sentence patterns).\\\\n</option><option points='2'>\\\\nIncludes vocabulary to make explanations detailed and precise. Includes varied sentence patterns, including complex sentences.\\\\n</option></category><category><description>\\\\nVoice\\\\n</description><score>2</score><option points='0'>\\\\nDemonstrates language and tone that may be inappropriate to task and reader.\\\\n</option><option points='1'>\\\\nDemonstrates an attempt to adjust language and tone to task and reader.\\\\n</option><option points='2'>\\\\nDemonstrates effective adjustment of language and tone to task and reader.\\\\n</option></category></rubric>\\\"}\", \"score\": 12}], \"max_score\": 12, \"child_state\": \"post_assessment\"}"]882# Task state with self and then ai assessment.883TEST_STATE_AI = ["{\"child_created\": false, \"child_attempts\": 2, \"version\": 1, \"child_history\": [{\"answer\": \"In libraries, there should not be censorship on materials considering that it's an individual's decision to read what they prefer. There is no appropriate standard on what makes a book offensive to a group, so it should be undetermined as to what makes a book offensive. In a public library, many children, who the books are censored for, are with their parents. Parents should make an independent choice on what they can allow their children to read. Letting society ban a book simply for the use of inappropriate materials is ridiculous. If an author spent time creating a story, it should be appreciated, and should not put on a list of no-nos. If a certain person doesn't like a book's reputation, all they have to do is not read it. Even in school systems, librarians are there to guide kids to read good books. If a child wants to read an inappropriate book, the librarian will most likely discourage him or her not to read it. In my experience, I wanted to read a book that my mother suggested to me, but as I went to the school library it turned out to be a censored book. Some parents believe children should be ignorant about offensive things written in books, but honestly many of the same ideas are exploited to them everyday on television and internet. So trying to shield your child from the bad things may be a great thing, but the efforts are usually failed attempts. It also never occurs to the people censoring the books, that some people can't afford to buy the books they want to read. The libraries, for some, are the main means for getting books. To conclude there is very little reason to ban a book from the shelves. Many of the books banned have important lessons that can be obtained through reading it. If a person doesn't like a book, the simplest thing to do is not to pick it up.\", \"post_assessment\": \"[1, 1]\", \"score\": 2}, {\"answer\": \"This is another response\", \"post_assessment\": \"[1, 1]\", \"score\": 2}], \"max_score\": 2, \"child_state\": \"done\"}", "{\"child_created\": false, \"child_attempts\": 0, \"version\": 1, \"child_history\": [{\"answer\": \"In libraries, there should not be censorship on materials considering that it's an individual's decision to read what they prefer. There is no appropriate standard on what makes a book offensive to a group, so it should be undetermined as to what makes a book offensive. In a public library, many children, who the books are censored for, are with their parents. Parents should make an independent choice on what they can allow their children to read. Letting society ban a book simply for the use of inappropriate materials is ridiculous. If an author spent time creating a story, it should be appreciated, and should not put on a list of no-nos. If a certain person doesn't like a book's reputation, all they have to do is not read it. Even in school systems, librarians are there to guide kids to read good books. If a child wants to read an inappropriate book, the librarian will most likely discourage him or her not to read it. In my experience, I wanted to read a book that my mother suggested to me, but as I went to the school library it turned out to be a censored book. Some parents believe children should be ignorant about offensive things written in books, but honestly many of the same ideas are exploited to them everyday on television and internet. So trying to shield your child from the bad things may be a great thing, but the efforts are usually failed attempts. It also never occurs to the people censoring the books, that some people can't afford to buy the books they want to read. The libraries, for some, are the main means for getting books. To conclude there is very little reason to ban a book from the shelves. Many of the books banned have important lessons that can be obtained through reading it. If a person doesn't like a book, the simplest thing to do is not to pick it up.\", \"post_assessment\": \"{\\\"submission_id\\\": 6107, \\\"score\\\": 2, \\\"feedback\\\": \\\"{\\\\\\\"feedback\\\\\\\": \\\\\\\"\\\\\\\"}\\\", \\\"success\\\": true, \\\"grader_id\\\": 1898718, \\\"grader_type\\\": \\\"IN\\\", \\\"rubric_scores_complete\\\": true, \\\"rubric_xml\\\": \\\"<rubric><category><description>Writing Applications</description><score>1</score><option points='0'> The essay loses focus, has little information or supporting details, and the organization makes it difficult to follow.</option><option points='1'> The essay presents a mostly unified theme, includes sufficient information to convey the theme, and is generally organized well.</option></category><category><description> Language Conventions </description><score>1</score><option points='0'> The essay demonstrates a reasonable command of proper spelling and grammar. </option><option points='1'> The essay demonstrates superior command of proper spelling and grammar.</option></category></rubric>\\\"}\", \"score\": 2}, {\"answer\": \"This is another response\"}], \"max_score\": 2, \"child_state\": \"assessing\"}"]884# Task state with ai assessment only.885TEST_STATE_AI2 = ["{\"child_created\": false, \"child_attempts\": 0, \"version\": 1, \"child_history\": [{\"answer\": \"This isn't a real essay, and you should give me a zero on it. \", \"post_assessment\": \"{\\\"submission_id\\\": 18446, \\\"score\\\": [0, 1, 0], \\\"feedback\\\": [\\\"{\\\\\\\"feedback\\\\\\\": \\\\\\\"\\\\\\\"}\\\", \\\"{\\\\\\\"feedback\\\\\\\": \\\\\\\"\\\\\\\"}\\\", \\\"{\\\\\\\"feedback\\\\\\\": \\\\\\\"Zero it is! \\\\\\\"}\\\"], \\\"success\\\": true, \\\"grader_id\\\": [1944146, 1943188, 1940991], \\\"grader_type\\\": \\\"PE\\\", \\\"rubric_scores_complete\\\": [true, true, true], \\\"rubric_xml\\\": [\\\"<rubric><category><description>Writing Applications</description><score>0</score><option points='0'> The essay loses focus, has little information or supporting details, and the organization makes it difficult to follow.</option><option points='1'> The essay presents a mostly unified theme, includes sufficient information to convey the theme, and is generally organized well.</option></category><category><description> Language Conventions </description><score>0</score><option points='0'> The essay demonstrates a reasonable command of proper spelling and grammar. </option><option points='1'> The essay demonstrates superior command of proper spelling and grammar.</option></category></rubric>\\\", \\\"<rubric><category><description>Writing Applications</description><score>0</score><option points='0'> The essay loses focus, has little information or supporting details, and the organization makes it difficult to follow.</option><option points='1'> The essay presents a mostly unified theme, includes sufficient information to convey the theme, and is generally organized well.</option></category><category><description> Language Conventions </description><score>1</score><option points='0'> The essay demonstrates a reasonable command of proper spelling and grammar. </option><option points='1'> The essay demonstrates superior command of proper spelling and grammar.</option></category></rubric>\\\", \\\"<rubric><category><description>Writing Applications</description><score>0</score><option points='0'> The essay loses focus, has little information or supporting details, and the organization makes it difficult to follow.</option><option points='1'> The essay presents a mostly unified theme, includes sufficient information to convey the theme, and is generally organized well.</option></category><category><description> Language Conventions </description><score>0</score><option points='0'> The essay demonstrates a reasonable command of proper spelling and grammar. </option><option points='1'> The essay demonstrates superior command of proper spelling and grammar.</option></category></rubric>\\\"]}\", \"score\": 0}], \"max_score\": 2, \"child_state\": \"post_assessment\"}"]886# Invalid task state with ai assessment.887TEST_STATE_AI2_INVALID = ["{\"child_created\": false, \"child_attempts\": 0, \"version\": 1, \"child_history\": [{\"answer\": \"This isn't a real essay, and you should give me a zero on it. \", \"post_assessment\": \"{\\\"submission_id\\\": 18446, \\\"score\\\": [0, 1, 0], \\\"feedback\\\": [\\\"{\\\\\\\"feedback\\\\\\\": \\\\\\\"\\\\\\\"}\\\", \\\"{\\\\\\\"feedback\\\\\\\": \\\\\\\"\\\\\\\"}\\\", \\\"{\\\\\\\"feedback\\\\\\\": \\\\\\\"Zero it is! \\\\\\\"}\\\"], \\\"success\\\": true, \\\"grader_id\\\": [1943188, 1940991], \\\"grader_type\\\": \\\"PE\\\", \\\"rubric_scores_complete\\\": [true, true, true], \\\"rubric_xml\\\": [\\\"<rubric><category><description>Writing Applications</description><score>0</score><option points='0'> The essay loses focus, has little information or supporting details, and the organization makes it difficult to follow.</option><option points='1'> The essay presents a mostly unified theme, includes sufficient information to convey the theme, and is generally organized well.</option></category><category><description> Language Conventions </description><score>0</score><option points='0'> The essay demonstrates a reasonable command of proper spelling and grammar. </option><option points='1'> The essay demonstrates superior command of proper spelling and grammar.</option></category></rubric>\\\", \\\"<rubric><category><description>Writing Applications</description><score>0</score><option points='0'> The essay loses focus, has little information or supporting details, and the organization makes it difficult to follow.</option><option points='1'> The essay presents a mostly unified theme, includes sufficient information to convey the theme, and is generally organized well.</option></category><category><description> Language Conventions </description><score>1</score><option points='0'> The essay demonstrates a reasonable command of proper spelling and grammar. </option><option points='1'> The essay demonstrates superior command of proper spelling and grammar.</option></category></rubric>\\\", \\\"<rubric><category><description>Writing Applications</description><score>0</score><option points='0'> The essay loses focus, has little information or supporting details, and the organization makes it difficult to follow.</option><option points='1'> The essay presents a mostly unified theme, includes sufficient information to convey the theme, and is generally organized well.</option></category><category><description> Language Conventions </description><score>0</score><option points='0'> The essay demonstrates a reasonable command of proper spelling and grammar. </option><option points='1'> The essay demonstrates superior command of proper spelling and grammar.</option></category></rubric>\\\"]}\", \"score\": 0}], \"max_score\": 2, \"child_state\": \"post_assessment\"}"]888# Self assessment state.889TEST_STATE_SINGLE = ["{\"child_created\": false, \"child_attempts\": 1, \"version\": 1, \"child_history\": [{\"answer\": \"'All of us can think of a book that we hope none of our children or any other children have taken off the shelf. But if I have the right to remove that book from the shelf -- that work I abhor -- then you also have exactly the same right and so does everyone else. And then we have no books left on the shelf for any of us.' --Katherine Paterson, Author\\r<br><br>Write a persuasive essay to a newspaper reflecting your views on censorship in libraries. Do you believe that certain materials, such as books, music, movies, magazines, etc., should be removed from the shelves if they are found offensive? Support your position with convincing arguments from your own experience, observations, and/or reading. \", \"post_assessment\": \"[3, 3, 2, 2, 2]\", \"score\": 12}], \"max_score\": 12, \"child_state\": \"done\"}"]890# Peer grading state....

Full Screen

Full Screen

test_optparse.py

Source:test_optparse.py Github

copy

Full Screen

...155 raise self.failureException(156 'help text failure; expected:\n"' +157 expected_help + '"; got:\n"' +158 actual_help + '"\n')159# -- Test make_option() aka Option -------------------------------------160# It's not necessary to test correct options here. All the tests in the161# parser.parse_args() section deal with those, because they're needed162# there.163class TestOptionChecks(BaseTest):164 def setUp(self):165 self.parser = OptionParser(usage=SUPPRESS_USAGE)166 def assertOptionError(self, expected_message, args=[], kwargs={}):167 self.assertRaises(make_option, args, kwargs,168 OptionError, expected_message)169 def test_opt_string_empty(self):170 self.assertTypeError(make_option,171 "at least one option string must be supplied")172 def test_opt_string_too_short(self):173 self.assertOptionError(174 "invalid option string 'b': must be at least two characters long",175 ["b"])176 def test_opt_string_short_invalid(self):177 self.assertOptionError(178 "invalid short option string '--': must be "179 "of the form -x, (x any non-dash char)",180 ["--"])181 def test_opt_string_long_invalid(self):182 self.assertOptionError(183 "invalid long option string '---': "184 "must start with --, followed by non-dash",185 ["---"])186 def test_attr_invalid(self):187 self.assertOptionError(188 "option -b: invalid keyword arguments: bar, foo",189 ["-b"], {'foo': None, 'bar': None})190 def test_action_invalid(self):191 self.assertOptionError(192 "option -b: invalid action: 'foo'",193 ["-b"], {'action': 'foo'})194 def test_type_invalid(self):195 self.assertOptionError(196 "option -b: invalid option type: 'foo'",197 ["-b"], {'type': 'foo'})198 self.assertOptionError(199 "option -b: invalid option type: 'tuple'",200 ["-b"], {'type': tuple})201 def test_no_type_for_action(self):202 self.assertOptionError(203 "option -b: must not supply a type for action 'count'",204 ["-b"], {'action': 'count', 'type': 'int'})205 def test_no_choices_list(self):206 self.assertOptionError(207 "option -b/--bad: must supply a list of "208 "choices for type 'choice'",209 ["-b", "--bad"], {'type': "choice"})210 def test_bad_choices_list(self):211 typename = type('').__name__212 self.assertOptionError(213 "option -b/--bad: choices must be a list of "214 "strings ('%s' supplied)" % typename,215 ["-b", "--bad"],216 {'type': "choice", 'choices':"bad choices"})217 def test_no_choices_for_type(self):218 self.assertOptionError(219 "option -b: must not supply choices for type 'int'",220 ["-b"], {'type': 'int', 'choices':"bad"})221 def test_no_const_for_action(self):222 self.assertOptionError(223 "option -b: 'const' must not be supplied for action 'store'",224 ["-b"], {'action': 'store', 'const': 1})225 def test_no_nargs_for_action(self):226 self.assertOptionError(227 "option -b: 'nargs' must not be supplied for action 'count'",228 ["-b"], {'action': 'count', 'nargs': 2})229 def test_callback_not_callable(self):230 self.assertOptionError(231 "option -b: callback not callable: 'foo'",232 ["-b"], {'action': 'callback',233 'callback': 'foo'})234 def dummy(self):235 pass236 def test_callback_args_no_tuple(self):237 self.assertOptionError(238 "option -b: callback_args, if supplied, "239 "must be a tuple: not 'foo'",240 ["-b"], {'action': 'callback',241 'callback': self.dummy,242 'callback_args': 'foo'})243 def test_callback_kwargs_no_dict(self):244 self.assertOptionError(245 "option -b: callback_kwargs, if supplied, "246 "must be a dict: not 'foo'",247 ["-b"], {'action': 'callback',248 'callback': self.dummy,249 'callback_kwargs': 'foo'})250 def test_no_callback_for_action(self):251 self.assertOptionError(252 "option -b: callback supplied ('foo') for non-callback option",253 ["-b"], {'action': 'store',254 'callback': 'foo'})255 def test_no_callback_args_for_action(self):256 self.assertOptionError(257 "option -b: callback_args supplied for non-callback option",258 ["-b"], {'action': 'store',259 'callback_args': 'foo'})260 def test_no_callback_kwargs_for_action(self):261 self.assertOptionError(262 "option -b: callback_kwargs supplied for non-callback option",263 ["-b"], {'action': 'store',264 'callback_kwargs': 'foo'})265 def test_no_single_dash(self):266 self.assertOptionError(267 "invalid long option string '-debug': "268 "must start with --, followed by non-dash",269 ["-debug"])270 self.assertOptionError(271 "option -d: invalid long option string '-debug': must start with"272 " --, followed by non-dash",273 ["-d", "-debug"])274 self.assertOptionError(275 "invalid long option string '-debug': "276 "must start with --, followed by non-dash",277 ["-debug", "--debug"])278class TestOptionParser(BaseTest):279 def setUp(self):280 self.parser = OptionParser()281 self.parser.add_option("-v", "--verbose", "-n", "--noisy",282 action="store_true", dest="verbose")283 self.parser.add_option("-q", "--quiet", "--silent",284 action="store_false", dest="verbose")285 def test_add_option_no_Option(self):286 self.assertTypeError(self.parser.add_option,287 "not an Option instance: None", None)288 def test_add_option_invalid_arguments(self):289 self.assertTypeError(self.parser.add_option,290 "invalid arguments", None, None)291 def test_get_option(self):292 opt1 = self.parser.get_option("-v")293 self.assertIsInstance(opt1, Option)294 self.assertEqual(opt1._short_opts, ["-v", "-n"])295 self.assertEqual(opt1._long_opts, ["--verbose", "--noisy"])296 self.assertEqual(opt1.action, "store_true")297 self.assertEqual(opt1.dest, "verbose")298 def test_get_option_equals(self):299 opt1 = self.parser.get_option("-v")300 opt2 = self.parser.get_option("--verbose")301 opt3 = self.parser.get_option("-n")302 opt4 = self.parser.get_option("--noisy")303 self.assertTrue(opt1 is opt2 is opt3 is opt4)304 def test_has_option(self):305 self.assertTrue(self.parser.has_option("-v"))306 self.assertTrue(self.parser.has_option("--verbose"))307 def assertTrueremoved(self):308 self.assertTrue(self.parser.get_option("-v") is None)309 self.assertTrue(self.parser.get_option("--verbose") is None)310 self.assertTrue(self.parser.get_option("-n") is None)311 self.assertTrue(self.parser.get_option("--noisy") is None)312 self.assertFalse(self.parser.has_option("-v"))313 self.assertFalse(self.parser.has_option("--verbose"))314 self.assertFalse(self.parser.has_option("-n"))315 self.assertFalse(self.parser.has_option("--noisy"))316 self.assertTrue(self.parser.has_option("-q"))317 self.assertTrue(self.parser.has_option("--silent"))318 def test_remove_short_opt(self):319 self.parser.remove_option("-n")320 self.assertTrueremoved()321 def test_remove_long_opt(self):322 self.parser.remove_option("--verbose")323 self.assertTrueremoved()324 def test_remove_nonexistent(self):325 self.assertRaises(self.parser.remove_option, ('foo',), None,326 ValueError, "no such option 'foo'")327 def test_refleak(self):328 # If an OptionParser is carrying around a reference to a large329 # object, various cycles can prevent it from being GC'd in330 # a timely fashion. destroy() breaks the cycles to ensure stuff331 # can be cleaned up.332 big_thing = [42]333 refcount = sys.getrefcount(big_thing)334 parser = OptionParser()335 parser.add_option("-a", "--aaarggh")336 parser.big_thing = big_thing337 parser.destroy()338 #self.assertEqual(refcount, sys.getrefcount(big_thing))339 del parser340 self.assertEqual(refcount, sys.getrefcount(big_thing))341class TestOptionValues(BaseTest):342 def setUp(self):343 pass344 def test_basics(self):345 values = Values()346 self.assertEqual(vars(values), {})347 self.assertEqual(values, {})348 self.assertNotEqual(values, {"foo": "bar"})349 self.assertNotEqual(values, "")350 dict = {"foo": "bar", "baz": 42}351 values = Values(defaults=dict)352 self.assertEqual(vars(values), dict)353 self.assertEqual(values, dict)354 self.assertNotEqual(values, {"foo": "bar"})355 self.assertNotEqual(values, {})356 self.assertNotEqual(values, "")357 self.assertNotEqual(values, [])358class TestTypeAliases(BaseTest):359 def setUp(self):360 self.parser = OptionParser()361 def test_str_aliases_string(self):362 self.parser.add_option("-s", type="str")363 self.assertEqual(self.parser.get_option("-s").type, "string")364 def test_type_object(self):365 self.parser.add_option("-s", type=str)366 self.assertEqual(self.parser.get_option("-s").type, "string")367 self.parser.add_option("-x", type=int)368 self.assertEqual(self.parser.get_option("-x").type, "int")369# Custom type for testing processing of default values.370_time_units = { 's' : 1, 'm' : 60, 'h' : 60*60, 'd' : 60*60*24 }371def _check_duration(option, opt, value):372 try:373 if value[-1].isdigit():374 return int(value)375 else:376 return int(value[:-1]) * _time_units[value[-1]]377 except (ValueError, IndexError):378 raise OptionValueError(379 'option %s: invalid duration: %r' % (opt, value))380class DurationOption(Option):381 TYPES = Option.TYPES + ('duration',)382 TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER)383 TYPE_CHECKER['duration'] = _check_duration384class TestDefaultValues(BaseTest):385 def setUp(self):386 self.parser = OptionParser()387 self.parser.add_option("-v", "--verbose", default=True)388 self.parser.add_option("-q", "--quiet", dest='verbose')389 self.parser.add_option("-n", type="int", default=37)390 self.parser.add_option("-m", type="int")391 self.parser.add_option("-s", default="foo")392 self.parser.add_option("-t")393 self.parser.add_option("-u", default=None)394 self.expected = { 'verbose': True,395 'n': 37,396 'm': None,397 's': "foo",398 't': None,399 'u': None }400 def test_basic_defaults(self):401 self.assertEqual(self.parser.get_default_values(), self.expected)402 def test_mixed_defaults_post(self):403 self.parser.set_defaults(n=42, m=-100)404 self.expected.update({'n': 42, 'm': -100})405 self.assertEqual(self.parser.get_default_values(), self.expected)406 def test_mixed_defaults_pre(self):407 self.parser.set_defaults(x="barf", y="blah")408 self.parser.add_option("-x", default="frob")409 self.parser.add_option("-y")410 self.expected.update({'x': "frob", 'y': "blah"})411 self.assertEqual(self.parser.get_default_values(), self.expected)412 self.parser.remove_option("-y")413 self.parser.add_option("-y", default=None)414 self.expected.update({'y': None})415 self.assertEqual(self.parser.get_default_values(), self.expected)416 def test_process_default(self):417 self.parser.option_class = DurationOption418 self.parser.add_option("-d", type="duration", default=300)419 self.parser.add_option("-e", type="duration", default="6m")420 self.parser.set_defaults(n="42")421 self.expected.update({'d': 300, 'e': 360, 'n': 42})422 self.assertEqual(self.parser.get_default_values(), self.expected)423 self.parser.set_process_default_values(False)424 self.expected.update({'d': 300, 'e': "6m", 'n': "42"})425 self.assertEqual(self.parser.get_default_values(), self.expected)426class TestProgName(BaseTest):427 """428 Test that %prog expands to the right thing in usage, version,429 and help strings.430 """431 def assertUsage(self, parser, expected_usage):432 self.assertEqual(parser.get_usage(), expected_usage)433 def assertVersion(self, parser, expected_version):434 self.assertEqual(parser.get_version(), expected_version)435 def test_default_progname(self):436 # Make sure that program name taken from sys.argv[0] by default.437 save_argv = sys.argv[:]438 try:439 sys.argv[0] = os.path.join("foo", "bar", "baz.py")440 parser = OptionParser("%prog ...", version="%prog 1.2")441 expected_usage = "Usage: baz.py ...\n"442 self.assertUsage(parser, expected_usage)443 self.assertVersion(parser, "baz.py 1.2")444 self.assertHelp(parser,445 expected_usage + "\n" +446 "Options:\n"447 " --version show program's version number and exit\n"448 " -h, --help show this help message and exit\n")449 finally:450 sys.argv[:] = save_argv451 def test_custom_progname(self):452 parser = OptionParser(prog="thingy",453 version="%prog 0.1",454 usage="%prog arg arg")455 parser.remove_option("-h")456 parser.remove_option("--version")457 expected_usage = "Usage: thingy arg arg\n"458 self.assertUsage(parser, expected_usage)459 self.assertVersion(parser, "thingy 0.1")460 self.assertHelp(parser, expected_usage + "\n")461class TestExpandDefaults(BaseTest):462 def setUp(self):463 self.parser = OptionParser(prog="test")464 self.help_prefix = """\465Usage: test [options]466Options:467 -h, --help show this help message and exit468"""469 self.file_help = "read from FILE [default: %default]"470 self.expected_help_file = self.help_prefix + \471 " -f FILE, --file=FILE read from FILE [default: foo.txt]\n"472 self.expected_help_none = self.help_prefix + \473 " -f FILE, --file=FILE read from FILE [default: none]\n"474 def test_option_default(self):475 self.parser.add_option("-f", "--file",476 default="foo.txt",477 help=self.file_help)478 self.assertHelp(self.parser, self.expected_help_file)479 def test_parser_default_1(self):480 self.parser.add_option("-f", "--file",481 help=self.file_help)482 self.parser.set_default('file', "foo.txt")483 self.assertHelp(self.parser, self.expected_help_file)484 def test_parser_default_2(self):485 self.parser.add_option("-f", "--file",486 help=self.file_help)487 self.parser.set_defaults(file="foo.txt")488 self.assertHelp(self.parser, self.expected_help_file)489 def test_no_default(self):490 self.parser.add_option("-f", "--file",491 help=self.file_help)492 self.assertHelp(self.parser, self.expected_help_none)493 def test_default_none_1(self):494 self.parser.add_option("-f", "--file",495 default=None,496 help=self.file_help)497 self.assertHelp(self.parser, self.expected_help_none)498 def test_default_none_2(self):499 self.parser.add_option("-f", "--file",500 help=self.file_help)501 self.parser.set_defaults(file=None)502 self.assertHelp(self.parser, self.expected_help_none)503 def test_float_default(self):504 self.parser.add_option(505 "-p", "--prob",506 help="blow up with probability PROB [default: %default]")507 self.parser.set_defaults(prob=0.43)508 expected_help = self.help_prefix + \509 " -p PROB, --prob=PROB blow up with probability PROB [default: 0.43]\n"510 self.assertHelp(self.parser, expected_help)511 def test_alt_expand(self):512 self.parser.add_option("-f", "--file",513 default="foo.txt",514 help="read from FILE [default: *DEFAULT*]")515 self.parser.formatter.default_tag = "*DEFAULT*"516 self.assertHelp(self.parser, self.expected_help_file)517 def test_no_expand(self):518 self.parser.add_option("-f", "--file",519 default="foo.txt",520 help="read from %default file")521 self.parser.formatter.default_tag = None522 expected_help = self.help_prefix + \523 " -f FILE, --file=FILE read from %default file\n"524 self.assertHelp(self.parser, expected_help)525# -- Test parser.parse_args() ------------------------------------------526class TestStandard(BaseTest):527 def setUp(self):528 options = [make_option("-a", type="string"),529 make_option("-b", "--boo", type="int", dest='boo'),530 make_option("--foo", action="append")]531 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,532 option_list=options)533 def test_required_value(self):534 self.assertParseFail(["-a"], "-a option requires 1 argument")535 def test_invalid_integer(self):536 self.assertParseFail(["-b", "5x"],537 "option -b: invalid integer value: '5x'")538 def test_no_such_option(self):539 self.assertParseFail(["--boo13"], "no such option: --boo13")540 def test_long_invalid_integer(self):541 self.assertParseFail(["--boo=x5"],542 "option --boo: invalid integer value: 'x5'")543 def test_empty(self):544 self.assertParseOK([], {'a': None, 'boo': None, 'foo': None}, [])545 def test_shortopt_empty_longopt_append(self):546 self.assertParseOK(["-a", "", "--foo=blah", "--foo="],547 {'a': "", 'boo': None, 'foo': ["blah", ""]},548 [])549 def test_long_option_append(self):550 self.assertParseOK(["--foo", "bar", "--foo", "", "--foo=x"],551 {'a': None,552 'boo': None,553 'foo': ["bar", "", "x"]},554 [])555 def test_option_argument_joined(self):556 self.assertParseOK(["-abc"],557 {'a': "bc", 'boo': None, 'foo': None},558 [])559 def test_option_argument_split(self):560 self.assertParseOK(["-a", "34"],561 {'a': "34", 'boo': None, 'foo': None},562 [])563 def test_option_argument_joined_integer(self):564 self.assertParseOK(["-b34"],565 {'a': None, 'boo': 34, 'foo': None},566 [])567 def test_option_argument_split_negative_integer(self):568 self.assertParseOK(["-b", "-5"],569 {'a': None, 'boo': -5, 'foo': None},570 [])571 def test_long_option_argument_joined(self):572 self.assertParseOK(["--boo=13"],573 {'a': None, 'boo': 13, 'foo': None},574 [])575 def test_long_option_argument_split(self):576 self.assertParseOK(["--boo", "111"],577 {'a': None, 'boo': 111, 'foo': None},578 [])579 def test_long_option_short_option(self):580 self.assertParseOK(["--foo=bar", "-axyz"],581 {'a': 'xyz', 'boo': None, 'foo': ["bar"]},582 [])583 def test_abbrev_long_option(self):584 self.assertParseOK(["--f=bar", "-axyz"],585 {'a': 'xyz', 'boo': None, 'foo': ["bar"]},586 [])587 def test_defaults(self):588 (options, args) = self.parser.parse_args([])589 defaults = self.parser.get_default_values()590 self.assertEqual(vars(defaults), vars(options))591 def test_ambiguous_option(self):592 self.parser.add_option("--foz", action="store",593 type="string", dest="foo")594 self.assertParseFail(["--f=bar"],595 "ambiguous option: --f (--foo, --foz?)")596 def test_short_and_long_option_split(self):597 self.assertParseOK(["-a", "xyz", "--foo", "bar"],598 {'a': 'xyz', 'boo': None, 'foo': ["bar"]},599 []),600 def test_short_option_split_long_option_append(self):601 self.assertParseOK(["--foo=bar", "-b", "123", "--foo", "baz"],602 {'a': None, 'boo': 123, 'foo': ["bar", "baz"]},603 [])604 def test_short_option_split_one_positional_arg(self):605 self.assertParseOK(["-a", "foo", "bar"],606 {'a': "foo", 'boo': None, 'foo': None},607 ["bar"]),608 def test_short_option_consumes_separator(self):609 self.assertParseOK(["-a", "--", "foo", "bar"],610 {'a': "--", 'boo': None, 'foo': None},611 ["foo", "bar"]),612 self.assertParseOK(["-a", "--", "--foo", "bar"],613 {'a': "--", 'boo': None, 'foo': ["bar"]},614 []),615 def test_short_option_joined_and_separator(self):616 self.assertParseOK(["-ab", "--", "--foo", "bar"],617 {'a': "b", 'boo': None, 'foo': None},618 ["--foo", "bar"]),619 def test_hyphen_becomes_positional_arg(self):620 self.assertParseOK(["-ab", "-", "--foo", "bar"],621 {'a': "b", 'boo': None, 'foo': ["bar"]},622 ["-"])623 def test_no_append_versus_append(self):624 self.assertParseOK(["-b3", "-b", "5", "--foo=bar", "--foo", "baz"],625 {'a': None, 'boo': 5, 'foo': ["bar", "baz"]},626 [])627 def test_option_consumes_optionlike_string(self):628 self.assertParseOK(["-a", "-b3"],629 {'a': "-b3", 'boo': None, 'foo': None},630 [])631 def test_combined_single_invalid_option(self):632 self.parser.add_option("-t", action="store_true")633 self.assertParseFail(["-test"],634 "no such option: -e")635class TestBool(BaseTest):636 def setUp(self):637 options = [make_option("-v",638 "--verbose",639 action="store_true",640 dest="verbose",641 default=''),642 make_option("-q",643 "--quiet",644 action="store_false",645 dest="verbose")]646 self.parser = OptionParser(option_list = options)647 def test_bool_default(self):648 self.assertParseOK([],649 {'verbose': ''},650 [])651 def test_bool_false(self):652 (options, args) = self.assertParseOK(["-q"],653 {'verbose': 0},654 [])655 self.assertTrue(options.verbose is False)656 def test_bool_true(self):657 (options, args) = self.assertParseOK(["-v"],658 {'verbose': 1},659 [])660 self.assertTrue(options.verbose is True)661 def test_bool_flicker_on_and_off(self):662 self.assertParseOK(["-qvq", "-q", "-v"],663 {'verbose': 1},664 [])665class TestChoice(BaseTest):666 def setUp(self):667 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)668 self.parser.add_option("-c", action="store", type="choice",669 dest="choice", choices=["one", "two", "three"])670 def test_valid_choice(self):671 self.assertParseOK(["-c", "one", "xyz"],672 {'choice': 'one'},673 ["xyz"])674 def test_invalid_choice(self):675 self.assertParseFail(["-c", "four", "abc"],676 "option -c: invalid choice: 'four' "677 "(choose from 'one', 'two', 'three')")678 def test_add_choice_option(self):679 self.parser.add_option("-d", "--default",680 choices=["four", "five", "six"])681 opt = self.parser.get_option("-d")682 self.assertEqual(opt.type, "choice")683 self.assertEqual(opt.action, "store")684class TestCount(BaseTest):685 def setUp(self):686 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)687 self.v_opt = make_option("-v", action="count", dest="verbose")688 self.parser.add_option(self.v_opt)689 self.parser.add_option("--verbose", type="int", dest="verbose")690 self.parser.add_option("-q", "--quiet",691 action="store_const", dest="verbose", const=0)692 def test_empty(self):693 self.assertParseOK([], {'verbose': None}, [])694 def test_count_one(self):695 self.assertParseOK(["-v"], {'verbose': 1}, [])696 def test_count_three(self):697 self.assertParseOK(["-vvv"], {'verbose': 3}, [])698 def test_count_three_apart(self):699 self.assertParseOK(["-v", "-v", "-v"], {'verbose': 3}, [])700 def test_count_override_amount(self):701 self.assertParseOK(["-vvv", "--verbose=2"], {'verbose': 2}, [])702 def test_count_override_quiet(self):703 self.assertParseOK(["-vvv", "--verbose=2", "-q"], {'verbose': 0}, [])704 def test_count_overriding(self):705 self.assertParseOK(["-vvv", "--verbose=2", "-q", "-v"],706 {'verbose': 1}, [])707 def test_count_interspersed_args(self):708 self.assertParseOK(["--quiet", "3", "-v"],709 {'verbose': 1},710 ["3"])711 def test_count_no_interspersed_args(self):712 self.parser.disable_interspersed_args()713 self.assertParseOK(["--quiet", "3", "-v"],714 {'verbose': 0},715 ["3", "-v"])716 def test_count_no_such_option(self):717 self.assertParseFail(["-q3", "-v"], "no such option: -3")718 def test_count_option_no_value(self):719 self.assertParseFail(["--quiet=3", "-v"],720 "--quiet option does not take a value")721 def test_count_with_default(self):722 self.parser.set_default('verbose', 0)723 self.assertParseOK([], {'verbose':0}, [])724 def test_count_overriding_default(self):725 self.parser.set_default('verbose', 0)726 self.assertParseOK(["-vvv", "--verbose=2", "-q", "-v"],727 {'verbose': 1}, [])728class TestMultipleArgs(BaseTest):729 def setUp(self):730 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)731 self.parser.add_option("-p", "--point",732 action="store", nargs=3, type="float", dest="point")733 def test_nargs_with_positional_args(self):734 self.assertParseOK(["foo", "-p", "1", "2.5", "-4.3", "xyz"],735 {'point': (1.0, 2.5, -4.3)},736 ["foo", "xyz"])737 def test_nargs_long_opt(self):738 self.assertParseOK(["--point", "-1", "2.5", "-0", "xyz"],739 {'point': (-1.0, 2.5, -0.0)},740 ["xyz"])741 def test_nargs_invalid_float_value(self):742 self.assertParseFail(["-p", "1.0", "2x", "3.5"],743 "option -p: "744 "invalid floating-point value: '2x'")745 def test_nargs_required_values(self):746 self.assertParseFail(["--point", "1.0", "3.5"],747 "--point option requires 3 arguments")748class TestMultipleArgsAppend(BaseTest):749 def setUp(self):750 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)751 self.parser.add_option("-p", "--point", action="store", nargs=3,752 type="float", dest="point")753 self.parser.add_option("-f", "--foo", action="append", nargs=2,754 type="int", dest="foo")755 self.parser.add_option("-z", "--zero", action="append_const",756 dest="foo", const=(0, 0))757 def test_nargs_append(self):758 self.assertParseOK(["-f", "4", "-3", "blah", "--foo", "1", "666"],759 {'point': None, 'foo': [(4, -3), (1, 666)]},760 ["blah"])761 def test_nargs_append_required_values(self):762 self.assertParseFail(["-f4,3"],763 "-f option requires 2 arguments")764 def test_nargs_append_simple(self):765 self.assertParseOK(["--foo=3", "4"],766 {'point': None, 'foo':[(3, 4)]},767 [])768 def test_nargs_append_const(self):769 self.assertParseOK(["--zero", "--foo", "3", "4", "-z"],770 {'point': None, 'foo':[(0, 0), (3, 4), (0, 0)]},771 [])772class TestVersion(BaseTest):773 def test_version(self):774 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,775 version="%prog 0.1")776 save_argv = sys.argv[:]777 try:778 sys.argv[0] = os.path.join(os.curdir, "foo", "bar")779 self.assertOutput(["--version"], "bar 0.1\n")780 finally:781 sys.argv[:] = save_argv782 def test_no_version(self):783 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)784 self.assertParseFail(["--version"],785 "no such option: --version")786# -- Test conflicting default values and parser.parse_args() -----------787class TestConflictingDefaults(BaseTest):788 """Conflicting default values: the last one should win."""789 def setUp(self):790 self.parser = OptionParser(option_list=[791 make_option("-v", action="store_true", dest="verbose", default=1)])792 def test_conflict_default(self):793 self.parser.add_option("-q", action="store_false", dest="verbose",794 default=0)795 self.assertParseOK([], {'verbose': 0}, [])796 def test_conflict_default_none(self):797 self.parser.add_option("-q", action="store_false", dest="verbose",798 default=None)799 self.assertParseOK([], {'verbose': None}, [])800class TestOptionGroup(BaseTest):801 def setUp(self):802 self.parser = OptionParser(usage=SUPPRESS_USAGE)803 def test_option_group_create_instance(self):804 group = OptionGroup(self.parser, "Spam")805 self.parser.add_option_group(group)806 group.add_option("--spam", action="store_true",807 help="spam spam spam spam")808 self.assertParseOK(["--spam"], {'spam': 1}, [])809 def test_add_group_no_group(self):810 self.assertTypeError(self.parser.add_option_group,811 "not an OptionGroup instance: None", None)812 def test_add_group_invalid_arguments(self):813 self.assertTypeError(self.parser.add_option_group,814 "invalid arguments", None, None)815 def test_add_group_wrong_parser(self):816 group = OptionGroup(self.parser, "Spam")817 group.parser = OptionParser()818 self.assertRaises(self.parser.add_option_group, (group,), None,819 ValueError, "invalid OptionGroup (wrong parser)")820 def test_group_manipulate(self):821 group = self.parser.add_option_group("Group 2",822 description="Some more options")823 group.set_title("Bacon")824 group.add_option("--bacon", type="int")825 self.assertTrue(self.parser.get_option_group("--bacon"), group)826# -- Test extending and parser.parse_args() ----------------------------827class TestExtendAddTypes(BaseTest):828 def setUp(self):829 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,830 option_class=self.MyOption)831 self.parser.add_option("-a", None, type="string", dest="a")832 self.parser.add_option("-f", "--file", type="file", dest="file")833 def tearDown(self):834 if os.path.isdir(support.TESTFN):835 os.rmdir(support.TESTFN)836 elif os.path.isfile(support.TESTFN):837 os.unlink(support.TESTFN)838 class MyOption (Option):839 def check_file(option, opt, value):840 if not os.path.exists(value):841 raise OptionValueError("%s: file does not exist" % value)842 elif not os.path.isfile(value):843 raise OptionValueError("%s: not a regular file" % value)844 return value845 TYPES = Option.TYPES + ("file",)846 TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER)847 TYPE_CHECKER["file"] = check_file848 def test_filetype_ok(self):849 support.create_empty_file(support.TESTFN)850 self.assertParseOK(["--file", support.TESTFN, "-afoo"],851 {'file': support.TESTFN, 'a': 'foo'},852 [])853 def test_filetype_noexist(self):854 self.assertParseFail(["--file", support.TESTFN, "-afoo"],855 "%s: file does not exist" %856 support.TESTFN)857 def test_filetype_notfile(self):858 os.mkdir(support.TESTFN)859 self.assertParseFail(["--file", support.TESTFN, "-afoo"],860 "%s: not a regular file" %861 support.TESTFN)862class TestExtendAddActions(BaseTest):863 def setUp(self):864 options = [self.MyOption("-a", "--apple", action="extend",865 type="string", dest="apple")]866 self.parser = OptionParser(option_list=options)867 class MyOption (Option):868 ACTIONS = Option.ACTIONS + ("extend",)869 STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)870 TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)871 def take_action(self, action, dest, opt, value, values, parser):872 if action == "extend":873 lvalue = value.split(",")874 values.ensure_value(dest, []).extend(lvalue)875 else:876 Option.take_action(self, action, dest, opt, parser, value,877 values)878 def test_extend_add_action(self):879 self.assertParseOK(["-afoo,bar", "--apple=blah"],880 {'apple': ["foo", "bar", "blah"]},881 [])882 def test_extend_add_action_normal(self):883 self.assertParseOK(["-a", "foo", "-abar", "--apple=x,y"],884 {'apple': ["foo", "bar", "x", "y"]},885 [])886# -- Test callbacks and parser.parse_args() ----------------------------887class TestCallback(BaseTest):888 def setUp(self):889 options = [make_option("-x",890 None,891 action="callback",892 callback=self.process_opt),893 make_option("-f",894 "--file",895 action="callback",896 callback=self.process_opt,897 type="string",898 dest="filename")]899 self.parser = OptionParser(option_list=options)900 def process_opt(self, option, opt, value, parser_):901 if opt == "-x":902 self.assertEqual(option._short_opts, ["-x"])903 self.assertEqual(option._long_opts, [])904 self.assertTrue(parser_ is self.parser)905 self.assertTrue(value is None)906 self.assertEqual(vars(parser_.values), {'filename': None})907 parser_.values.x = 42908 elif opt == "--file":909 self.assertEqual(option._short_opts, ["-f"])910 self.assertEqual(option._long_opts, ["--file"])911 self.assertTrue(parser_ is self.parser)912 self.assertEqual(value, "foo")913 self.assertEqual(vars(parser_.values), {'filename': None, 'x': 42})914 setattr(parser_.values, option.dest, value)915 else:916 self.fail("Unknown option %r in process_opt." % opt)917 def test_callback(self):918 self.assertParseOK(["-x", "--file=foo"],919 {'filename': "foo", 'x': 42},920 [])921 def test_callback_help(self):922 # This test was prompted by SF bug #960515 -- the point is923 # not to inspect the help text, just to make sure that924 # format_help() doesn't crash.925 parser = OptionParser(usage=SUPPRESS_USAGE)926 parser.remove_option("-h")927 parser.add_option("-t", "--test", action="callback",928 callback=lambda: None, type="string",929 help="foo")930 expected_help = ("Options:\n"931 " -t TEST, --test=TEST foo\n")932 self.assertHelp(parser, expected_help)933class TestCallbackExtraArgs(BaseTest):934 def setUp(self):935 options = [make_option("-p", "--point", action="callback",936 callback=self.process_tuple,937 callback_args=(3, int), type="string",938 dest="points", default=[])]939 self.parser = OptionParser(option_list=options)940 def process_tuple(self, option, opt, value, parser_, len, type):941 self.assertEqual(len, 3)942 self.assertTrue(type is int)943 if opt == "-p":944 self.assertEqual(value, "1,2,3")945 elif opt == "--point":946 self.assertEqual(value, "4,5,6")947 value = tuple(map(type, value.split(",")))948 getattr(parser_.values, option.dest).append(value)949 def test_callback_extra_args(self):950 self.assertParseOK(["-p1,2,3", "--point", "4,5,6"],951 {'points': [(1,2,3), (4,5,6)]},952 [])953class TestCallbackMeddleArgs(BaseTest):954 def setUp(self):955 options = [make_option(str(x), action="callback",956 callback=self.process_n, dest='things')957 for x in range(-1, -6, -1)]958 self.parser = OptionParser(option_list=options)959 # Callback that meddles in rargs, largs960 def process_n(self, option, opt, value, parser_):961 # option is -3, -5, etc.962 nargs = int(opt[1:])963 rargs = parser_.rargs964 if len(rargs) < nargs:965 self.fail("Expected %d arguments for %s option." % (nargs, opt))966 dest = parser_.values.ensure_value(option.dest, [])967 dest.append(tuple(rargs[0:nargs]))968 parser_.largs.append(nargs)969 del rargs[0:nargs]970 def test_callback_meddle_args(self):971 self.assertParseOK(["-1", "foo", "-3", "bar", "baz", "qux"],972 {'things': [("foo",), ("bar", "baz", "qux")]},973 [1, 3])974 def test_callback_meddle_args_separator(self):975 self.assertParseOK(["-2", "foo", "--"],976 {'things': [('foo', '--')]},977 [2])978class TestCallbackManyArgs(BaseTest):979 def setUp(self):980 options = [make_option("-a", "--apple", action="callback", nargs=2,981 callback=self.process_many, type="string"),982 make_option("-b", "--bob", action="callback", nargs=3,983 callback=self.process_many, type="int")]984 self.parser = OptionParser(option_list=options)985 def process_many(self, option, opt, value, parser_):986 if opt == "-a":987 self.assertEqual(value, ("foo", "bar"))988 elif opt == "--apple":989 self.assertEqual(value, ("ding", "dong"))990 elif opt == "-b":991 self.assertEqual(value, (1, 2, 3))992 elif opt == "--bob":993 self.assertEqual(value, (-666, 42, 0))994 def test_many_args(self):995 self.assertParseOK(["-a", "foo", "bar", "--apple", "ding", "dong",996 "-b", "1", "2", "3", "--bob", "-666", "42",997 "0"],998 {"apple": None, "bob": None},999 [])1000class TestCallbackCheckAbbrev(BaseTest):1001 def setUp(self):1002 self.parser = OptionParser()1003 self.parser.add_option("--foo-bar", action="callback",1004 callback=self.check_abbrev)1005 def check_abbrev(self, option, opt, value, parser):1006 self.assertEqual(opt, "--foo-bar")1007 def test_abbrev_callback_expansion(self):1008 self.assertParseOK(["--foo"], {}, [])1009class TestCallbackVarArgs(BaseTest):1010 def setUp(self):1011 options = [make_option("-a", type="int", nargs=2, dest="a"),1012 make_option("-b", action="store_true", dest="b"),1013 make_option("-c", "--callback", action="callback",1014 callback=self.variable_args, dest="c")]1015 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,1016 option_list=options)1017 def variable_args(self, option, opt, value, parser):1018 self.assertTrue(value is None)1019 value = []1020 rargs = parser.rargs1021 while rargs:1022 arg = rargs[0]1023 if ((arg[:2] == "--" and len(arg) > 2) or1024 (arg[:1] == "-" and len(arg) > 1 and arg[1] != "-")):1025 break1026 else:1027 value.append(arg)1028 del rargs[0]1029 setattr(parser.values, option.dest, value)1030 def test_variable_args(self):1031 self.assertParseOK(["-a3", "-5", "--callback", "foo", "bar"],1032 {'a': (3, -5), 'b': None, 'c': ["foo", "bar"]},1033 [])1034 def test_consume_separator_stop_at_option(self):1035 self.assertParseOK(["-c", "37", "--", "xxx", "-b", "hello"],1036 {'a': None,1037 'b': True,1038 'c': ["37", "--", "xxx"]},1039 ["hello"])1040 def test_positional_arg_and_variable_args(self):1041 self.assertParseOK(["hello", "-c", "foo", "-", "bar"],1042 {'a': None,1043 'b': None,1044 'c':["foo", "-", "bar"]},1045 ["hello"])1046 def test_stop_at_option(self):1047 self.assertParseOK(["-c", "foo", "-b"],1048 {'a': None, 'b': True, 'c': ["foo"]},1049 [])1050 def test_stop_at_invalid_option(self):1051 self.assertParseFail(["-c", "3", "-5", "-a"], "no such option: -5")1052# -- Test conflict handling and parser.parse_args() --------------------1053class ConflictBase(BaseTest):1054 def setUp(self):1055 options = [make_option("-v", "--verbose", action="count",1056 dest="verbose", help="increment verbosity")]1057 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,1058 option_list=options)1059 def show_version(self, option, opt, value, parser):1060 parser.values.show_version = 11061class TestConflict(ConflictBase):1062 """Use the default conflict resolution for Optik 1.2: error."""1063 def assertTrueconflict_error(self, func):1064 err = self.assertRaises(1065 func, ("-v", "--version"), {'action' : "callback",1066 'callback' : self.show_version,1067 'help' : "show version"},1068 OptionConflictError,1069 "option -v/--version: conflicting option string(s): -v")1070 self.assertEqual(err.msg, "conflicting option string(s): -v")1071 self.assertEqual(err.option_id, "-v/--version")1072 def test_conflict_error(self):1073 self.assertTrueconflict_error(self.parser.add_option)1074 def test_conflict_error_group(self):1075 group = OptionGroup(self.parser, "Group 1")1076 self.assertTrueconflict_error(group.add_option)1077 def test_no_such_conflict_handler(self):1078 self.assertRaises(1079 self.parser.set_conflict_handler, ('foo',), None,1080 ValueError, "invalid conflict_resolution value 'foo'")1081class TestConflictResolve(ConflictBase):1082 def setUp(self):1083 ConflictBase.setUp(self)1084 self.parser.set_conflict_handler("resolve")1085 self.parser.add_option("-v", "--version", action="callback",1086 callback=self.show_version, help="show version")1087 def test_conflict_resolve(self):1088 v_opt = self.parser.get_option("-v")1089 verbose_opt = self.parser.get_option("--verbose")1090 version_opt = self.parser.get_option("--version")1091 self.assertTrue(v_opt is version_opt)1092 self.assertTrue(v_opt is not verbose_opt)1093 self.assertEqual(v_opt._long_opts, ["--version"])1094 self.assertEqual(version_opt._short_opts, ["-v"])1095 self.assertEqual(version_opt._long_opts, ["--version"])1096 self.assertEqual(verbose_opt._short_opts, [])1097 self.assertEqual(verbose_opt._long_opts, ["--verbose"])1098 def test_conflict_resolve_help(self):1099 self.assertOutput(["-h"], """\1100Options:1101 --verbose increment verbosity1102 -h, --help show this help message and exit1103 -v, --version show version1104""")1105 def test_conflict_resolve_short_opt(self):1106 self.assertParseOK(["-v"],1107 {'verbose': None, 'show_version': 1},1108 [])1109 def test_conflict_resolve_long_opt(self):1110 self.assertParseOK(["--verbose"],1111 {'verbose': 1},1112 [])1113 def test_conflict_resolve_long_opts(self):1114 self.assertParseOK(["--verbose", "--version"],1115 {'verbose': 1, 'show_version': 1},1116 [])1117class TestConflictOverride(BaseTest):1118 def setUp(self):1119 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)1120 self.parser.set_conflict_handler("resolve")1121 self.parser.add_option("-n", "--dry-run",1122 action="store_true", dest="dry_run",1123 help="don't do anything")1124 self.parser.add_option("--dry-run", "-n",1125 action="store_const", const=42, dest="dry_run",1126 help="dry run mode")1127 def test_conflict_override_opts(self):1128 opt = self.parser.get_option("--dry-run")1129 self.assertEqual(opt._short_opts, ["-n"])1130 self.assertEqual(opt._long_opts, ["--dry-run"])1131 def test_conflict_override_help(self):1132 self.assertOutput(["-h"], """\1133Options:1134 -h, --help show this help message and exit1135 -n, --dry-run dry run mode1136""")1137 def test_conflict_override_args(self):1138 self.assertParseOK(["-n"],1139 {'dry_run': 42},1140 [])1141# -- Other testing. ----------------------------------------------------1142_expected_help_basic = """\1143Usage: bar.py [options]1144Options:1145 -a APPLE throw APPLEs at basket1146 -b NUM, --boo=NUM shout "boo!" NUM times (in order to frighten away all the1147 evil spirits that cause trouble and mayhem)1148 --foo=FOO store FOO in the foo list for later fooing1149 -h, --help show this help message and exit1150"""1151_expected_help_long_opts_first = """\1152Usage: bar.py [options]1153Options:1154 -a APPLE throw APPLEs at basket1155 --boo=NUM, -b NUM shout "boo!" NUM times (in order to frighten away all the1156 evil spirits that cause trouble and mayhem)1157 --foo=FOO store FOO in the foo list for later fooing1158 --help, -h show this help message and exit1159"""1160_expected_help_title_formatter = """\1161Usage1162=====1163 bar.py [options]1164Options1165=======1166-a APPLE throw APPLEs at basket1167--boo=NUM, -b NUM shout "boo!" NUM times (in order to frighten away all the1168 evil spirits that cause trouble and mayhem)1169--foo=FOO store FOO in the foo list for later fooing1170--help, -h show this help message and exit1171"""1172_expected_help_short_lines = """\1173Usage: bar.py [options]1174Options:1175 -a APPLE throw APPLEs at basket1176 -b NUM, --boo=NUM shout "boo!" NUM times (in order to1177 frighten away all the evil spirits1178 that cause trouble and mayhem)1179 --foo=FOO store FOO in the foo list for later1180 fooing1181 -h, --help show this help message and exit1182"""1183class TestHelp(BaseTest):1184 def setUp(self):1185 self.parser = self.make_parser(80)1186 def make_parser(self, columns):1187 options = [1188 make_option("-a", type="string", dest='a',1189 metavar="APPLE", help="throw APPLEs at basket"),1190 make_option("-b", "--boo", type="int", dest='boo',1191 metavar="NUM",1192 help=1193 "shout \"boo!\" NUM times (in order to frighten away "1194 "all the evil spirits that cause trouble and mayhem)"),1195 make_option("--foo", action="append", type="string", dest='foo',1196 help="store FOO in the foo list for later fooing"),1197 ]1198 # We need to set COLUMNS for the OptionParser constructor, but1199 # we must restore its original value -- otherwise, this test1200 # screws things up for other tests when it's part of the Python1201 # test suite.1202 with support.EnvironmentVarGuard() as env:1203 env['COLUMNS'] = str(columns)1204 return InterceptingOptionParser(option_list=options)1205 def assertHelpEquals(self, expected_output):1206 save_argv = sys.argv[:]1207 try:1208 # Make optparse believe bar.py is being executed.1209 sys.argv[0] = os.path.join("foo", "bar.py")1210 self.assertOutput(["-h"], expected_output)1211 finally:1212 sys.argv[:] = save_argv1213 def test_help(self):1214 self.assertHelpEquals(_expected_help_basic)1215 def test_help_old_usage(self):1216 self.parser.set_usage("Usage: %prog [options]")1217 self.assertHelpEquals(_expected_help_basic)1218 def test_help_long_opts_first(self):1219 self.parser.formatter.short_first = 01220 self.assertHelpEquals(_expected_help_long_opts_first)1221 def test_help_title_formatter(self):1222 with support.EnvironmentVarGuard() as env:1223 env["COLUMNS"] = "80"1224 self.parser.formatter = TitledHelpFormatter()1225 self.assertHelpEquals(_expected_help_title_formatter)1226 def test_wrap_columns(self):1227 # Ensure that wrapping respects $COLUMNS environment variable.1228 # Need to reconstruct the parser, since that's the only time1229 # we look at $COLUMNS.1230 self.parser = self.make_parser(60)1231 self.assertHelpEquals(_expected_help_short_lines)1232 def test_help_unicode(self):1233 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)1234 self.parser.add_option("-a", action="store_true", help="ol\u00E9!")1235 expect = """\1236Options:1237 -h, --help show this help message and exit1238 -a ol\u00E9!1239"""1240 self.assertHelpEquals(expect)1241 def test_help_unicode_description(self):1242 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,1243 description="ol\u00E9!")1244 expect = """\1245ol\u00E9!1246Options:1247 -h, --help show this help message and exit1248"""1249 self.assertHelpEquals(expect)1250 def test_help_description_groups(self):1251 self.parser.set_description(1252 "This is the program description for %prog. %prog has "1253 "an option group as well as single options.")1254 group = OptionGroup(1255 self.parser, "Dangerous Options",1256 "Caution: use of these options is at your own risk. "1257 "It is believed that some of them bite.")1258 group.add_option("-g", action="store_true", help="Group option.")1259 self.parser.add_option_group(group)1260 expect = """\1261Usage: bar.py [options]1262This is the program description for bar.py. bar.py has an option group as1263well as single options.1264Options:1265 -a APPLE throw APPLEs at basket1266 -b NUM, --boo=NUM shout "boo!" NUM times (in order to frighten away all the1267 evil spirits that cause trouble and mayhem)1268 --foo=FOO store FOO in the foo list for later fooing1269 -h, --help show this help message and exit1270 Dangerous Options:1271 Caution: use of these options is at your own risk. It is believed1272 that some of them bite.1273 -g Group option.1274"""1275 self.assertHelpEquals(expect)1276 self.parser.epilog = "Please report bugs to /dev/null."1277 self.assertHelpEquals(expect + "\nPlease report bugs to /dev/null.\n")1278class TestMatchAbbrev(BaseTest):1279 def test_match_abbrev(self):1280 self.assertEqual(_match_abbrev("--f",1281 {"--foz": None,1282 "--foo": None,1283 "--fie": None,1284 "--f": None}),1285 "--f")1286 def test_match_abbrev_error(self):1287 s = "--f"1288 wordmap = {"--foz": None, "--foo": None, "--fie": None}1289 self.assertRaises(1290 _match_abbrev, (s, wordmap), None,1291 BadOptionError, "ambiguous option: --f (--fie, --foo, --foz?)")1292class TestParseNumber(BaseTest):1293 def setUp(self):1294 self.parser = InterceptingOptionParser()1295 self.parser.add_option("-n", type=int)1296 self.parser.add_option("-l", type=int)1297 def test_parse_num_fail(self):1298 self.assertRaises(1299 _parse_num, ("", int), {},1300 ValueError,1301 re.compile(r"invalid literal for int().*: '?'?"))1302 self.assertRaises(1303 _parse_num, ("0xOoops", int), {},1304 ValueError,1305 re.compile(r"invalid literal for int().*: s?'?0xOoops'?"))1306 def test_parse_num_ok(self):1307 self.assertEqual(_parse_num("0", int), 0)1308 self.assertEqual(_parse_num("0x10", int), 16)1309 self.assertEqual(_parse_num("0XA", int), 10)1310 self.assertEqual(_parse_num("010", int), 8)...

Full Screen

Full Screen

optparse.py

Source:optparse.py Github

copy

Full Screen

...5(http://lists.sourceforge.net/lists/listinfo/optik-users).6Simple usage example:7 from optparse import OptionParser8 parser = OptionParser()9 parser.add_option("-f", "--file", dest="filename",10 help="write report to FILE", metavar="FILE")11 parser.add_option("-q", "--quiet",12 action="store_false", dest="verbose", default=True,13 help="don't print status messages to stdout")14 (options, args) = parser.parse_args()15"""16__version__ = "1.5.3"17__all__ = ['Option',18 'make_option',19 'SUPPRESS_HELP',20 'SUPPRESS_USAGE',21 'Values',22 'OptionContainer',23 'OptionGroup',24 'OptionParser',25 'HelpFormatter',26 'IndentedHelpFormatter',27 'TitledHelpFormatter',28 'OptParseError',29 'OptionError',30 'OptionConflictError',31 'OptionValueError',32 'BadOptionError']33__copyright__ = """34Copyright (c) 2001-2006 Gregory P. Ward. All rights reserved.35Copyright (c) 2002-2006 Python Software Foundation. All rights reserved.36Redistribution and use in source and binary forms, with or without37modification, are permitted provided that the following conditions are38met:39 * Redistributions of source code must retain the above copyright40 notice, this list of conditions and the following disclaimer.41 * Redistributions in binary form must reproduce the above copyright42 notice, this list of conditions and the following disclaimer in the43 documentation and/or other materials provided with the distribution.44 * Neither the name of the author nor the names of its45 contributors may be used to endorse or promote products derived from46 this software without specific prior written permission.47THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS48IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED49TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A50PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR51CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,52EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,53PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR54PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF55LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING56NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS57SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.58"""59import sys, os60import textwrap61def _repr(self):62 return "<%s at 0x%x: %s>" % (self.__class__.__name__, id(self), self)63# This file was generated from:64# Id: option_parser.py 527 2006-07-23 15:21:30Z greg65# Id: option.py 522 2006-06-11 16:22:03Z gward66# Id: help.py 527 2006-07-23 15:21:30Z greg67# Id: errors.py 509 2006-04-20 00:58:24Z gward68try:69 from gettext import gettext, ngettext70except ImportError:71 def gettext(message):72 return message73 def ngettext(singular, plural, n):74 if n == 1:75 return singular76 return plural77_ = gettext78class OptParseError (Exception):79 def __init__(self, msg):80 self.msg = msg81 def __str__(self):82 return self.msg83class OptionError (OptParseError):84 """85 Raised if an Option instance is created with invalid or86 inconsistent arguments.87 """88 def __init__(self, msg, option):89 self.msg = msg90 self.option_id = str(option)91 def __str__(self):92 if self.option_id:93 return "option %s: %s" % (self.option_id, self.msg)94 else:95 return self.msg96class OptionConflictError (OptionError):97 """98 Raised if conflicting options are added to an OptionParser.99 """100class OptionValueError (OptParseError):101 """102 Raised if an invalid option value is encountered on the command103 line.104 """105class BadOptionError (OptParseError):106 """107 Raised if an invalid option is seen on the command line.108 """109 def __init__(self, opt_str):110 self.opt_str = opt_str111 def __str__(self):112 return _("no such option: %s") % self.opt_str113class AmbiguousOptionError (BadOptionError):114 """115 Raised if an ambiguous option is seen on the command line.116 """117 def __init__(self, opt_str, possibilities):118 BadOptionError.__init__(self, opt_str)119 self.possibilities = possibilities120 def __str__(self):121 return (_("ambiguous option: %s (%s?)")122 % (self.opt_str, ", ".join(self.possibilities)))123class HelpFormatter:124 """125 Abstract base class for formatting option help. OptionParser126 instances should use one of the HelpFormatter subclasses for127 formatting help; by default IndentedHelpFormatter is used.128 Instance attributes:129 parser : OptionParser130 the controlling OptionParser instance131 indent_increment : int132 the number of columns to indent per nesting level133 max_help_position : int134 the maximum starting column for option help text135 help_position : int136 the calculated starting column for option help text;137 initially the same as the maximum138 width : int139 total number of columns for output (pass None to constructor for140 this value to be taken from the $COLUMNS environment variable)141 level : int142 current indentation level143 current_indent : int144 current indentation level (in columns)145 help_width : int146 number of columns available for option help text (calculated)147 default_tag : str148 text to replace with each option's default value, "%default"149 by default. Set to false value to disable default value expansion.150 option_strings : { Option : str }151 maps Option instances to the snippet of help text explaining152 the syntax of that option, e.g. "-h, --help" or153 "-fFILE, --file=FILE"154 _short_opt_fmt : str155 format string controlling how short options with values are156 printed in help text. Must be either "%s%s" ("-fFILE") or157 "%s %s" ("-f FILE"), because those are the two syntaxes that158 Optik supports.159 _long_opt_fmt : str160 similar but for long options; must be either "%s %s" ("--file FILE")161 or "%s=%s" ("--file=FILE").162 """163 NO_DEFAULT_VALUE = "none"164 def __init__(self,165 indent_increment,166 max_help_position,167 width,168 short_first):169 self.parser = None170 self.indent_increment = indent_increment171 self.help_position = self.max_help_position = max_help_position172 if width is None:173 try:174 width = int(os.environ['COLUMNS'])175 except (KeyError, ValueError):176 width = 80177 width -= 2178 self.width = width179 self.current_indent = 0180 self.level = 0181 self.help_width = None # computed later182 self.short_first = short_first183 self.default_tag = "%default"184 self.option_strings = {}185 self._short_opt_fmt = "%s %s"186 self._long_opt_fmt = "%s=%s"187 def set_parser(self, parser):188 self.parser = parser189 def set_short_opt_delimiter(self, delim):190 if delim not in ("", " "):191 raise ValueError(192 "invalid metavar delimiter for short options: %r" % delim)193 self._short_opt_fmt = "%s" + delim + "%s"194 def set_long_opt_delimiter(self, delim):195 if delim not in ("=", " "):196 raise ValueError(197 "invalid metavar delimiter for long options: %r" % delim)198 self._long_opt_fmt = "%s" + delim + "%s"199 def indent(self):200 self.current_indent += self.indent_increment201 self.level += 1202 def dedent(self):203 self.current_indent -= self.indent_increment204 assert self.current_indent >= 0, "Indent decreased below 0."205 self.level -= 1206 def format_usage(self, usage):207 raise NotImplementedError("subclasses must implement")208 def format_heading(self, heading):209 raise NotImplementedError("subclasses must implement")210 def _format_text(self, text):211 """212 Format a paragraph of free-form text for inclusion in the213 help output at the current indentation level.214 """215 text_width = self.width - self.current_indent216 indent = " "*self.current_indent217 return textwrap.fill(text,218 text_width,219 initial_indent=indent,220 subsequent_indent=indent)221 def format_description(self, description):222 if description:223 return self._format_text(description) + "\n"224 else:225 return ""226 def format_epilog(self, epilog):227 if epilog:228 return "\n" + self._format_text(epilog) + "\n"229 else:230 return ""231 def expand_default(self, option):232 if self.parser is None or not self.default_tag:233 return option.help234 default_value = self.parser.defaults.get(option.dest)235 if default_value is NO_DEFAULT or default_value is None:236 default_value = self.NO_DEFAULT_VALUE237 return option.help.replace(self.default_tag, str(default_value))238 def format_option(self, option):239 # The help for each option consists of two parts:240 # * the opt strings and metavars241 # eg. ("-x", or "-fFILENAME, --file=FILENAME")242 # * the user-supplied help string243 # eg. ("turn on expert mode", "read data from FILENAME")244 #245 # If possible, we write both of these on the same line:246 # -x turn on expert mode247 #248 # But if the opt string list is too long, we put the help249 # string on a second line, indented to the same column it would250 # start in if it fit on the first line.251 # -fFILENAME, --file=FILENAME252 # read data from FILENAME253 result = []254 opts = self.option_strings[option]255 opt_width = self.help_position - self.current_indent - 2256 if len(opts) > opt_width:257 opts = "%*s%s\n" % (self.current_indent, "", opts)258 indent_first = self.help_position259 else: # start help on same line as opts260 opts = "%*s%-*s " % (self.current_indent, "", opt_width, opts)261 indent_first = 0262 result.append(opts)263 if option.help:264 help_text = self.expand_default(option)265 help_lines = textwrap.wrap(help_text, self.help_width)266 result.append("%*s%s\n" % (indent_first, "", help_lines[0]))267 result.extend(["%*s%s\n" % (self.help_position, "", line)268 for line in help_lines[1:]])269 elif opts[-1] != "\n":270 result.append("\n")271 return "".join(result)272 def store_option_strings(self, parser):273 self.indent()274 max_len = 0275 for opt in parser.option_list:276 strings = self.format_option_strings(opt)277 self.option_strings[opt] = strings278 max_len = max(max_len, len(strings) + self.current_indent)279 self.indent()280 for group in parser.option_groups:281 for opt in group.option_list:282 strings = self.format_option_strings(opt)283 self.option_strings[opt] = strings284 max_len = max(max_len, len(strings) + self.current_indent)285 self.dedent()286 self.dedent()287 self.help_position = min(max_len + 2, self.max_help_position)288 self.help_width = self.width - self.help_position289 def format_option_strings(self, option):290 """Return a comma-separated list of option strings & metavariables."""291 if option.takes_value():292 metavar = option.metavar or option.dest.upper()293 short_opts = [self._short_opt_fmt % (sopt, metavar)294 for sopt in option._short_opts]295 long_opts = [self._long_opt_fmt % (lopt, metavar)296 for lopt in option._long_opts]297 else:298 short_opts = option._short_opts299 long_opts = option._long_opts300 if self.short_first:301 opts = short_opts + long_opts302 else:303 opts = long_opts + short_opts304 return ", ".join(opts)305class IndentedHelpFormatter (HelpFormatter):306 """Format help with indented section bodies.307 """308 def __init__(self,309 indent_increment=2,310 max_help_position=24,311 width=None,312 short_first=1):313 HelpFormatter.__init__(314 self, indent_increment, max_help_position, width, short_first)315 def format_usage(self, usage):316 return _("Usage: %s\n") % usage317 def format_heading(self, heading):318 return "%*s%s:\n" % (self.current_indent, "", heading)319class TitledHelpFormatter (HelpFormatter):320 """Format help with underlined section headers.321 """322 def __init__(self,323 indent_increment=0,324 max_help_position=24,325 width=None,326 short_first=0):327 HelpFormatter.__init__ (328 self, indent_increment, max_help_position, width, short_first)329 def format_usage(self, usage):330 return "%s %s\n" % (self.format_heading(_("Usage")), usage)331 def format_heading(self, heading):332 return "%s\n%s\n" % (heading, "=-"[self.level] * len(heading))333def _parse_num(val, type):334 if val[:2].lower() == "0x": # hexadecimal335 radix = 16336 elif val[:2].lower() == "0b": # binary337 radix = 2338 val = val[2:] or "0" # have to remove "0b" prefix339 elif val[:1] == "0": # octal340 radix = 8341 else: # decimal342 radix = 10343 return type(val, radix)344def _parse_int(val):345 return _parse_num(val, int)346_builtin_cvt = { "int" : (_parse_int, _("integer")),347 "long" : (_parse_int, _("integer")),348 "float" : (float, _("floating-point")),349 "complex" : (complex, _("complex")) }350def check_builtin(option, opt, value):351 (cvt, what) = _builtin_cvt[option.type]352 try:353 return cvt(value)354 except ValueError:355 raise OptionValueError(356 _("option %s: invalid %s value: %r") % (opt, what, value))357def check_choice(option, opt, value):358 if value in option.choices:359 return value360 else:361 choices = ", ".join(map(repr, option.choices))362 raise OptionValueError(363 _("option %s: invalid choice: %r (choose from %s)")364 % (opt, value, choices))365# Not supplying a default is different from a default of None,366# so we need an explicit "not supplied" value.367NO_DEFAULT = ("NO", "DEFAULT")368class Option:369 """370 Instance attributes:371 _short_opts : [string]372 _long_opts : [string]373 action : string374 type : string375 dest : string376 default : any377 nargs : int378 const : any379 choices : [string]380 callback : function381 callback_args : (any*)382 callback_kwargs : { string : any }383 help : string384 metavar : string385 """386 # The list of instance attributes that may be set through387 # keyword args to the constructor.388 ATTRS = ['action',389 'type',390 'dest',391 'default',392 'nargs',393 'const',394 'choices',395 'callback',396 'callback_args',397 'callback_kwargs',398 'help',399 'metavar']400 # The set of actions allowed by option parsers. Explicitly listed401 # here so the constructor can validate its arguments.402 ACTIONS = ("store",403 "store_const",404 "store_true",405 "store_false",406 "append",407 "append_const",408 "count",409 "callback",410 "help",411 "version")412 # The set of actions that involve storing a value somewhere;413 # also listed just for constructor argument validation. (If414 # the action is one of these, there must be a destination.)415 STORE_ACTIONS = ("store",416 "store_const",417 "store_true",418 "store_false",419 "append",420 "append_const",421 "count")422 # The set of actions for which it makes sense to supply a value423 # type, ie. which may consume an argument from the command line.424 TYPED_ACTIONS = ("store",425 "append",426 "callback")427 # The set of actions which *require* a value type, ie. that428 # always consume an argument from the command line.429 ALWAYS_TYPED_ACTIONS = ("store",430 "append")431 # The set of actions which take a 'const' attribute.432 CONST_ACTIONS = ("store_const",433 "append_const")434 # The set of known types for option parsers. Again, listed here for435 # constructor argument validation.436 TYPES = ("string", "int", "long", "float", "complex", "choice")437 # Dictionary of argument checking functions, which convert and438 # validate option arguments according to the option type.439 #440 # Signature of checking functions is:441 # check(option : Option, opt : string, value : string) -> any442 # where443 # option is the Option instance calling the checker444 # opt is the actual option seen on the command-line445 # (eg. "-a", "--file")446 # value is the option argument seen on the command-line447 #448 # The return value should be in the appropriate Python type449 # for option.type -- eg. an integer if option.type == "int".450 #451 # If no checker is defined for a type, arguments will be452 # unchecked and remain strings.453 TYPE_CHECKER = { "int" : check_builtin,454 "long" : check_builtin,455 "float" : check_builtin,456 "complex": check_builtin,457 "choice" : check_choice,458 }459 # CHECK_METHODS is a list of unbound method objects; they are called460 # by the constructor, in order, after all attributes are461 # initialized. The list is created and filled in later, after all462 # the methods are actually defined. (I just put it here because I463 # like to define and document all class attributes in the same464 # place.) Subclasses that add another _check_*() method should465 # define their own CHECK_METHODS list that adds their check method466 # to those from this class.467 CHECK_METHODS = None468 # -- Constructor/initialization methods ----------------------------469 def __init__(self, *opts, **attrs):470 # Set _short_opts, _long_opts attrs from 'opts' tuple.471 # Have to be set now, in case no option strings are supplied.472 self._short_opts = []473 self._long_opts = []474 opts = self._check_opt_strings(opts)475 self._set_opt_strings(opts)476 # Set all other attrs (action, type, etc.) from 'attrs' dict477 self._set_attrs(attrs)478 # Check all the attributes we just set. There are lots of479 # complicated interdependencies, but luckily they can be farmed480 # out to the _check_*() methods listed in CHECK_METHODS -- which481 # could be handy for subclasses! The one thing these all share482 # is that they raise OptionError if they discover a problem.483 for checker in self.CHECK_METHODS:484 checker(self)485 def _check_opt_strings(self, opts):486 # Filter out None because early versions of Optik had exactly487 # one short option and one long option, either of which488 # could be None.489 opts = [opt for opt in opts if opt]490 if not opts:491 raise TypeError("at least one option string must be supplied")492 return opts493 def _set_opt_strings(self, opts):494 for opt in opts:495 if len(opt) < 2:496 raise OptionError(497 "invalid option string %r: "498 "must be at least two characters long" % opt, self)499 elif len(opt) == 2:500 if not (opt[0] == "-" and opt[1] != "-"):501 raise OptionError(502 "invalid short option string %r: "503 "must be of the form -x, (x any non-dash char)" % opt,504 self)505 self._short_opts.append(opt)506 else:507 if not (opt[0:2] == "--" and opt[2] != "-"):508 raise OptionError(509 "invalid long option string %r: "510 "must start with --, followed by non-dash" % opt,511 self)512 self._long_opts.append(opt)513 def _set_attrs(self, attrs):514 for attr in self.ATTRS:515 if attr in attrs:516 setattr(self, attr, attrs[attr])517 del attrs[attr]518 else:519 if attr == 'default':520 setattr(self, attr, NO_DEFAULT)521 else:522 setattr(self, attr, None)523 if attrs:524 attrs = sorted(attrs.keys())525 raise OptionError(526 "invalid keyword arguments: %s" % ", ".join(attrs),527 self)528 # -- Constructor validation methods --------------------------------529 def _check_action(self):530 if self.action is None:531 self.action = "store"532 elif self.action not in self.ACTIONS:533 raise OptionError("invalid action: %r" % self.action, self)534 def _check_type(self):535 if self.type is None:536 if self.action in self.ALWAYS_TYPED_ACTIONS:537 if self.choices is not None:538 # The "choices" attribute implies "choice" type.539 self.type = "choice"540 else:541 # No type given? "string" is the most sensible default.542 self.type = "string"543 else:544 # Allow type objects or builtin type conversion functions545 # (int, str, etc.) as an alternative to their names. (The546 # complicated check of builtins is only necessary for547 # Python 2.1 and earlier, and is short-circuited by the548 # first check on modern Pythons.)549 import builtins550 if ( isinstance(self.type, type) or551 (hasattr(self.type, "__name__") and552 getattr(builtins, self.type.__name__, None) is self.type) ):553 self.type = self.type.__name__554 if self.type == "str":555 self.type = "string"556 if self.type not in self.TYPES:557 raise OptionError("invalid option type: %r" % self.type, self)558 if self.action not in self.TYPED_ACTIONS:559 raise OptionError(560 "must not supply a type for action %r" % self.action, self)561 def _check_choice(self):562 if self.type == "choice":563 if self.choices is None:564 raise OptionError(565 "must supply a list of choices for type 'choice'", self)566 elif not isinstance(self.choices, (tuple, list)):567 raise OptionError(568 "choices must be a list of strings ('%s' supplied)"569 % str(type(self.choices)).split("'")[1], self)570 elif self.choices is not None:571 raise OptionError(572 "must not supply choices for type %r" % self.type, self)573 def _check_dest(self):574 # No destination given, and we need one for this action. The575 # self.type check is for callbacks that take a value.576 takes_value = (self.action in self.STORE_ACTIONS or577 self.type is not None)578 if self.dest is None and takes_value:579 # Glean a destination from the first long option string,580 # or from the first short option string if no long options.581 if self._long_opts:582 # eg. "--foo-bar" -> "foo_bar"583 self.dest = self._long_opts[0][2:].replace('-', '_')584 else:585 self.dest = self._short_opts[0][1]586 def _check_const(self):587 if self.action not in self.CONST_ACTIONS and self.const is not None:588 raise OptionError(589 "'const' must not be supplied for action %r" % self.action,590 self)591 def _check_nargs(self):592 if self.action in self.TYPED_ACTIONS:593 if self.nargs is None:594 self.nargs = 1595 elif self.nargs is not None:596 raise OptionError(597 "'nargs' must not be supplied for action %r" % self.action,598 self)599 def _check_callback(self):600 if self.action == "callback":601 if not callable(self.callback):602 raise OptionError(603 "callback not callable: %r" % self.callback, self)604 if (self.callback_args is not None and605 not isinstance(self.callback_args, tuple)):606 raise OptionError(607 "callback_args, if supplied, must be a tuple: not %r"608 % self.callback_args, self)609 if (self.callback_kwargs is not None and610 not isinstance(self.callback_kwargs, dict)):611 raise OptionError(612 "callback_kwargs, if supplied, must be a dict: not %r"613 % self.callback_kwargs, self)614 else:615 if self.callback is not None:616 raise OptionError(617 "callback supplied (%r) for non-callback option"618 % self.callback, self)619 if self.callback_args is not None:620 raise OptionError(621 "callback_args supplied for non-callback option", self)622 if self.callback_kwargs is not None:623 raise OptionError(624 "callback_kwargs supplied for non-callback option", self)625 CHECK_METHODS = [_check_action,626 _check_type,627 _check_choice,628 _check_dest,629 _check_const,630 _check_nargs,631 _check_callback]632 # -- Miscellaneous methods -----------------------------------------633 def __str__(self):634 return "/".join(self._short_opts + self._long_opts)635 __repr__ = _repr636 def takes_value(self):637 return self.type is not None638 def get_opt_string(self):639 if self._long_opts:640 return self._long_opts[0]641 else:642 return self._short_opts[0]643 # -- Processing methods --------------------------------------------644 def check_value(self, opt, value):645 checker = self.TYPE_CHECKER.get(self.type)646 if checker is None:647 return value648 else:649 return checker(self, opt, value)650 def convert_value(self, opt, value):651 if value is not None:652 if self.nargs == 1:653 return self.check_value(opt, value)654 else:655 return tuple([self.check_value(opt, v) for v in value])656 def process(self, opt, value, values, parser):657 # First, convert the value(s) to the right type. Howl if any658 # value(s) are bogus.659 value = self.convert_value(opt, value)660 # And then take whatever action is expected of us.661 # This is a separate method to make life easier for662 # subclasses to add new actions.663 return self.take_action(664 self.action, self.dest, opt, value, values, parser)665 def take_action(self, action, dest, opt, value, values, parser):666 if action == "store":667 setattr(values, dest, value)668 elif action == "store_const":669 setattr(values, dest, self.const)670 elif action == "store_true":671 setattr(values, dest, True)672 elif action == "store_false":673 setattr(values, dest, False)674 elif action == "append":675 values.ensure_value(dest, []).append(value)676 elif action == "append_const":677 values.ensure_value(dest, []).append(self.const)678 elif action == "count":679 setattr(values, dest, values.ensure_value(dest, 0) + 1)680 elif action == "callback":681 args = self.callback_args or ()682 kwargs = self.callback_kwargs or {}683 self.callback(self, opt, value, parser, *args, **kwargs)684 elif action == "help":685 parser.print_help()686 parser.exit()687 elif action == "version":688 parser.print_version()689 parser.exit()690 else:691 raise ValueError("unknown action %r" % self.action)692 return 1693# class Option694SUPPRESS_HELP = "SUPPRESS"+"HELP"695SUPPRESS_USAGE = "SUPPRESS"+"USAGE"696class Values:697 def __init__(self, defaults=None):698 if defaults:699 for (attr, val) in defaults.items():700 setattr(self, attr, val)701 def __str__(self):702 return str(self.__dict__)703 __repr__ = _repr704 def __eq__(self, other):705 if isinstance(other, Values):706 return self.__dict__ == other.__dict__707 elif isinstance(other, dict):708 return self.__dict__ == other709 else:710 return NotImplemented711 def _update_careful(self, dict):712 """713 Update the option values from an arbitrary dictionary, but only714 use keys from dict that already have a corresponding attribute715 in self. Any keys in dict without a corresponding attribute716 are silently ignored.717 """718 for attr in dir(self):719 if attr in dict:720 dval = dict[attr]721 if dval is not None:722 setattr(self, attr, dval)723 def _update_loose(self, dict):724 """725 Update the option values from an arbitrary dictionary,726 using all keys from the dictionary regardless of whether727 they have a corresponding attribute in self or not.728 """729 self.__dict__.update(dict)730 def _update(self, dict, mode):731 if mode == "careful":732 self._update_careful(dict)733 elif mode == "loose":734 self._update_loose(dict)735 else:736 raise ValueError("invalid update mode: %r" % mode)737 def read_module(self, modname, mode="careful"):738 __import__(modname)739 mod = sys.modules[modname]740 self._update(vars(mod), mode)741 def read_file(self, filename, mode="careful"):742 vars = {}743 exec(open(filename).read(), vars)744 self._update(vars, mode)745 def ensure_value(self, attr, value):746 if not hasattr(self, attr) or getattr(self, attr) is None:747 setattr(self, attr, value)748 return getattr(self, attr)749class OptionContainer:750 """751 Abstract base class.752 Class attributes:753 standard_option_list : [Option]754 list of standard options that will be accepted by all instances755 of this parser class (intended to be overridden by subclasses).756 Instance attributes:757 option_list : [Option]758 the list of Option objects contained by this OptionContainer759 _short_opt : { string : Option }760 dictionary mapping short option strings, eg. "-f" or "-X",761 to the Option instances that implement them. If an Option762 has multiple short option strings, it will appears in this763 dictionary multiple times. [1]764 _long_opt : { string : Option }765 dictionary mapping long option strings, eg. "--file" or766 "--exclude", to the Option instances that implement them.767 Again, a given Option can occur multiple times in this768 dictionary. [1]769 defaults : { string : any }770 dictionary mapping option destination names to default771 values for each destination [1]772 [1] These mappings are common to (shared by) all components of the773 controlling OptionParser, where they are initially created.774 """775 def __init__(self, option_class, conflict_handler, description):776 # Initialize the option list and related data structures.777 # This method must be provided by subclasses, and it must778 # initialize at least the following instance attributes:779 # option_list, _short_opt, _long_opt, defaults.780 self._create_option_list()781 self.option_class = option_class782 self.set_conflict_handler(conflict_handler)783 self.set_description(description)784 def _create_option_mappings(self):785 # For use by OptionParser constructor -- create the master786 # option mappings used by this OptionParser and all787 # OptionGroups that it owns.788 self._short_opt = {} # single letter -> Option instance789 self._long_opt = {} # long option -> Option instance790 self.defaults = {} # maps option dest -> default value791 def _share_option_mappings(self, parser):792 # For use by OptionGroup constructor -- use shared option793 # mappings from the OptionParser that owns this OptionGroup.794 self._short_opt = parser._short_opt795 self._long_opt = parser._long_opt796 self.defaults = parser.defaults797 def set_conflict_handler(self, handler):798 if handler not in ("error", "resolve"):799 raise ValueError("invalid conflict_resolution value %r" % handler)800 self.conflict_handler = handler801 def set_description(self, description):802 self.description = description803 def get_description(self):804 return self.description805 def destroy(self):806 """see OptionParser.destroy()."""807 del self._short_opt808 del self._long_opt809 del self.defaults810 # -- Option-adding methods -----------------------------------------811 def _check_conflict(self, option):812 conflict_opts = []813 for opt in option._short_opts:814 if opt in self._short_opt:815 conflict_opts.append((opt, self._short_opt[opt]))816 for opt in option._long_opts:817 if opt in self._long_opt:818 conflict_opts.append((opt, self._long_opt[opt]))819 if conflict_opts:820 handler = self.conflict_handler821 if handler == "error":822 raise OptionConflictError(823 "conflicting option string(s): %s"824 % ", ".join([co[0] for co in conflict_opts]),825 option)826 elif handler == "resolve":827 for (opt, c_option) in conflict_opts:828 if opt.startswith("--"):829 c_option._long_opts.remove(opt)830 del self._long_opt[opt]831 else:832 c_option._short_opts.remove(opt)833 del self._short_opt[opt]834 if not (c_option._short_opts or c_option._long_opts):835 c_option.container.option_list.remove(c_option)836 def add_option(self, *args, **kwargs):837 """add_option(Option)838 add_option(opt_str, ..., kwarg=val, ...)839 """840 if isinstance(args[0], str):841 option = self.option_class(*args, **kwargs)842 elif len(args) == 1 and not kwargs:843 option = args[0]844 if not isinstance(option, Option):845 raise TypeError("not an Option instance: %r" % option)846 else:847 raise TypeError("invalid arguments")848 self._check_conflict(option)849 self.option_list.append(option)850 option.container = self851 for opt in option._short_opts:852 self._short_opt[opt] = option853 for opt in option._long_opts:854 self._long_opt[opt] = option855 if option.dest is not None: # option has a dest, we need a default856 if option.default is not NO_DEFAULT:857 self.defaults[option.dest] = option.default858 elif option.dest not in self.defaults:859 self.defaults[option.dest] = None860 return option861 def add_options(self, option_list):862 for option in option_list:863 self.add_option(option)864 # -- Option query/removal methods ----------------------------------865 def get_option(self, opt_str):866 return (self._short_opt.get(opt_str) or867 self._long_opt.get(opt_str))868 def has_option(self, opt_str):869 return (opt_str in self._short_opt or870 opt_str in self._long_opt)871 def remove_option(self, opt_str):872 option = self._short_opt.get(opt_str)873 if option is None:874 option = self._long_opt.get(opt_str)875 if option is None:876 raise ValueError("no such option %r" % opt_str)877 for opt in option._short_opts:878 del self._short_opt[opt]879 for opt in option._long_opts:880 del self._long_opt[opt]881 option.container.option_list.remove(option)882 # -- Help-formatting methods ---------------------------------------883 def format_option_help(self, formatter):884 if not self.option_list:885 return ""886 result = []887 for option in self.option_list:888 if not option.help is SUPPRESS_HELP:889 result.append(formatter.format_option(option))890 return "".join(result)891 def format_description(self, formatter):892 return formatter.format_description(self.get_description())893 def format_help(self, formatter):894 result = []895 if self.description:896 result.append(self.format_description(formatter))897 if self.option_list:898 result.append(self.format_option_help(formatter))899 return "\n".join(result)900class OptionGroup (OptionContainer):901 def __init__(self, parser, title, description=None):902 self.parser = parser903 OptionContainer.__init__(904 self, parser.option_class, parser.conflict_handler, description)905 self.title = title906 def _create_option_list(self):907 self.option_list = []908 self._share_option_mappings(self.parser)909 def set_title(self, title):910 self.title = title911 def destroy(self):912 """see OptionParser.destroy()."""913 OptionContainer.destroy(self)914 del self.option_list915 # -- Help-formatting methods ---------------------------------------916 def format_help(self, formatter):917 result = formatter.format_heading(self.title)918 formatter.indent()919 result += OptionContainer.format_help(self, formatter)920 formatter.dedent()921 return result922class OptionParser (OptionContainer):923 """924 Class attributes:925 standard_option_list : [Option]926 list of standard options that will be accepted by all instances927 of this parser class (intended to be overridden by subclasses).928 Instance attributes:929 usage : string930 a usage string for your program. Before it is displayed931 to the user, "%prog" will be expanded to the name of932 your program (self.prog or os.path.basename(sys.argv[0])).933 prog : string934 the name of the current program (to override935 os.path.basename(sys.argv[0])).936 description : string937 A paragraph of text giving a brief overview of your program.938 optparse reformats this paragraph to fit the current terminal939 width and prints it when the user requests help (after usage,940 but before the list of options).941 epilog : string942 paragraph of help text to print after option help943 option_groups : [OptionGroup]944 list of option groups in this parser (option groups are945 irrelevant for parsing the command-line, but very useful946 for generating help)947 allow_interspersed_args : bool = true948 if true, positional arguments may be interspersed with options.949 Assuming -a and -b each take a single argument, the command-line950 -ablah foo bar -bboo baz951 will be interpreted the same as952 -ablah -bboo -- foo bar baz953 If this flag were false, that command line would be interpreted as954 -ablah -- foo bar -bboo baz955 -- ie. we stop processing options as soon as we see the first956 non-option argument. (This is the tradition followed by957 Python's getopt module, Perl's Getopt::Std, and other argument-958 parsing libraries, but it is generally annoying to users.)959 process_default_values : bool = true960 if true, option default values are processed similarly to option961 values from the command line: that is, they are passed to the962 type-checking function for the option's type (as long as the963 default value is a string). (This really only matters if you964 have defined custom types; see SF bug #955889.) Set it to false965 to restore the behaviour of Optik 1.4.1 and earlier.966 rargs : [string]967 the argument list currently being parsed. Only set when968 parse_args() is active, and continually trimmed down as969 we consume arguments. Mainly there for the benefit of970 callback options.971 largs : [string]972 the list of leftover arguments that we have skipped while973 parsing options. If allow_interspersed_args is false, this974 list is always empty.975 values : Values976 the set of option values currently being accumulated. Only977 set when parse_args() is active. Also mainly for callbacks.978 Because of the 'rargs', 'largs', and 'values' attributes,979 OptionParser is not thread-safe. If, for some perverse reason, you980 need to parse command-line arguments simultaneously in different981 threads, use different OptionParser instances.982 """983 standard_option_list = []984 def __init__(self,985 usage=None,986 option_list=None,987 option_class=Option,988 version=None,989 conflict_handler="error",990 description=None,991 formatter=None,992 add_help_option=True,993 prog=None,994 epilog=None):995 OptionContainer.__init__(996 self, option_class, conflict_handler, description)997 self.set_usage(usage)998 self.prog = prog999 self.version = version1000 self.allow_interspersed_args = True1001 self.process_default_values = True1002 if formatter is None:1003 formatter = IndentedHelpFormatter()1004 self.formatter = formatter1005 self.formatter.set_parser(self)1006 self.epilog = epilog1007 # Populate the option list; initial sources are the1008 # standard_option_list class attribute, the 'option_list'1009 # argument, and (if applicable) the _add_version_option() and1010 # _add_help_option() methods.1011 self._populate_option_list(option_list,1012 add_help=add_help_option)1013 self._init_parsing_state()1014 def destroy(self):1015 """1016 Declare that you are done with this OptionParser. This cleans up1017 reference cycles so the OptionParser (and all objects referenced by1018 it) can be garbage-collected promptly. After calling destroy(), the1019 OptionParser is unusable.1020 """1021 OptionContainer.destroy(self)1022 for group in self.option_groups:1023 group.destroy()1024 del self.option_list1025 del self.option_groups1026 del self.formatter1027 # -- Private methods -----------------------------------------------1028 # (used by our or OptionContainer's constructor)1029 def _create_option_list(self):1030 self.option_list = []1031 self.option_groups = []1032 self._create_option_mappings()1033 def _add_help_option(self):1034 self.add_option("-h", "--help",1035 action="help",1036 help=_("show this help message and exit"))1037 def _add_version_option(self):1038 self.add_option("--version",1039 action="version",1040 help=_("show program's version number and exit"))1041 def _populate_option_list(self, option_list, add_help=True):1042 if self.standard_option_list:1043 self.add_options(self.standard_option_list)1044 if option_list:1045 self.add_options(option_list)1046 if self.version:1047 self._add_version_option()1048 if add_help:1049 self._add_help_option()1050 def _init_parsing_state(self):1051 # These are set in parse_args() for the convenience of callbacks.1052 self.rargs = None1053 self.largs = None1054 self.values = None1055 # -- Simple modifier methods ---------------------------------------1056 def set_usage(self, usage):1057 if usage is None:1058 self.usage = _("%prog [options]")1059 elif usage is SUPPRESS_USAGE:1060 self.usage = None1061 # For backwards compatibility with Optik 1.3 and earlier.1062 elif usage.lower().startswith("usage: "):1063 self.usage = usage[7:]1064 else:1065 self.usage = usage1066 def enable_interspersed_args(self):1067 """Set parsing to not stop on the first non-option, allowing1068 interspersing switches with command arguments. This is the1069 default behavior. See also disable_interspersed_args() and the1070 class documentation description of the attribute1071 allow_interspersed_args."""1072 self.allow_interspersed_args = True1073 def disable_interspersed_args(self):1074 """Set parsing to stop on the first non-option. Use this if1075 you have a command processor which runs another command that1076 has options of its own and you want to make sure these options1077 don't get confused.1078 """1079 self.allow_interspersed_args = False1080 def set_process_default_values(self, process):1081 self.process_default_values = process1082 def set_default(self, dest, value):1083 self.defaults[dest] = value1084 def set_defaults(self, **kwargs):1085 self.defaults.update(kwargs)1086 def _get_all_options(self):1087 options = self.option_list[:]1088 for group in self.option_groups:1089 options.extend(group.option_list)1090 return options1091 def get_default_values(self):1092 if not self.process_default_values:1093 # Old, pre-Optik 1.5 behaviour.1094 return Values(self.defaults)1095 defaults = self.defaults.copy()1096 for option in self._get_all_options():1097 default = defaults.get(option.dest)1098 if isinstance(default, str):1099 opt_str = option.get_opt_string()1100 defaults[option.dest] = option.check_value(opt_str, default)1101 return Values(defaults)1102 # -- OptionGroup methods -------------------------------------------1103 def add_option_group(self, *args, **kwargs):1104 # XXX lots of overlap with OptionContainer.add_option()1105 if isinstance(args[0], str):1106 group = OptionGroup(self, *args, **kwargs)1107 elif len(args) == 1 and not kwargs:1108 group = args[0]1109 if not isinstance(group, OptionGroup):1110 raise TypeError("not an OptionGroup instance: %r" % group)1111 if group.parser is not self:1112 raise ValueError("invalid OptionGroup (wrong parser)")1113 else:1114 raise TypeError("invalid arguments")1115 self.option_groups.append(group)1116 return group1117 def get_option_group(self, opt_str):1118 option = (self._short_opt.get(opt_str) or1119 self._long_opt.get(opt_str))1120 if option and option.container is not self:1121 return option.container1122 return None1123 # -- Option-parsing methods ----------------------------------------1124 def _get_args(self, args):1125 if args is None:1126 return sys.argv[1:]1127 else:1128 return args[:] # don't modify caller's list1129 def parse_args(self, args=None, values=None):1130 """1131 parse_args(args : [string] = sys.argv[1:],1132 values : Values = None)1133 -> (values : Values, args : [string])1134 Parse the command-line options found in 'args' (default:1135 sys.argv[1:]). Any errors result in a call to 'error()', which1136 by default prints the usage message to stderr and calls1137 sys.exit() with an error message. On success returns a pair1138 (values, args) where 'values' is an Values instance (with all1139 your option values) and 'args' is the list of arguments left1140 over after parsing options.1141 """1142 rargs = self._get_args(args)1143 if values is None:1144 values = self.get_default_values()1145 # Store the halves of the argument list as attributes for the1146 # convenience of callbacks:1147 # rargs1148 # the rest of the command-line (the "r" stands for1149 # "remaining" or "right-hand")1150 # largs1151 # the leftover arguments -- ie. what's left after removing1152 # options and their arguments (the "l" stands for "leftover"1153 # or "left-hand")1154 self.rargs = rargs1155 self.largs = largs = []1156 self.values = values1157 try:1158 stop = self._process_args(largs, rargs, values)1159 except (BadOptionError, OptionValueError) as err:1160 self.error(str(err))1161 args = largs + rargs1162 return self.check_values(values, args)1163 def check_values(self, values, args):1164 """1165 check_values(values : Values, args : [string])1166 -> (values : Values, args : [string])1167 Check that the supplied option values and leftover arguments are1168 valid. Returns the option values and leftover arguments1169 (possibly adjusted, possibly completely new -- whatever you1170 like). Default implementation just returns the passed-in1171 values; subclasses may override as desired.1172 """1173 return (values, args)1174 def _process_args(self, largs, rargs, values):1175 """_process_args(largs : [string],1176 rargs : [string],1177 values : Values)1178 Process command-line arguments and populate 'values', consuming1179 options and arguments from 'rargs'. If 'allow_interspersed_args' is1180 false, stop at the first non-option argument. If true, accumulate any1181 interspersed non-option arguments in 'largs'.1182 """1183 while rargs:1184 arg = rargs[0]1185 # We handle bare "--" explicitly, and bare "-" is handled by the1186 # standard arg handler since the short arg case ensures that the1187 # len of the opt string is greater than 1.1188 if arg == "--":1189 del rargs[0]1190 return1191 elif arg[0:2] == "--":1192 # process a single long option (possibly with value(s))1193 self._process_long_opt(rargs, values)1194 elif arg[:1] == "-" and len(arg) > 1:1195 # process a cluster of short options (possibly with1196 # value(s) for the last one only)1197 self._process_short_opts(rargs, values)1198 elif self.allow_interspersed_args:1199 largs.append(arg)1200 del rargs[0]1201 else:1202 return # stop now, leave this arg in rargs1203 # Say this is the original argument list:1204 # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)]1205 # ^1206 # (we are about to process arg(i)).1207 #1208 # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of1209 # [arg0, ..., arg(i-1)] (any options and their arguments will have1210 # been removed from largs).1211 #1212 # The while loop will usually consume 1 or more arguments per pass.1213 # If it consumes 1 (eg. arg is an option that takes no arguments),1214 # then after _process_arg() is done the situation is:1215 #1216 # largs = subset of [arg0, ..., arg(i)]1217 # rargs = [arg(i+1), ..., arg(N-1)]1218 #1219 # If allow_interspersed_args is false, largs will always be1220 # *empty* -- still a subset of [arg0, ..., arg(i-1)], but1221 # not a very interesting subset!1222 def _match_long_opt(self, opt):1223 """_match_long_opt(opt : string) -> string1224 Determine which long option string 'opt' matches, ie. which one1225 it is an unambiguous abbreviation for. Raises BadOptionError if1226 'opt' doesn't unambiguously match any long option string.1227 """1228 return _match_abbrev(opt, self._long_opt)1229 def _process_long_opt(self, rargs, values):1230 arg = rargs.pop(0)1231 # Value explicitly attached to arg? Pretend it's the next1232 # argument.1233 if "=" in arg:1234 (opt, next_arg) = arg.split("=", 1)1235 rargs.insert(0, next_arg)1236 had_explicit_value = True1237 else:1238 opt = arg1239 had_explicit_value = False1240 opt = self._match_long_opt(opt)1241 option = self._long_opt[opt]1242 if option.takes_value():1243 nargs = option.nargs1244 if len(rargs) < nargs:1245 self.error(ngettext(1246 "%(option)s option requires %(number)d argument",1247 "%(option)s option requires %(number)d arguments",1248 nargs) % {"option": opt, "number": nargs})1249 elif nargs == 1:1250 value = rargs.pop(0)1251 else:1252 value = tuple(rargs[0:nargs])1253 del rargs[0:nargs]1254 elif had_explicit_value:1255 self.error(_("%s option does not take a value") % opt)1256 else:1257 value = None1258 option.process(opt, value, values, self)1259 def _process_short_opts(self, rargs, values):1260 arg = rargs.pop(0)1261 stop = False1262 i = 11263 for ch in arg[1:]:1264 opt = "-" + ch1265 option = self._short_opt.get(opt)1266 i += 1 # we have consumed a character1267 if not option:1268 raise BadOptionError(opt)1269 if option.takes_value():1270 # Any characters left in arg? Pretend they're the1271 # next arg, and stop consuming characters of arg.1272 if i < len(arg):1273 rargs.insert(0, arg[i:])1274 stop = True1275 nargs = option.nargs1276 if len(rargs) < nargs:1277 self.error(ngettext(1278 "%(option)s option requires %(number)d argument",1279 "%(option)s option requires %(number)d arguments",1280 nargs) % {"option": opt, "number": nargs})1281 elif nargs == 1:1282 value = rargs.pop(0)1283 else:1284 value = tuple(rargs[0:nargs])1285 del rargs[0:nargs]1286 else: # option doesn't take a value1287 value = None1288 option.process(opt, value, values, self)1289 if stop:1290 break1291 # -- Feedback methods ----------------------------------------------1292 def get_prog_name(self):1293 if self.prog is None:1294 return os.path.basename(sys.argv[0])1295 else:1296 return self.prog1297 def expand_prog_name(self, s):1298 return s.replace("%prog", self.get_prog_name())1299 def get_description(self):1300 return self.expand_prog_name(self.description)1301 def exit(self, status=0, msg=None):1302 if msg:1303 sys.stderr.write(msg)1304 sys.exit(status)1305 def error(self, msg):1306 """error(msg : string)1307 Print a usage message incorporating 'msg' to stderr and exit.1308 If you override this in a subclass, it should not return -- it1309 should either exit or raise an exception.1310 """1311 self.print_usage(sys.stderr)1312 self.exit(2, "%s: error: %s\n" % (self.get_prog_name(), msg))1313 def get_usage(self):1314 if self.usage:1315 return self.formatter.format_usage(1316 self.expand_prog_name(self.usage))1317 else:1318 return ""1319 def print_usage(self, file=None):1320 """print_usage(file : file = stdout)1321 Print the usage message for the current program (self.usage) to1322 'file' (default stdout). Any occurrence of the string "%prog" in1323 self.usage is replaced with the name of the current program1324 (basename of sys.argv[0]). Does nothing if self.usage is empty1325 or not defined.1326 """1327 if self.usage:1328 print(self.get_usage(), file=file)1329 def get_version(self):1330 if self.version:1331 return self.expand_prog_name(self.version)1332 else:1333 return ""1334 def print_version(self, file=None):1335 """print_version(file : file = stdout)1336 Print the version message for this program (self.version) to1337 'file' (default stdout). As with print_usage(), any occurrence1338 of "%prog" in self.version is replaced by the current program's1339 name. Does nothing if self.version is empty or undefined.1340 """1341 if self.version:1342 print(self.get_version(), file=file)1343 def format_option_help(self, formatter=None):1344 if formatter is None:1345 formatter = self.formatter1346 formatter.store_option_strings(self)1347 result = []1348 result.append(formatter.format_heading(_("Options")))1349 formatter.indent()1350 if self.option_list:1351 result.append(OptionContainer.format_option_help(self, formatter))1352 result.append("\n")1353 for group in self.option_groups:1354 result.append(group.format_help(formatter))1355 result.append("\n")1356 formatter.dedent()1357 # Drop the last "\n", or the header if no options or option groups:1358 return "".join(result[:-1])1359 def format_epilog(self, formatter):1360 return formatter.format_epilog(self.epilog)1361 def format_help(self, formatter=None):1362 if formatter is None:1363 formatter = self.formatter1364 result = []1365 if self.usage:1366 result.append(self.get_usage() + "\n")1367 if self.description:1368 result.append(self.format_description(formatter) + "\n")1369 result.append(self.format_option_help(formatter))1370 result.append(self.format_epilog(formatter))1371 return "".join(result)1372 def print_help(self, file=None):1373 """print_help(file : file = stdout)1374 Print an extended help message, listing all options and any1375 help text provided with them, to 'file' (default stdout).1376 """1377 if file is None:1378 file = sys.stdout1379 file.write(self.format_help())1380# class OptionParser1381def _match_abbrev(s, wordmap):1382 """_match_abbrev(s : string, wordmap : {string : Option}) -> string1383 Return the string key in 'wordmap' for which 's' is an unambiguous1384 abbreviation. If 's' is found to be ambiguous or doesn't match any of1385 'words', raise BadOptionError.1386 """1387 # Is there an exact match?1388 if s in wordmap:1389 return s1390 else:1391 # Isolate all words with s as a prefix.1392 possibilities = [word for word in wordmap.keys()1393 if word.startswith(s)]1394 # No exact match, so there had better be just one possibility.1395 if len(possibilities) == 1:1396 return possibilities[0]1397 elif not possibilities:1398 raise BadOptionError(s)1399 else:1400 # More than one possible completion: ambiguous prefix.1401 possibilities.sort()1402 raise AmbiguousOptionError(s, possibilities)1403# Some day, there might be many Option classes. As of Optik 1.3, the1404# preferred way to instantiate Options is indirectly, via make_option(),1405# which will become a factory function when there are many Option1406# classes....

Full Screen

Full Screen

cmdline.py

Source:cmdline.py Github

copy

Full Screen

...44 usage = "%s%s [options]" % ("python " if not IS_WIN else "", \45 "\"%s\"" % _ if " " in _ else _)46 parser = OptionParser(usage=usage)47 try:48 parser.add_option("--hh", dest="advancedHelp",49 action="store_true",50 help="Show advanced help message and exit")51 parser.add_option("--version", dest="showVersion",52 action="store_true",53 help="Show program's version number and exit")54 parser.add_option("-v", dest="verbose", type="int",55 help="Verbosity level: 0-6 (default %d)" % defaults.verbose)56 # Target options57 target = OptionGroup(parser, "Target", "At least one of these "58 "options has to be provided to define the target(s)")59 target.add_option("-d", dest="direct", help="Connection string "60 "for direct database connection")61 target.add_option("-u", "--url", dest="url", help="Target URL (e.g. \"http://www.site.com/vuln.php?id=1\")")62 target.add_option("-l", dest="logFile", help="Parse target(s) from Burp "63 "or WebScarab proxy log file")64 target.add_option("-x", dest="sitemapUrl", help="Parse target(s) from remote sitemap(.xml) file")65 target.add_option("-m", dest="bulkFile", help="Scan multiple targets given "66 "in a textual file ")67 target.add_option("-r", dest="requestFile",68 help="Load HTTP request from a file")69 target.add_option("-g", dest="googleDork",70 help="Process Google dork results as target URLs")71 target.add_option("-c", dest="configFile",72 help="Load options from a configuration INI file")73 # Request options74 request = OptionGroup(parser, "Request", "These options can be used "75 "to specify how to connect to the target URL")76 request.add_option("--method", dest="method",77 help="Force usage of given HTTP method (e.g. PUT)")78 request.add_option("--data", dest="data",79 help="Data string to be sent through POST")80 request.add_option("--param-del", dest="paramDel",81 help="Character used for splitting parameter values")82 request.add_option("--cookie", dest="cookie",83 help="HTTP Cookie header value")84 request.add_option("--cookie-del", dest="cookieDel",85 help="Character used for splitting cookie values")86 request.add_option("--load-cookies", dest="loadCookies",87 help="File containing cookies in Netscape/wget format")88 request.add_option("--drop-set-cookie", dest="dropSetCookie",89 action="store_true",90 help="Ignore Set-Cookie header from response")91 request.add_option("--user-agent", dest="agent",92 help="HTTP User-Agent header value")93 request.add_option("--random-agent", dest="randomAgent",94 action="store_true",95 help="Use randomly selected HTTP User-Agent header value")96 request.add_option("--host", dest="host",97 help="HTTP Host header value")98 request.add_option("--referer", dest="referer",99 help="HTTP Referer header value")100 request.add_option("-H", "--header", dest="header",101 help="Extra header (e.g. \"X-Forwarded-For: 127.0.0.1\")")102 request.add_option("--headers", dest="headers",103 help="Extra headers (e.g. \"Accept-Language: fr\\nETag: 123\")")104 request.add_option("--auth-type", dest="authType",105 help="HTTP authentication type "106 "(Basic, Digest, NTLM or PKI)")107 request.add_option("--auth-cred", dest="authCred",108 help="HTTP authentication credentials "109 "(name:password)")110 request.add_option("--auth-file", dest="authFile",111 help="HTTP authentication PEM cert/private key file")112 request.add_option("--ignore-401", dest="ignore401", action="store_true",113 help="Ignore HTTP Error 401 (Unauthorized)")114 request.add_option("--ignore-proxy", dest="ignoreProxy", action="store_true",115 help="Ignore system default proxy settings")116 request.add_option("--ignore-redirects", dest="ignoreRedirects", action="store_true",117 help="Ignore redirection attempts")118 request.add_option("--ignore-timeouts", dest="ignoreTimeouts", action="store_true",119 help="Ignore connection timeouts")120 request.add_option("--proxy", dest="proxy",121 help="Use a proxy to connect to the target URL")122 request.add_option("--proxy-cred", dest="proxyCred",123 help="Proxy authentication credentials "124 "(name:password)")125 request.add_option("--proxy-file", dest="proxyFile",126 help="Load proxy list from a file")127 request.add_option("--tor", dest="tor",128 action="store_true",129 help="Use Tor anonymity network")130 request.add_option("--tor-port", dest="torPort",131 help="Set Tor proxy port other than default")132 request.add_option("--tor-type", dest="torType",133 help="Set Tor proxy type (HTTP, SOCKS4 or SOCKS5 (default))")134 request.add_option("--check-tor", dest="checkTor",135 action="store_true",136 help="Check to see if Tor is used properly")137 request.add_option("--delay", dest="delay", type="float",138 help="Delay in seconds between each HTTP request")139 request.add_option("--timeout", dest="timeout", type="float",140 help="Seconds to wait before timeout connection "141 "(default %d)" % defaults.timeout)142 request.add_option("--retries", dest="retries", type="int",143 help="Retries when the connection timeouts "144 "(default %d)" % defaults.retries)145 request.add_option("--randomize", dest="rParam",146 help="Randomly change value for given parameter(s)")147 request.add_option("--safe-url", dest="safeUrl",148 help="URL address to visit frequently during testing")149 request.add_option("--safe-post", dest="safePost",150 help="POST data to send to a safe URL")151 request.add_option("--safe-req", dest="safeReqFile",152 help="Load safe HTTP request from a file")153 request.add_option("--safe-freq", dest="safeFreq", type="int",154 help="Test requests between two visits to a given safe URL")155 request.add_option("--skip-urlencode", dest="skipUrlEncode",156 action="store_true",157 help="Skip URL encoding of payload data")158 request.add_option("--csrf-token", dest="csrfToken",159 help="Parameter used to hold anti-CSRF token")160 request.add_option("--csrf-url", dest="csrfUrl",161 help="URL address to visit to extract anti-CSRF token")162 request.add_option("--force-ssl", dest="forceSSL",163 action="store_true",164 help="Force usage of SSL/HTTPS")165 request.add_option("--hpp", dest="hpp",166 action="store_true",167 help="Use HTTP parameter pollution method")168 request.add_option("--eval", dest="evalCode",169 help="Evaluate provided Python code before the request (e.g. \"import hashlib;id2=hashlib.md5(id).hexdigest()\")")170 # Optimization options171 optimization = OptionGroup(parser, "Optimization", "These "172 "options can be used to optimize the "173 "performance of sqlmap")174 optimization.add_option("-o", dest="optimize",175 action="store_true",176 help="Turn on all optimization switches")177 optimization.add_option("--predict-output", dest="predictOutput", action="store_true",178 help="Predict common queries output")179 optimization.add_option("--keep-alive", dest="keepAlive", action="store_true",180 help="Use persistent HTTP(s) connections")181 optimization.add_option("--null-connection", dest="nullConnection", action="store_true",182 help="Retrieve page length without actual HTTP response body")183 optimization.add_option("--threads", dest="threads", type="int",184 help="Max number of concurrent HTTP(s) "185 "requests (default %d)" % defaults.threads)186 # Injection options187 injection = OptionGroup(parser, "Injection", "These options can be "188 "used to specify which parameters to test "189 "for, provide custom injection payloads and "190 "optional tampering scripts")191 injection.add_option("-p", dest="testParameter",192 help="Testable parameter(s)")193 injection.add_option("--skip", dest="skip",194 help="Skip testing for given parameter(s)")195 injection.add_option("--skip-static", dest="skipStatic", action="store_true",196 help="Skip testing parameters that not appear to be dynamic")197 injection.add_option("--param-exclude", dest="paramExclude",198 help="Regexp to exclude parameters from testing (e.g. \"ses\")")199 injection.add_option("--dbms", dest="dbms",200 help="Force back-end DBMS to this value")201 injection.add_option("--dbms-cred", dest="dbmsCred",202 help="DBMS authentication credentials (user:password)")203 injection.add_option("--os", dest="os",204 help="Force back-end DBMS operating system "205 "to this value")206 injection.add_option("--invalid-bignum", dest="invalidBignum",207 action="store_true",208 help="Use big numbers for invalidating values")209 injection.add_option("--invalid-logical", dest="invalidLogical",210 action="store_true",211 help="Use logical operations for invalidating values")212 injection.add_option("--invalid-string", dest="invalidString",213 action="store_true",214 help="Use random strings for invalidating values")215 injection.add_option("--no-cast", dest="noCast",216 action="store_true",217 help="Turn off payload casting mechanism")218 injection.add_option("--no-escape", dest="noEscape",219 action="store_true",220 help="Turn off string escaping mechanism")221 injection.add_option("--prefix", dest="prefix",222 help="Injection payload prefix string")223 injection.add_option("--suffix", dest="suffix",224 help="Injection payload suffix string")225 injection.add_option("--tamper", dest="tamper",226 help="Use given script(s) for tampering injection data")227 # Detection options228 detection = OptionGroup(parser, "Detection", "These options can be "229 "used to customize the detection phase")230 detection.add_option("--level", dest="level", type="int",231 help="Level of tests to perform (1-5, "232 "default %d)" % defaults.level)233 detection.add_option("--risk", dest="risk", type="int",234 help="Risk of tests to perform (1-3, "235 "default %d)" % defaults.level)236 detection.add_option("--string", dest="string",237 help="String to match when "238 "query is evaluated to True")239 detection.add_option("--not-string", dest="notString",240 help="String to match when "241 "query is evaluated to False")242 detection.add_option("--regexp", dest="regexp",243 help="Regexp to match when "244 "query is evaluated to True")245 detection.add_option("--code", dest="code", type="int",246 help="HTTP code to match when "247 "query is evaluated to True")248 detection.add_option("--text-only", dest="textOnly",249 action="store_true",250 help="Compare pages based only on the textual content")251 detection.add_option("--titles", dest="titles",252 action="store_true",253 help="Compare pages based only on their titles")254 # Techniques options255 techniques = OptionGroup(parser, "Techniques", "These options can be "256 "used to tweak testing of specific SQL "257 "injection techniques")258 techniques.add_option("--technique", dest="tech",259 help="SQL injection techniques to use "260 "(default \"%s\")" % defaults.tech)261 techniques.add_option("--time-sec", dest="timeSec",262 type="int",263 help="Seconds to delay the DBMS response "264 "(default %d)" % defaults.timeSec)265 techniques.add_option("--union-cols", dest="uCols",266 help="Range of columns to test for UNION query SQL injection")267 techniques.add_option("--union-char", dest="uChar",268 help="Character to use for bruteforcing number of columns")269 techniques.add_option("--union-from", dest="uFrom",270 help="Table to use in FROM part of UNION query SQL injection")271 techniques.add_option("--dns-domain", dest="dnsDomain",272 help="Domain name used for DNS exfiltration attack")273 techniques.add_option("--second-order", dest="secondOrder",274 help="Resulting page URL searched for second-order "275 "response")276 # Fingerprint options277 fingerprint = OptionGroup(parser, "Fingerprint")278 fingerprint.add_option("-f", "--fingerprint", dest="extensiveFp",279 action="store_true",280 help="Perform an extensive DBMS version fingerprint")281 # Enumeration options282 enumeration = OptionGroup(parser, "Enumeration", "These options can "283 "be used to enumerate the back-end database "284 "management system information, structure "285 "and data contained in the tables. Moreover "286 "you can run your own SQL statements")287 enumeration.add_option("-a", "--all", dest="getAll",288 action="store_true", help="Retrieve everything")289 enumeration.add_option("-b", "--banner", dest="getBanner",290 action="store_true", help="Retrieve DBMS banner")291 enumeration.add_option("--current-user", dest="getCurrentUser",292 action="store_true",293 help="Retrieve DBMS current user")294 enumeration.add_option("--current-db", dest="getCurrentDb",295 action="store_true",296 help="Retrieve DBMS current database")297 enumeration.add_option("--hostname", dest="getHostname",298 action="store_true",299 help="Retrieve DBMS server hostname")300 enumeration.add_option("--is-dba", dest="isDba",301 action="store_true",302 help="Detect if the DBMS current user is DBA")303 enumeration.add_option("--users", dest="getUsers", action="store_true",304 help="Enumerate DBMS users")305 enumeration.add_option("--passwords", dest="getPasswordHashes",306 action="store_true",307 help="Enumerate DBMS users password hashes")308 enumeration.add_option("--privileges", dest="getPrivileges",309 action="store_true",310 help="Enumerate DBMS users privileges")311 enumeration.add_option("--roles", dest="getRoles",312 action="store_true",313 help="Enumerate DBMS users roles")314 enumeration.add_option("--dbs", dest="getDbs", action="store_true",315 help="Enumerate DBMS databases")316 enumeration.add_option("--tables", dest="getTables", action="store_true",317 help="Enumerate DBMS database tables")318 enumeration.add_option("--columns", dest="getColumns", action="store_true",319 help="Enumerate DBMS database table columns")320 enumeration.add_option("--schema", dest="getSchema", action="store_true",321 help="Enumerate DBMS schema")322 enumeration.add_option("--count", dest="getCount", action="store_true",323 help="Retrieve number of entries for table(s)")324 enumeration.add_option("--dump", dest="dumpTable", action="store_true",325 help="Dump DBMS database table entries")326 enumeration.add_option("--dump-all", dest="dumpAll", action="store_true",327 help="Dump all DBMS databases tables entries")328 enumeration.add_option("--search", dest="search", action="store_true",329 help="Search column(s), table(s) and/or database name(s)")330 enumeration.add_option("--comments", dest="getComments", action="store_true",331 help="Retrieve DBMS comments")332 enumeration.add_option("-D", dest="db",333 help="DBMS database to enumerate")334 enumeration.add_option("-T", dest="tbl",335 help="DBMS database table(s) to enumerate")336 enumeration.add_option("-C", dest="col",337 help="DBMS database table column(s) to enumerate")338 enumeration.add_option("-X", dest="excludeCol",339 help="DBMS database table column(s) to not enumerate")340 enumeration.add_option("-U", dest="user",341 help="DBMS user to enumerate")342 enumeration.add_option("--exclude-sysdbs", dest="excludeSysDbs",343 action="store_true",344 help="Exclude DBMS system databases when "345 "enumerating tables")346 enumeration.add_option("--pivot-column", dest="pivotColumn",347 help="Pivot column name")348 enumeration.add_option("--where", dest="dumpWhere",349 help="Use WHERE condition while table dumping")350 enumeration.add_option("--start", dest="limitStart", type="int",351 help="First query output entry to retrieve")352 enumeration.add_option("--stop", dest="limitStop", type="int",353 help="Last query output entry to retrieve")354 enumeration.add_option("--first", dest="firstChar", type="int",355 help="First query output word character to retrieve")356 enumeration.add_option("--last", dest="lastChar", type="int",357 help="Last query output word character to retrieve")358 enumeration.add_option("--sql-query", dest="query",359 help="SQL statement to be executed")360 enumeration.add_option("--sql-shell", dest="sqlShell",361 action="store_true",362 help="Prompt for an interactive SQL shell")363 enumeration.add_option("--sql-file", dest="sqlFile",364 help="Execute SQL statements from given file(s)")365 # Brute force options366 brute = OptionGroup(parser, "Brute force", "These "367 "options can be used to run brute force "368 "checks")369 brute.add_option("--common-tables", dest="commonTables", action="store_true",370 help="Check existence of common tables")371 brute.add_option("--common-columns", dest="commonColumns", action="store_true",372 help="Check existence of common columns")373 # User-defined function options374 udf = OptionGroup(parser, "User-defined function injection", "These "375 "options can be used to create custom user-defined "376 "functions")377 udf.add_option("--udf-inject", dest="udfInject", action="store_true",378 help="Inject custom user-defined functions")379 udf.add_option("--shared-lib", dest="shLib",380 help="Local path of the shared library")381 # File system options382 filesystem = OptionGroup(parser, "File system access", "These options "383 "can be used to access the back-end database "384 "management system underlying file system")385 filesystem.add_option("--file-read", dest="rFile",386 help="Read a file from the back-end DBMS "387 "file system")388 filesystem.add_option("--file-write", dest="wFile",389 help="Write a local file on the back-end "390 "DBMS file system")391 filesystem.add_option("--file-dest", dest="dFile",392 help="Back-end DBMS absolute filepath to "393 "write to")394 # Takeover options395 takeover = OptionGroup(parser, "Operating system access", "These "396 "options can be used to access the back-end "397 "database management system underlying "398 "operating system")399 takeover.add_option("--os-cmd", dest="osCmd",400 help="Execute an operating system command")401 takeover.add_option("--os-shell", dest="osShell",402 action="store_true",403 help="Prompt for an interactive operating "404 "system shell")405 takeover.add_option("--os-pwn", dest="osPwn",406 action="store_true",407 help="Prompt for an OOB shell, "408 "Meterpreter or VNC")409 takeover.add_option("--os-smbrelay", dest="osSmb",410 action="store_true",411 help="One click prompt for an OOB shell, "412 "Meterpreter or VNC")413 takeover.add_option("--os-bof", dest="osBof",414 action="store_true",415 help="Stored procedure buffer overflow "416 "exploitation")417 takeover.add_option("--priv-esc", dest="privEsc",418 action="store_true",419 help="Database process user privilege escalation")420 takeover.add_option("--msf-path", dest="msfPath",421 help="Local path where Metasploit Framework "422 "is installed")423 takeover.add_option("--tmp-path", dest="tmpPath",424 help="Remote absolute path of temporary files "425 "directory")426 # Windows registry options427 windows = OptionGroup(parser, "Windows registry access", "These "428 "options can be used to access the back-end "429 "database management system Windows "430 "registry")431 windows.add_option("--reg-read", dest="regRead",432 action="store_true",433 help="Read a Windows registry key value")434 windows.add_option("--reg-add", dest="regAdd",435 action="store_true",436 help="Write a Windows registry key value data")437 windows.add_option("--reg-del", dest="regDel",438 action="store_true",439 help="Delete a Windows registry key value")440 windows.add_option("--reg-key", dest="regKey",441 help="Windows registry key")442 windows.add_option("--reg-value", dest="regVal",443 help="Windows registry key value")444 windows.add_option("--reg-data", dest="regData",445 help="Windows registry key value data")446 windows.add_option("--reg-type", dest="regType",447 help="Windows registry key value type")448 # General options449 general = OptionGroup(parser, "General", "These options can be used "450 "to set some general working parameters")451 #general.add_option("-x", dest="xmlFile",452 # help="Dump the data into an XML file")453 general.add_option("-s", dest="sessionFile",454 help="Load session from a stored (.sqlite) file")455 general.add_option("-t", dest="trafficFile",456 help="Log all HTTP traffic into a "457 "textual file")458 general.add_option("--batch", dest="batch",459 action="store_true",460 help="Never ask for user input, use the default behaviour")461 general.add_option("--binary-fields", dest="binaryFields",462 help="Result fields having binary values (e.g. \"digest\")")463 general.add_option("--charset", dest="charset",464 help="Force character encoding used for data retrieval")465 general.add_option("--crawl", dest="crawlDepth", type="int",466 help="Crawl the website starting from the target URL")467 general.add_option("--crawl-exclude", dest="crawlExclude",468 help="Regexp to exclude pages from crawling (e.g. \"logout\")")469 general.add_option("--csv-del", dest="csvDel",470 help="Delimiting character used in CSV output "471 "(default \"%s\")" % defaults.csvDel)472 general.add_option("--dump-format", dest="dumpFormat",473 help="Format of dumped data (CSV (default), HTML or SQLITE)")474 general.add_option("--eta", dest="eta",475 action="store_true",476 help="Display for each output the "477 "estimated time of arrival")478 general.add_option("--flush-session", dest="flushSession",479 action="store_true",480 help="Flush session files for current target")481 general.add_option("--forms", dest="forms",482 action="store_true",483 help="Parse and test forms on target URL")484 general.add_option("--fresh-queries", dest="freshQueries",485 action="store_true",486 help="Ignore query results stored in session file")487 general.add_option("--hex", dest="hexConvert",488 action="store_true",489 help="Use DBMS hex function(s) for data retrieval")490 general.add_option("--output-dir", dest="outputDir",491 action="store",492 help="Custom output directory path")493 general.add_option("--parse-errors", dest="parseErrors",494 action="store_true",495 help="Parse and display DBMS error messages from responses")496 general.add_option("--save", dest="saveConfig",497 help="Save options to a configuration INI file")498 general.add_option("--scope", dest="scope",499 help="Regexp to filter targets from provided proxy log")500 general.add_option("--test-filter", dest="testFilter",501 help="Select tests by payloads and/or titles (e.g. ROW)")502 general.add_option("--test-skip", dest="testSkip",503 help="Skip tests by payloads and/or titles (e.g. BENCHMARK)")504 general.add_option("--update", dest="updateAll",505 action="store_true",506 help="Update sqlmap")507 # Miscellaneous options508 miscellaneous = OptionGroup(parser, "Miscellaneous")509 miscellaneous.add_option("-z", dest="mnemonics",510 help="Use short mnemonics (e.g. \"flu,bat,ban,tec=EU\")")511 miscellaneous.add_option("--alert", dest="alert",512 help="Run host OS command(s) when SQL injection is found")513 miscellaneous.add_option("--answers", dest="answers",514 help="Set question answers (e.g. \"quit=N,follow=N\")")515 miscellaneous.add_option("--beep", dest="beep", action="store_true",516 help="Beep on question and/or when SQL injection is found")517 miscellaneous.add_option("--cleanup", dest="cleanup",518 action="store_true",519 help="Clean up the DBMS from sqlmap specific "520 "UDF and tables")521 miscellaneous.add_option("--dependencies", dest="dependencies",522 action="store_true",523 help="Check for missing (non-core) sqlmap dependencies")524 miscellaneous.add_option("--disable-coloring", dest="disableColoring",525 action="store_true",526 help="Disable console output coloring")527 miscellaneous.add_option("--gpage", dest="googlePage", type="int",528 help="Use Google dork results from specified page number")529 miscellaneous.add_option("--identify-waf", dest="identifyWaf",530 action="store_true",531 help="Make a thorough testing for a WAF/IPS/IDS protection")532 miscellaneous.add_option("--mobile", dest="mobile",533 action="store_true",534 help="Imitate smartphone through HTTP User-Agent header")535 miscellaneous.add_option("--offline", dest="offline",536 action="store_true",537 help="Work in offline mode (only use session data)")538 miscellaneous.add_option("--page-rank", dest="pageRank",539 action="store_true",540 help="Display page rank (PR) for Google dork results")541 miscellaneous.add_option("--purge-output", dest="purgeOutput",542 action="store_true",543 help="Safely remove all content from output directory")544 miscellaneous.add_option("--skip-waf", dest="skipWaf",545 action="store_true",546 help="Skip heuristic detection of WAF/IPS/IDS protection")547 miscellaneous.add_option("--smart", dest="smart",548 action="store_true",549 help="Conduct thorough tests only if positive heuristic(s)")550 miscellaneous.add_option("--sqlmap-shell", dest="sqlmapShell", action="store_true",551 help="Prompt for an interactive sqlmap shell")552 miscellaneous.add_option("--tmp-dir", dest="tmpDir",553 help="Local directory for storing temporary files")554 miscellaneous.add_option("--wizard", dest="wizard",555 action="store_true",556 help="Simple wizard interface for beginner users")557 # Hidden and/or experimental options558 parser.add_option("--dummy", dest="dummy", action="store_true",559 help=SUPPRESS_HELP)560 parser.add_option("--murphy-rate", dest="murphyRate", type="int",561 help=SUPPRESS_HELP)562 parser.add_option("--pickled-options", dest="pickledOptions",563 help=SUPPRESS_HELP)564 parser.add_option("--disable-precon", dest="disablePrecon", action="store_true",565 help=SUPPRESS_HELP)566 parser.add_option("--profile", dest="profile", action="store_true",567 help=SUPPRESS_HELP)568 parser.add_option("--force-dns", dest="forceDns", action="store_true",569 help=SUPPRESS_HELP)570 parser.add_option("--force-threads", dest="forceThreads", action="store_true",571 help=SUPPRESS_HELP)572 parser.add_option("--smoke-test", dest="smokeTest", action="store_true",573 help=SUPPRESS_HELP)574 parser.add_option("--live-test", dest="liveTest", action="store_true",575 help=SUPPRESS_HELP)576 parser.add_option("--stop-fail", dest="stopFail", action="store_true",577 help=SUPPRESS_HELP)578 parser.add_option("--run-case", dest="runCase", help=SUPPRESS_HELP)579 parser.add_option_group(target)580 parser.add_option_group(request)581 parser.add_option_group(optimization)582 parser.add_option_group(injection)583 parser.add_option_group(detection)584 parser.add_option_group(techniques)585 parser.add_option_group(fingerprint)586 parser.add_option_group(enumeration)587 parser.add_option_group(brute)588 parser.add_option_group(udf)589 parser.add_option_group(filesystem)590 parser.add_option_group(takeover)591 parser.add_option_group(windows)592 parser.add_option_group(general)593 parser.add_option_group(miscellaneous)594 # Dirty hack to display longer options without breaking into two lines595 def _(self, *args):596 retVal = parser.formatter._format_option_strings(*args)597 if len(retVal) > MAX_HELP_OPTION_LENGTH:598 retVal = ("%%.%ds.." % (MAX_HELP_OPTION_LENGTH - parser.formatter.indent_increment)) % retVal599 return retVal600 parser.formatter._format_option_strings = parser.formatter.format_option_strings601 parser.formatter.format_option_strings = type(parser.formatter.format_option_strings)(_, parser, type(parser))602 # Dirty hack for making a short option '-hh'603 option = parser.get_option("--hh")604 option._short_opts = ["-hh"]605 option._long_opts = []606 # Dirty hack for inherent help message of switch '-h'607 option = parser.get_option("-h")608 option.help = option.help.capitalize().replace("this help", "basic help")609 _ = []610 prompt = False611 advancedHelp = True612 extraHeaders = []613 for arg in argv:614 _.append(getUnicode(arg, encoding=sys.getfilesystemencoding() or UNICODE_ENCODING))615 argv = _616 checkDeprecatedOptions(argv)617 prompt = "--sqlmap-shell" in argv618 if prompt:619 parser.usage = ""620 cmdLineOptions.sqlmapShell = True621 _ = ["x", "q", "exit", "quit", "clear"]622 for option in parser.option_list:623 _.extend(option._long_opts)624 _.extend(option._short_opts)625 for group in parser.option_groups:626 for option in group.option_list:627 _.extend(option._long_opts)628 _.extend(option._short_opts)629 autoCompletion(AUTOCOMPLETE_TYPE.SQLMAP, commands=_)630 while True:631 command = None632 try:633 command = raw_input("sqlmap-shell> ").strip()634 command = getUnicode(command, encoding=sys.stdin.encoding)635 except (KeyboardInterrupt, EOFError):636 print637 raise SqlmapShellQuitException638 if not command:639 continue640 elif command.lower() == "clear":641 clearHistory()642 dataToStdout("[i] history cleared\n")643 saveHistory(AUTOCOMPLETE_TYPE.SQLMAP)644 elif command.lower() in ("x", "q", "exit", "quit"):645 raise SqlmapShellQuitException646 elif command[0] != '-':647 dataToStdout("[!] invalid option(s) provided\n")648 dataToStdout("[i] proper example: '-u http://www.site.com/vuln.php?id=1 --banner'\n")649 else:650 saveHistory(AUTOCOMPLETE_TYPE.SQLMAP)651 loadHistory(AUTOCOMPLETE_TYPE.SQLMAP)652 break653 try:654 for arg in shlex.split(command):655 argv.append(getUnicode(arg, encoding=sys.stdin.encoding))656 except ValueError, ex:657 raise SqlmapSyntaxException, "something went wrong during command line parsing ('%s')" % ex.message658 for i in xrange(len(argv)):659 if argv[i] == "-hh":660 argv[i] = "-h"661 elif len(argv[i]) > 1 and all(ord(_) in xrange(0x2018, 0x2020) for _ in ((argv[i].split('=', 1)[-1].strip() or ' ')[0], argv[i][-1])):...

Full Screen

Full Screen

Pytest Tutorial

Looking for an in-depth tutorial around pytest? LambdaTest covers the detailed pytest tutorial that has everything related to the pytest, from setting up the pytest framework to automation testing. Delve deeper into pytest testing by exploring advanced use cases like parallel testing, pytest fixtures, parameterization, executing multiple test cases from a single file, and more.

Chapters

  1. What is pytest
  2. Pytest installation: Want to start pytest from scratch? See how to install and configure pytest for Python automation testing.
  3. Run first test with pytest framework: Follow this step-by-step tutorial to write and run your first pytest script.
  4. Parallel testing with pytest: A hands-on guide to parallel testing with pytest to improve the scalability of your test automation.
  5. Generate pytest reports: Reports make it easier to understand the results of pytest-based test runs. Learn how to generate pytest reports.
  6. Pytest Parameterized tests: Create and run your pytest scripts while avoiding code duplication and increasing test coverage with parameterization.
  7. Pytest Fixtures: Check out how to implement pytest fixtures for your end-to-end testing needs.
  8. Execute Multiple Test Cases: Explore different scenarios for running multiple test cases in pytest from a single file.
  9. Stop Test Suite after N Test Failures: See how to stop your test suite after n test failures in pytest using the @pytest.mark.incremental decorator and maxfail command-line option.

YouTube

Skim our below pytest tutorial playlist to get started with automation testing using the pytest framework.

https://www.youtube.com/playlist?list=PLZMWkkQEwOPlcGgDmHl8KkXKeLF83XlrP

Run Pytest automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful