diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..17757a9 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,27 @@ +Copyright (c) 2017, Xianglong Tao +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by the . +4. Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Xianglong Tao ''AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Xianglong Tao BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..b98bb3e --- /dev/null +++ b/README.rst @@ -0,0 +1,45 @@ +====== +findQA +====== + +findQA is a Django command that enables users to search for testers based on +the country(s) and device(s) the user specifies. The command output includes +the following fields formatted as CSV: the tester's first name, last name, +country code, and experience (which is how many bugs the tester has spotted +based on the searching criteria). + +This is version 0.1.1 of this app. + +Quick start +----------- + +1. Check the requirements for this app in requirement.txt in 'findQA/requirements.txt' + `pip freeze > requirements.txt` + If you wish to install all required libraries, simply run + `pip install -r requirements.txt` + +2. In matchQA/matchQA/settings.py, make sure the app has been added to INSTALLED_APPS, such as + INSTALLED_APPS = [ + 'findQA.apps.FindQAConfig', + ...] + +3. Run `python manage.py migrate` to create the findQA tables in the database. + +4. Run `python manage.py shell < load_data.py` to insert all data from matchQA/matchQA/csv_data + into database. + +5. Run `python manage.py find_testers -h` to view the command's help. + Examples: + * If you wish to search by all countries and device + `python manage.py find_testers` + + * If you wish to search by country(s) + `python manage.py find_testers -c US,JP` + + * If you wish to search by device(s), please make sure enclose each device's name in single quotes. + `python manage.py find_testers -d 'iPhone 4','iPhone 4S'` + + * If you wish to search by countries and device(s). + `python manage.py find_testers -c US,JP -d 'iPhone 4','iPhone 4S'` + +5b. [OPTIONAL] Run `python manage.py test` to run unit tests to against the code. \ No newline at end of file diff --git a/csv_data/bugs.csv b/csv_data/bugs.csv new file mode 100644 index 0000000..e7eaa27 --- /dev/null +++ b/csv_data/bugs.csv @@ -0,0 +1,1001 @@ +"bugId","deviceId","testerId" +"1","1","4" +"2","8","9" +"3","4","7" +"4","2","4" +"5","6","3" +"6","8","7" +"7","9","9" +"8","7","5" +"9","5","9" +"10","1","4" +"11","2","4" +"12","9","9" +"13","8","9" +"14","3","3" +"15","5","9" +"16","1","1" +"17","1","4" +"18","3","6" +"19","6","9" +"20","4","3" +"21","3","1" +"22","10","1" +"23","3","1" +"24","3","6" +"25","5","5" +"26","5","3" +"27","3","6" +"28","6","9" +"29","6","8" +"30","4","3" +"31","1","5" +"32","6","9" +"33","1","4" +"34","5","3" +"35","3","6" +"36","3","6" +"37","7","5" +"38","10","1" +"39","2","4" +"40","3","6" +"41","9","8" +"42","9","9" +"43","10","8" +"44","1","1" +"45","8","9" +"46","4","3" +"47","3","1" +"48","2","1" +"49","8","9" +"50","3","6" +"51","7","7" +"52","2","4" +"53","8","7" +"54","4","7" +"55","10","8" +"56","2","4" +"57","3","1" +"58","1","4" +"59","2","4" +"60","8","9" +"61","5","5" +"62","10","8" +"63","2","4" +"64","7","5" +"65","2","4" +"66","9","2" +"67","4","7" +"68","3","3" +"69","6","2" +"70","9","2" +"71","3","6" +"72","4","2" +"73","2","1" +"74","4","7" +"75","5","7" +"76","6","5" +"77","7","5" +"78","5","7" +"79","8","7" +"80","5","2" +"81","4","7" +"82","2","4" +"83","2","4" +"84","5","9" +"85","1","4" +"86","3","3" +"87","5","2" +"88","7","5" +"89","6","3" +"90","6","2" +"91","3","6" +"92","2","1" +"93","1","4" +"94","5","5" +"95","7","5" +"96","8","7" +"97","10","5" +"98","5","3" +"99","4","3" +"100","3","6" +"101","5","9" +"102","2","4" +"103","3","6" +"104","1","8" +"105","9","8" +"106","9","8" +"107","6","3" +"108","9","9" +"109","6","8" +"110","4","7" +"111","1","4" +"112","6","5" +"113","4","7" +"114","3","6" +"115","5","2" +"116","4","7" +"117","8","7" +"118","6","9" +"119","5","3" +"120","10","8" +"121","4","3" +"122","7","5" +"123","6","2" +"124","6","9" +"125","4","3" +"126","9","9" +"127","3","6" +"128","1","4" +"129","5","7" +"130","1","4" +"131","6","5" +"132","3","3" +"133","3","6" +"134","6","5" +"135","3","3" +"136","7","5" +"137","7","5" +"138","3","1" +"139","3","6" +"140","7","5" +"141","10","1" +"142","5","3" +"143","6","9" +"144","1","1" +"145","3","6" +"146","2","4" +"147","3","6" +"148","5","5" +"149","2","4" +"150","3","6" +"151","10","1" +"152","3","3" +"153","6","8" +"154","1","4" +"155","3","6" +"156","3","6" +"157","9","9" +"158","3","6" +"159","10","5" +"160","5","7" +"161","5","7" +"162","2","4" +"163","9","9" +"164","1","1" +"165","9","9" +"166","3","6" +"167","9","9" +"168","3","8" +"169","2","4" +"170","10","1" +"171","1","4" +"172","5","3" +"173","8","2" +"174","8","9" +"175","10","1" +"176","9","2" +"177","1","5" +"178","3","3" +"179","7","5" +"180","7","2" +"181","6","7" +"182","2","4" +"183","1","4" +"184","1","4" +"185","1","1" +"186","2","1" +"187","7","2" +"188","8","2" +"189","4","2" +"190","2","1" +"191","3","6" +"192","6","7" +"193","8","2" +"194","1","5" +"195","9","9" +"196","8","2" +"197","4","3" +"198","7","5" +"199","3","1" +"200","4","7" +"201","2","4" +"202","9","9" +"203","3","1" +"204","8","7" +"205","1","4" +"206","7","7" +"207","3","3" +"208","1","5" +"209","7","2" +"210","1","8" +"211","10","5" +"212","7","2" +"213","7","5" +"214","5","5" +"215","9","9" +"216","3","6" +"217","1","4" +"218","5","9" +"219","2","4" +"220","2","4" +"221","5","5" +"222","1","5" +"223","3","6" +"224","10","5" +"225","6","3" +"226","3","6" +"227","8","2" +"228","3","3" +"229","8","9" +"230","3","6" +"231","1","4" +"232","9","8" +"233","2","1" +"234","3","6" +"235","10","1" +"236","3","8" +"237","5","2" +"238","10","8" +"239","10","1" +"240","8","9" +"241","1","4" +"242","6","9" +"243","3","6" +"244","5","5" +"245","2","4" +"246","1","8" +"247","6","5" +"248","1","1" +"249","5","5" +"250","3","6" +"251","1","4" +"252","10","5" +"253","1","4" +"254","7","7" +"255","6","3" +"256","7","7" +"257","6","7" +"258","7","7" +"259","6","3" +"260","6","7" +"261","10","1" +"262","5","3" +"263","6","7" +"264","2","4" +"265","5","5" +"266","9","9" +"267","1","1" +"268","5","7" +"269","5","9" +"270","8","7" +"271","1","4" +"272","8","2" +"273","3","1" +"274","2","4" +"275","3","6" +"276","6","9" +"277","8","2" +"278","7","5" +"279","10","1" +"280","6","9" +"281","3","6" +"282","1","4" +"283","9","9" +"284","10","5" +"285","4","3" +"286","3","6" +"287","3","3" +"288","1","4" +"289","6","3" +"290","8","7" +"291","9","2" +"292","3","8" +"293","8","9" +"294","7","2" +"295","6","8" +"296","3","8" +"297","5","7" +"298","1","8" +"299","10","8" +"300","9","2" +"301","9","2" +"302","3","8" +"303","3","6" +"304","3","6" +"305","4","2" +"306","3","8" +"307","1","5" +"308","4","3" +"309","6","7" +"310","6","7" +"311","9","2" +"312","3","8" +"313","3","6" +"314","4","2" +"315","10","1" +"316","8","7" +"317","7","2" +"318","5","3" +"319","1","4" +"320","3","6" +"321","7","7" +"322","10","1" +"323","1","4" +"324","5","9" +"325","6","3" +"326","9","8" +"327","5","3" +"328","9","9" +"329","10","8" +"330","10","1" +"331","10","8" +"332","3","1" +"333","8","7" +"334","4","3" +"335","1","4" +"336","1","4" +"337","4","3" +"338","6","5" +"339","8","2" +"340","8","9" +"341","9","9" +"342","3","6" +"343","7","5" +"344","6","3" +"345","3","3" +"346","4","7" +"347","4","3" +"348","1","8" +"349","2","4" +"350","8","7" +"351","4","2" +"352","10","5" +"353","3","8" +"354","1","8" +"355","7","2" +"356","7","7" +"357","9","9" +"358","7","5" +"359","2","4" +"360","6","9" +"361","5","2" +"362","7","7" +"363","6","2" +"364","6","3" +"365","3","6" +"366","5","3" +"367","10","1" +"368","3","1" +"369","4","2" +"370","6","5" +"371","6","5" +"372","6","9" +"373","1","5" +"374","1","4" +"375","2","1" +"376","3","6" +"377","4","2" +"378","7","5" +"379","5","3" +"380","2","1" +"381","5","9" +"382","8","9" +"383","6","7" +"384","6","8" +"385","3","6" +"386","5","9" +"387","1","4" +"388","1","5" +"389","2","4" +"390","3","1" +"391","7","7" +"392","4","2" +"393","3","6" +"394","4","7" +"395","3","6" +"396","3","6" +"397","1","8" +"398","3","8" +"399","2","4" +"400","3","8" +"401","5","9" +"402","7","5" +"403","6","3" +"404","4","2" +"405","1","4" +"406","2","4" +"407","2","4" +"408","5","9" +"409","5","2" +"410","3","6" +"411","3","1" +"412","6","8" +"413","3","6" +"414","1","1" +"415","7","2" +"416","9","8" +"417","3","1" +"418","1","5" +"419","1","4" +"420","9","9" +"421","6","9" +"422","5","7" +"423","4","2" +"424","8","9" +"425","2","1" +"426","4","7" +"427","2","4" +"428","2","1" +"429","5","5" +"430","6","5" +"431","1","4" +"432","6","7" +"433","6","9" +"434","1","4" +"435","9","9" +"436","7","7" +"437","2","1" +"438","10","8" +"439","1","1" +"440","2","4" +"441","5","9" +"442","2","1" +"443","3","6" +"444","5","9" +"445","3","1" +"446","6","3" +"447","6","7" +"448","2","4" +"449","1","4" +"450","3","6" +"451","1","1" +"452","4","3" +"453","5","5" +"454","1","4" +"455","4","3" +"456","2","4" +"457","3","6" +"458","1","4" +"459","3","8" +"460","3","6" +"461","7","2" +"462","9","9" +"463","3","6" +"464","8","2" +"465","2","4" +"466","2","1" +"467","2","1" +"468","6","9" +"469","5","9" +"470","10","5" +"471","9","8" +"472","1","4" +"473","6","9" +"474","6","5" +"475","6","3" +"476","7","2" +"477","3","6" +"478","4","7" +"479","5","7" +"480","3","6" +"481","3","6" +"482","5","7" +"483","5","3" +"484","3","8" +"485","6","3" +"486","3","1" +"487","6","8" +"488","7","7" +"489","3","6" +"490","3","6" +"491","3","6" +"492","1","4" +"493","10","8" +"494","6","3" +"495","6","8" +"496","5","3" +"497","3","6" +"498","10","1" +"499","5","7" +"500","3","6" +"501","10","8" +"502","6","8" +"503","3","6" +"504","3","6" +"505","2","4" +"506","3","8" +"507","3","3" +"508","6","8" +"509","3","8" +"510","3","3" +"511","6","8" +"512","5","5" +"513","7","5" +"514","5","7" +"515","2","4" +"516","5","2" +"517","3","3" +"518","6","3" +"519","3","6" +"520","1","5" +"521","10","5" +"522","4","3" +"523","9","8" +"524","10","1" +"525","9","2" +"526","3","3" +"527","8","7" +"528","4","2" +"529","3","6" +"530","10","8" +"531","3","6" +"532","3","3" +"533","4","3" +"534","2","1" +"535","9","8" +"536","5","7" +"537","8","9" +"538","3","6" +"539","5","2" +"540","1","4" +"541","4","2" +"542","5","3" +"543","10","1" +"544","10","1" +"545","5","3" +"546","5","3" +"547","1","8" +"548","1","4" +"549","1","4" +"550","8","9" +"551","1","4" +"552","3","1" +"553","3","1" +"554","3","1" +"555","9","9" +"556","3","6" +"557","1","8" +"558","6","7" +"559","2","1" +"560","3","6" +"561","6","5" +"562","4","2" +"563","10","8" +"564","8","9" +"565","5","2" +"566","3","1" +"567","6","7" +"568","3","3" +"569","2","4" +"570","10","5" +"571","6","2" +"572","4","2" +"573","9","8" +"574","7","7" +"575","3","6" +"576","4","3" +"577","7","7" +"578","7","5" +"579","9","9" +"580","6","9" +"581","4","2" +"582","9","9" +"583","2","4" +"584","5","7" +"585","1","4" +"586","1","8" +"587","8","7" +"588","1","4" +"589","8","9" +"590","6","8" +"591","10","1" +"592","2","4" +"593","3","8" +"594","4","3" +"595","5","7" +"596","4","7" +"597","3","3" +"598","8","9" +"599","7","5" +"600","2","1" +"601","1","4" +"602","9","9" +"603","3","1" +"604","1","5" +"605","10","5" +"606","8","9" +"607","1","8" +"608","1","4" +"609","3","1" +"610","2","1" +"611","4","3" +"612","4","7" +"613","6","3" +"614","3","1" +"615","6","5" +"616","4","7" +"617","3","8" +"618","8","2" +"619","9","2" +"620","8","7" +"621","3","1" +"622","1","4" +"623","1","1" +"624","10","8" +"625","9","8" +"626","8","7" +"627","3","6" +"628","5","5" +"629","6","9" +"630","6","3" +"631","2","4" +"632","10","1" +"633","3","6" +"634","2","4" +"635","7","5" +"636","3","6" +"637","9","8" +"638","4","7" +"639","6","2" +"640","5","3" +"641","6","9" +"642","4","2" +"643","2","1" +"644","3","6" +"645","7","7" +"646","1","8" +"647","9","9" +"648","1","5" +"649","10","5" +"650","3","6" +"651","4","2" +"652","2","1" +"653","3","6" +"654","7","5" +"655","8","7" +"656","7","2" +"657","1","8" +"658","3","6" +"659","3","1" +"660","4","7" +"661","7","2" +"662","6","8" +"663","3","3" +"664","10","5" +"665","6","8" +"666","10","1" +"667","6","3" +"668","2","1" +"669","2","4" +"670","3","3" +"671","3","8" +"672","3","8" +"673","3","6" +"674","3","8" +"675","8","2" +"676","3","6" +"677","1","8" +"678","9","8" +"679","2","1" +"680","3","6" +"681","1","8" +"682","5","9" +"683","6","3" +"684","2","4" +"685","3","6" +"686","7","5" +"687","3","8" +"688","8","9" +"689","6","3" +"690","3","6" +"691","5","5" +"692","2","4" +"693","5","2" +"694","1","4" +"695","6","8" +"696","1","8" +"697","1","5" +"698","1","1" +"699","3","6" +"700","5","2" +"701","6","8" +"702","3","8" +"703","5","5" +"704","3","6" +"705","3","6" +"706","7","7" +"707","4","7" +"708","3","6" +"709","10","1" +"710","4","7" +"711","6","2" +"712","9","2" +"713","1","8" +"714","3","6" +"715","7","5" +"716","10","1" +"717","6","3" +"718","9","2" +"719","1","4" +"720","8","7" +"721","1","8" +"722","3","6" +"723","1","8" +"724","1","5" +"725","1","5" +"726","1","1" +"727","6","7" +"728","4","3" +"729","5","2" +"730","4","3" +"731","4","7" +"732","6","9" +"733","3","1" +"734","3","3" +"735","2","1" +"736","6","3" +"737","10","1" +"738","1","1" +"739","1","5" +"740","1","8" +"741","3","6" +"742","1","4" +"743","9","2" +"744","1","1" +"745","10","5" +"746","5","2" +"747","4","2" +"748","5","7" +"749","6","7" +"750","3","6" +"751","6","9" +"752","4","7" +"753","1","4" +"754","1","5" +"755","8","9" +"756","1","4" +"757","5","9" +"758","9","9" +"759","1","8" +"760","3","6" +"761","9","8" +"762","3","8" +"763","6","7" +"764","3","3" +"765","3","3" +"766","3","6" +"767","5","9" +"768","3","3" +"769","4","2" +"770","3","3" +"771","3","8" +"772","3","6" +"773","3","6" +"774","3","3" +"775","4","3" +"776","2","4" +"777","7","5" +"778","9","2" +"779","3","3" +"780","5","7" +"781","6","3" +"782","1","4" +"783","1","4" +"784","5","9" +"785","3","1" +"786","1","8" +"787","4","7" +"788","7","5" +"789","4","7" +"790","6","8" +"791","3","8" +"792","4","7" +"793","7","7" +"794","3","8" +"795","1","1" +"796","10","1" +"797","6","9" +"798","10","5" +"799","2","4" +"800","5","2" +"801","3","6" +"802","6","9" +"803","1","4" +"804","7","5" +"805","6","7" +"806","7","2" +"807","10","1" +"808","5","7" +"809","1","4" +"810","10","1" +"811","1","1" +"812","2","1" +"813","3","6" +"814","10","1" +"815","5","3" +"816","3","6" +"817","4","2" +"818","1","1" +"819","3","3" +"820","1","8" +"821","9","9" +"822","3","6" +"823","3","3" +"824","10","1" +"825","1","5" +"826","1","4" +"827","3","8" +"828","3","6" +"829","7","7" +"830","9","9" +"831","9","9" +"832","3","6" +"833","5","7" +"834","3","3" +"835","6","8" +"836","5","5" +"837","1","1" +"838","8","9" +"839","6","3" +"840","4","3" +"841","1","4" +"842","5","3" +"843","6","7" +"844","8","9" +"845","4","7" +"846","6","2" +"847","4","2" +"848","7","2" +"849","6","3" +"850","8","7" +"851","5","5" +"852","2","4" +"853","8","7" +"854","7","7" +"855","1","8" +"856","1","5" +"857","1","1" +"858","4","3" +"859","2","4" +"860","3","6" +"861","9","2" +"862","2","4" +"863","7","7" +"864","8","9" +"865","4","3" +"866","6","7" +"867","1","4" +"868","1","4" +"869","10","5" +"870","4","7" +"871","10","8" +"872","6","8" +"873","6","2" +"874","4","3" +"875","1","1" +"876","3","8" +"877","5","2" +"878","3","6" +"879","5","7" +"880","1","4" +"881","7","5" +"882","3","6" +"883","8","9" +"884","7","2" +"885","3","6" +"886","2","1" +"887","6","8" +"888","5","7" +"889","10","1" +"890","1","4" +"891","10","8" +"892","2","4" +"893","3","6" +"894","8","7" +"895","2","4" +"896","6","7" +"897","5","5" +"898","2","4" +"899","9","8" +"900","9","9" +"901","7","5" +"902","4","7" +"903","2","4" +"904","10","8" +"905","5","9" +"906","1","8" +"907","3","3" +"908","3","1" +"909","5","2" +"910","2","4" +"911","6","7" +"912","1","4" +"913","5","7" +"914","3","6" +"915","3","1" +"916","9","8" +"917","3","6" +"918","2","4" +"919","6","9" +"920","1","5" +"921","3","6" +"922","8","9" +"923","1","5" +"924","9","2" +"925","7","5" +"926","3","3" +"927","6","5" +"928","2","4" +"929","1","8" +"930","7","5" +"931","6","8" +"932","7","7" +"933","8","2" +"934","3","1" +"935","1","8" +"936","4","3" +"937","10","5" +"938","1","8" +"939","3","6" +"940","6","2" +"941","10","1" +"942","10","1" +"943","7","5" +"944","4","2" +"945","6","9" +"946","10","1" +"947","4","2" +"948","4","2" +"949","2","4" +"950","6","9" +"951","1","4" +"952","3","6" +"953","1","1" +"954","6","7" +"955","6","9" +"956","6","9" +"957","6","7" +"958","5","9" +"959","10","8" +"960","3","8" +"961","6","2" +"962","1","1" +"963","9","2" +"964","6","3" +"965","8","7" +"966","6","8" +"967","1","4" +"968","6","7" +"969","2","4" +"970","10","5" +"971","5","5" +"972","5","2" +"973","2","4" +"974","7","5" +"975","9","2" +"976","3","8" +"977","6","8" +"978","7","5" +"979","5","5" +"980","10","1" +"981","3","6" +"982","6","9" +"983","10","5" +"984","6","7" +"985","7","5" +"986","5","9" +"987","3","6" +"988","10","1" +"989","3","8" +"990","1","4" +"991","7","2" +"992","3","1" +"993","5","2" +"994","2","4" +"995","7","7" +"996","2","1" +"997","4","3" +"998","5","2" +"999","6","7" +"1000","9","8" diff --git a/csv_data/country.csv b/csv_data/country.csv new file mode 100644 index 0000000..a5758c9 --- /dev/null +++ b/csv_data/country.csv @@ -0,0 +1,4 @@ +"name","countryCode" +"United States","US" +"United Kingdom","GB" +"Japan","JP" \ No newline at end of file diff --git a/csv_data/devices.csv b/csv_data/devices.csv new file mode 100644 index 0000000..5076ae0 --- /dev/null +++ b/csv_data/devices.csv @@ -0,0 +1,11 @@ +"deviceId","description" +"1","iPhone 4" +"2","iPhone 4S" +"3","iPhone 5" +"4","Galaxy S3" +"5","Galaxy S4" +"6","Nexus 4" +"7","Droid Razor" +"8","Droid DNA" +"9","HTC One" +"10","iPhone 3" \ No newline at end of file diff --git a/csv_data/tester_device.csv b/csv_data/tester_device.csv new file mode 100644 index 0000000..38f6eae --- /dev/null +++ b/csv_data/tester_device.csv @@ -0,0 +1,37 @@ +"testerId","deviceId" +"1","1" +"1","2" +"1","3" +"1","10" +"2","4" +"2","5" +"2","6" +"2","7" +"2","8" +"2","9" +"3","3" +"3","4" +"3","5" +"3","6" +"4","1" +"4","2" +"5","5" +"5","6" +"5","7" +"5","1" +"5","10" +"6","3" +"7","4" +"7","5" +"7","6" +"7","7" +"7","8" +"8","1" +"8","3" +"8","6" +"8","9" +"8","10" +"9","5" +"9","6" +"9","8" +"9","9" \ No newline at end of file diff --git a/csv_data/testers.csv b/csv_data/testers.csv new file mode 100644 index 0000000..c67fdcc --- /dev/null +++ b/csv_data/testers.csv @@ -0,0 +1,10 @@ +"testerId","firstName","lastName","country","lastLogin" +"1","Miguel","Bautista","US","2013-08-04 23:57:38" +"2","Michael","Lubavin","US","2013-07-12 13:27:18" +"3","Leonard","Sutton","GB","2013-07-16 21:17:28" +"4","Taybin","Rutkin","US","2013-01-01 10:57:38" +"5","Mingquan","Zheng","JP","2013-08-04 22:07:38" +"6","Stanley","Chen","GB","2013-08-04 21:57:38" +"7","Lucas","Lowry","JP","2013-07-12 23:57:38" +"8","Sean","Wellington","JP","2013-08-05 13:27:38" +"9","Darshini","Thiagarajan","GB","2013-08-05 15:00:38" \ No newline at end of file diff --git a/db.sqlite3 b/db.sqlite3 new file mode 100644 index 0000000..d3c528a Binary files /dev/null and b/db.sqlite3 differ diff --git a/findQA/ApplicationServices/TesterASerivice.py b/findQA/ApplicationServices/TesterASerivice.py new file mode 100644 index 0000000..5f58972 --- /dev/null +++ b/findQA/ApplicationServices/TesterASerivice.py @@ -0,0 +1,37 @@ +import logging +from findQA.DataAccessServices.TesterDAO import TesterDAO + + +class TesterAService(object): + """ + Application service designed to retrieve tester data + """ + + @staticmethod + def get_testers(countries=None, devices=None): + """ + retrieving tester records based on given countries and devices + @param countries: a list of country codes or None if use all countries + @type countries: list or None + @param devices: a list of devices' descriptions or None if use all devices + @type devices: list or None + @rtype: tuple + """ + assert isinstance(countries, list) or countries is None, type(countries) + assert isinstance(devices, list) or devices is None, type(list) + assert countries is None or len(countries) > 0 + assert devices is None or len(devices) > 0 + + if countries: + for country in countries: + if len(country) > 2: + TesterAService.__LOGGER.warning("invalid country code {0}".format(country)) + return + + return TesterDAO.get_testers_sorted_by_bugs_count( + countries, + devices, + ) + + __LOGGER = logging.getLogger(__name__) + """ logger for the current class """ diff --git a/findQA/ApplicationServices/__pycache__/TesterASerivice.cpython-36.pyc b/findQA/ApplicationServices/__pycache__/TesterASerivice.cpython-36.pyc new file mode 100644 index 0000000..cfc3fdb Binary files /dev/null and b/findQA/ApplicationServices/__pycache__/TesterASerivice.cpython-36.pyc differ diff --git a/findQA/ApplicationServices/__pycache__/__init__.cpython-36.pyc b/findQA/ApplicationServices/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..23388fe Binary files /dev/null and b/findQA/ApplicationServices/__pycache__/__init__.cpython-36.pyc differ diff --git a/findQA/DataAccessServices/TesterDAO.py b/findQA/DataAccessServices/TesterDAO.py new file mode 100644 index 0000000..fd1bac0 --- /dev/null +++ b/findQA/DataAccessServices/TesterDAO.py @@ -0,0 +1,55 @@ +import datetime +import logging + +from findQA.models import Country +from findQA.models import Device +from findQA.models import Tester +from findQA.models import Bug +from findQA.models import Tester_Device +from django.db.models import Q +from django.db.models import Count + + +class TesterDAO(object): + """ + Data access service designed to retrieve tester data + """ + + @staticmethod + def get_testers_sorted_by_bugs_count( + countries=None, + devices=None): + """ + retrieving tester objects based on given countries and devices + + @param countries: a list of country codes or None if use all countries + @type countries: list or None + @param devices: a list of devices' descriptions or None if use all devices + @type devices: list + @rtype: tuple + + @precondition: len(countries) > 0 + @precondition: len(devices) > 0 + """ + assert isinstance(countries, list) or countries is None, type(countries) + assert isinstance(devices, list) or devices is None, type(list) + assert countries is None or len(countries) > 0 + assert devices is None or len(devices) > 0 + + result = Tester.objects + if countries: + result = result.filter( + country__country_code__in=countries) + + if devices: + result = result.filter(tester_device__device_id__description__in=devices).annotate( + experience=Count('bug', filter=Q(bug__device_id__description__in=devices))).order_by( + '-experience') + else: + result = result.annotate( + experience=Count('bug')).order_by('-experience') + + return result + + __LOGGER = logging.getLogger(__name__) + """ logger for the current class """ diff --git a/findQA/DataAccessServices/__pycache__/TesterDAO.cpython-36.pyc b/findQA/DataAccessServices/__pycache__/TesterDAO.cpython-36.pyc new file mode 100644 index 0000000..db2aa03 Binary files /dev/null and b/findQA/DataAccessServices/__pycache__/TesterDAO.cpython-36.pyc differ diff --git a/findQA/DataAccessServices/__pycache__/__init__.cpython-36.pyc b/findQA/DataAccessServices/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..b581e68 Binary files /dev/null and b/findQA/DataAccessServices/__pycache__/__init__.cpython-36.pyc differ diff --git a/findQA/__pycache__/__init__.cpython-36.pyc b/findQA/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..cad132a Binary files /dev/null and b/findQA/__pycache__/__init__.cpython-36.pyc differ diff --git a/findQA/__pycache__/admin.cpython-36.pyc b/findQA/__pycache__/admin.cpython-36.pyc new file mode 100644 index 0000000..6d0dc58 Binary files /dev/null and b/findQA/__pycache__/admin.cpython-36.pyc differ diff --git a/findQA/__pycache__/apps.cpython-36.pyc b/findQA/__pycache__/apps.cpython-36.pyc new file mode 100644 index 0000000..7da4b91 Binary files /dev/null and b/findQA/__pycache__/apps.cpython-36.pyc differ diff --git a/findQA/__pycache__/models.cpython-36.pyc b/findQA/__pycache__/models.cpython-36.pyc new file mode 100644 index 0000000..00f4117 Binary files /dev/null and b/findQA/__pycache__/models.cpython-36.pyc differ diff --git a/findQA/__pycache__/tests.cpython-36.pyc b/findQA/__pycache__/tests.cpython-36.pyc new file mode 100644 index 0000000..03deb6f Binary files /dev/null and b/findQA/__pycache__/tests.cpython-36.pyc differ diff --git a/findQA/admin.py b/findQA/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/findQA/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/findQA/apps.py b/findQA/apps.py new file mode 100644 index 0000000..d42eb4a --- /dev/null +++ b/findQA/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class FindQAConfig(AppConfig): + name = 'findQA' diff --git a/findQA/management/__pycache__/__init__.cpython-36.pyc b/findQA/management/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..be222a7 Binary files /dev/null and b/findQA/management/__pycache__/__init__.cpython-36.pyc differ diff --git a/findQA/management/commands/__pycache__/__init__.cpython-36.pyc b/findQA/management/commands/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..46bf496 Binary files /dev/null and b/findQA/management/commands/__pycache__/__init__.cpython-36.pyc differ diff --git a/findQA/management/commands/__pycache__/find_testers.cpython-36.pyc b/findQA/management/commands/__pycache__/find_testers.cpython-36.pyc new file mode 100644 index 0000000..c3b6279 Binary files /dev/null and b/findQA/management/commands/__pycache__/find_testers.cpython-36.pyc differ diff --git a/findQA/management/commands/find_testers.py b/findQA/management/commands/find_testers.py new file mode 100644 index 0000000..d6e5566 --- /dev/null +++ b/findQA/management/commands/find_testers.py @@ -0,0 +1,59 @@ +import logging + +from django.core.management.base import BaseCommand +from findQA.ApplicationServices.TesterASerivice import TesterAService + +OPTION_ALL = ['ALL'] +""" option select all """ + + +class Command(BaseCommand): + """ command that help users to search testers by country and device """ + help = 'Find all testers who live in countries and use devices by given parameters.' + + def add_arguments(self, parser): + # Positional argument + parser.add_argument('-c', + '--country', + nargs='+', + default=OPTION_ALL, + help=("Country codes that you will be using to search tester, a comma-separated" + "list of country code, such as -c US,JP. If you wish to search by all" + "countries, use 'ALL'(by default). " + "Currently supported countries are: US, GB, and JP")) + parser.add_argument('-d', + '--device', + nargs='+', + default=OPTION_ALL, + help=("Device names that you will be using to search tester, a comma-separated" + "list of device descriptions, such as -d iPhone 4,iPhone 4S. If you wish" + "to search by all devices, use 'ALL'(by default). " + "Currently supported devices are: 'iPhone 4', 'iPhone 4S', 'iPhone 5', 'Galaxy S3'," + " 'Galaxy S4', 'Nexus 4', 'Droid Razor', 'Droid DNA', 'HTC One', and 'iPhone 3'." + )) + + def handle(self, *args, **options): + countries = options['country'] + devices = options['device'] + + # assign default values + countries_list = None + devices_list = None + + if countries != OPTION_ALL: + countries_list = list(set(countries[0].split(','))) + + if devices != OPTION_ALL: + devices_list = list(set(devices[0].split(','))) + + result = TesterAService.get_testers( + countries=countries_list, + devices=devices_list) + + for i in result: + print(','.join([i.first_name, i.last_name, i.country.country_code, str(i.experience)])) + + self.stdout.write(self.style.SUCCESS('Finished searching testers by given country(s) and device(s)!')) + + __LOGGER = logging.getLogger(__name__) + """ logger for the current class """ diff --git a/findQA/migrations/0001_initial.py b/findQA/migrations/0001_initial.py new file mode 100644 index 0000000..ca4b792 --- /dev/null +++ b/findQA/migrations/0001_initial.py @@ -0,0 +1,75 @@ +# Generated by Django 2.0.4 on 2018-04-08 22:03 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Bug', + fields=[ + ('bug_id', models.AutoField(primary_key=True, serialize=False)), + ], + options={ + 'ordering': ('bug_id',), + }, + ), + migrations.CreateModel( + name='Country', + fields=[ + ('name', models.CharField(max_length=100)), + ('country_code', models.CharField(max_length=2, primary_key=True, serialize=False)), + ], + options={ + 'ordering': ('name',), + }, + ), + migrations.CreateModel( + name='Device', + fields=[ + ('device_id', models.AutoField(primary_key=True, serialize=False)), + ('description', models.CharField(max_length=100)), + ], + options={ + 'ordering': ('device_id',), + }, + ), + migrations.CreateModel( + name='Tester', + fields=[ + ('tester_id', models.AutoField(primary_key=True, serialize=False)), + ('first_name', models.CharField(max_length=100)), + ('last_name', models.CharField(max_length=100)), + ('lastLogin', models.DateTimeField(auto_now_add=True)), + ('country', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='findQA.Country')), + ], + options={ + 'ordering': ('tester_id',), + }, + ), + migrations.CreateModel( + name='Tester_Device', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('device_id', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='findQA.Device')), + ('tester_id', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='findQA.Tester')), + ], + ), + migrations.AddField( + model_name='bug', + name='device_id', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='findQA.Device'), + ), + migrations.AddField( + model_name='bug', + name='tester_id', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='findQA.Tester'), + ), + ] diff --git a/findQA/migrations/0002_auto_20180409_0230.py b/findQA/migrations/0002_auto_20180409_0230.py new file mode 100644 index 0000000..27d58aa --- /dev/null +++ b/findQA/migrations/0002_auto_20180409_0230.py @@ -0,0 +1,19 @@ +# Generated by Django 2.0.4 on 2018-04-09 02:30 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('findQA', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='tester', + name='country', + field=models.ForeignKey(db_column='country_code', on_delete=django.db.models.deletion.PROTECT, to='findQA.Country'), + ), + ] diff --git a/findQA/migrations/0003_auto_20180409_0345.py b/findQA/migrations/0003_auto_20180409_0345.py new file mode 100644 index 0000000..adebd56 --- /dev/null +++ b/findQA/migrations/0003_auto_20180409_0345.py @@ -0,0 +1,34 @@ +# Generated by Django 2.0.4 on 2018-04-09 03:45 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('findQA', '0002_auto_20180409_0230'), + ] + + operations = [ + migrations.AlterField( + model_name='bug', + name='device_id', + field=models.ForeignKey(db_column='device_id', on_delete=django.db.models.deletion.PROTECT, to='findQA.Device'), + ), + migrations.AlterField( + model_name='bug', + name='tester_id', + field=models.ForeignKey(db_column='tester_id', on_delete=django.db.models.deletion.PROTECT, to='findQA.Tester'), + ), + migrations.AlterField( + model_name='tester_device', + name='device_id', + field=models.ForeignKey(db_column='device_id', on_delete=django.db.models.deletion.PROTECT, to='findQA.Device'), + ), + migrations.AlterField( + model_name='tester_device', + name='tester_id', + field=models.ForeignKey(db_column='tester_id', on_delete=django.db.models.deletion.PROTECT, to='findQA.Tester'), + ), + ] diff --git a/findQA/migrations/__pycache__/0001_initial.cpython-36.pyc b/findQA/migrations/__pycache__/0001_initial.cpython-36.pyc new file mode 100644 index 0000000..5ae84af Binary files /dev/null and b/findQA/migrations/__pycache__/0001_initial.cpython-36.pyc differ diff --git a/findQA/migrations/__pycache__/0002_auto_20180409_0230.cpython-36.pyc b/findQA/migrations/__pycache__/0002_auto_20180409_0230.cpython-36.pyc new file mode 100644 index 0000000..8f6a8e7 Binary files /dev/null and b/findQA/migrations/__pycache__/0002_auto_20180409_0230.cpython-36.pyc differ diff --git a/findQA/migrations/__pycache__/0003_auto_20180409_0345.cpython-36.pyc b/findQA/migrations/__pycache__/0003_auto_20180409_0345.cpython-36.pyc new file mode 100644 index 0000000..2e7b297 Binary files /dev/null and b/findQA/migrations/__pycache__/0003_auto_20180409_0345.cpython-36.pyc differ diff --git a/findQA/migrations/__pycache__/__init__.cpython-36.pyc b/findQA/migrations/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..696882b Binary files /dev/null and b/findQA/migrations/__pycache__/__init__.cpython-36.pyc differ diff --git a/findQA/models.py b/findQA/models.py new file mode 100644 index 0000000..5949594 --- /dev/null +++ b/findQA/models.py @@ -0,0 +1,45 @@ +from django.db import models + +# Create your models here. + + +class Country(models.Model): + name = models.CharField(max_length=100) + country_code = models.CharField(max_length=2, primary_key=True) + + class Meta: + ordering = ('name',) + + +class Device(models.Model): + device_id = models.AutoField(primary_key=True) + description = models.CharField(max_length=100) + + class Meta: + ordering = ('device_id',) + + +class Tester(models.Model): + tester_id = models.AutoField(primary_key=True) + first_name = models.CharField(max_length=100) + last_name = models.CharField(max_length=100) + lastLogin = models.DateTimeField(auto_now_add=True) + country = models.ForeignKey(Country, db_column='country_code', on_delete=models.PROTECT) + + class Meta: + ordering = ('tester_id',) + + +class Bug(models.Model): + bug_id = models.AutoField(primary_key=True) + tester_id = models.ForeignKey(Tester, db_column='tester_id', on_delete=models.PROTECT) + device_id = models.ForeignKey(Device, db_column='device_id', on_delete=models.PROTECT) + + class Meta: + ordering = ('bug_id',) + + +class Tester_Device(models.Model): + tester_id = models.ForeignKey(Tester, db_column='tester_id', on_delete=models.PROTECT) + device_id = models.ForeignKey(Device, db_column='device_id', on_delete=models.PROTECT) + diff --git a/findQA/tests.py b/findQA/tests.py new file mode 100644 index 0000000..932601f --- /dev/null +++ b/findQA/tests.py @@ -0,0 +1,159 @@ +import csv +import os +from django.test import TestCase +from findQA.models import Country +from findQA.models import Device +from findQA.models import Tester +from findQA.models import Bug +from findQA.models import Tester_Device +from findQA.ApplicationServices.TesterASerivice import TesterAService + + +class FindQATestCase(TestCase): + """ + class to test + """ + + def setUp(self): + script_path = os.path.dirname(__file__) + country_file_path = script_path + '/../csv_data/country.csv' + device_file_path = script_path + '/../csv_data/devices.csv' + tester_file_path = script_path + '/../csv_data/testers.csv' + bug_file_path = script_path + '/../csv_data/bugs.csv' + tester_device_file_path = script_path + '/../csv_data/tester_device.csv' + + # please do not change the import order + with open(country_file_path) as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + country_entity = Country(name=row['name'], country_code=row['countryCode']) + country_entity.save() + + with open(device_file_path) as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + device_entity = Device(device_id=row['deviceId'], description=row['description']) + device_entity.save() + + with open(tester_file_path) as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + country_entity = Country.objects.get(country_code=row['country']) + tester_entity = Tester(tester_id=row['testerId'], + first_name=row['firstName'], + last_name=row['lastName'], + country=country_entity, + lastLogin=row['lastLogin'] + ) + tester_entity.save() + + with open(bug_file_path) as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + tester_entity = Tester.objects.get(tester_id=row['testerId']) + device_entity = Device.objects.get(device_id=row['deviceId']) + bug_entity = Bug(bug_id=row['bugId'], + tester_id=tester_entity, + device_id=device_entity) + bug_entity.save() + + with open(tester_device_file_path) as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + tester_entity = Tester.objects.get(tester_id=row['testerId']) + device_entity = Device.objects.get(device_id=row['deviceId']) + tester_device_entity = Tester_Device( + tester_id=tester_entity, + device_id=device_entity) + tester_device_entity.save() + + def test_all_countries_all_devices(self): + """ + testing with all countries and devices selected + """ + selected_testers = TesterAService.get_testers() + all_bugs_count = Bug.objects.all().count() + total_bugs = 0 + for tester_entity in selected_testers: + total_bugs += tester_entity.experience + + self.assertEqual(total_bugs, all_bugs_count) + + def test_one_country_all_devices(self): + """ + testing with one country selected + """ + countries = ['US'] + selected_testers = TesterAService.get_testers(countries=countries) + all_testers = Tester.objects.filter(country__country_code__in=countries).count() + self.assertEqual(len(selected_testers), all_testers) + + def test_one_device_all_countries(self): + """ + testing with one device selected + """ + devices = ['Galaxy S3'] + selected_testers = TesterAService.get_testers(devices=devices) + + tester_id_list = set(i.tester_id for i in selected_testers) + all_testers = Tester.objects.filter(bug__device_id__description__in=devices).distinct() + self.assertEqual(len(selected_testers), len(all_testers)) + self.assertTrue(i.tester_id in tester_id_list for i in all_testers) + + def test_one_country_one_device(self): + """ + testing with one country and one device selected + """ + countries = ['US'] + devices = ['iPhone 4'] + selected_testers = TesterAService.get_testers(countries=countries, + devices=devices) + for selected_tester in selected_testers: + tester_id = selected_tester.tester_id + + expected_count = Bug.objects.filter(tester_id__tester_id=tester_id).filter( + device_id__description__in=devices + ).count() + self.assertEqual(selected_tester.experience, expected_count) + + def test_unsupported_country_code(self): + """ + testing with unsupported country code + """ + countries = ['CH'] + selected_testers_count = TesterAService.get_testers(countries=countries).count() + + self.assertEqual(selected_testers_count, 0) + + def test_unsupported_device(self): + """ + testing with unsupported device + """ + devices = ['Pixel 2'] + selected_testers_count = TesterAService.get_testers(devices=devices).count() + + self.assertEqual(selected_testers_count, 0) + + def test_country_code_with_unsupported_country(self): + """ + testing with country codes which contain unsupported country + """ + countries = ['US', 'CH'] + selected_testers = TesterAService.get_testers(countries=countries) + all_testers = Tester.objects.filter(country__country_code__in=countries).count() + self.assertEqual(len(selected_testers), all_testers) + + def test_device_with_unsupported_device(self): + """ + testing with devices which contain unsupported device + """ + devices = ['Pixel 2', 'iPhone 4'] + selected_testers = TesterAService.get_testers(devices=devices) + tester_id_list = set(i.tester_id for i in selected_testers) + all_testers = Tester.objects.filter(bug__device_id__description__in=devices).distinct() + self.assertEqual(len(selected_testers), len(all_testers)) + self.assertTrue(i.tester_id in tester_id_list for i in all_testers) + + + + diff --git a/findQA/views.py b/findQA/views.py new file mode 100644 index 0000000..273ae26 --- /dev/null +++ b/findQA/views.py @@ -0,0 +1,16 @@ +from django.conf.urls import url +from rest_framework.urlpatterns import format_suffix_patterns +from weathermail import apiviews, views + +app_name='weathermail' +urlpatterns = [ + url(r'^$', views.IndexView.as_view(), name='index'), + url(r'^api/$', apiviews.api_root), + url(r'^api/city/$', apiviews.PopulousCityList.as_view(), name='city-list'), + url(r'^api/sub/$', apiviews.SubscriptionList.as_view(), name='sub-list'), + url(r'^api/sub/available$', apiviews.SubscriptionEmailAvailable.as_view(), name='email-available'), +] + +# Allow for the format of the API response to be determined by a file extension. +# For example, http://localhost:8000/snippets/4.json will return a JSON response. +urlpatterns = format_suffix_patterns(urlpatterns) \ No newline at end of file diff --git a/load_data.py b/load_data.py new file mode 100644 index 0000000..b5531dd --- /dev/null +++ b/load_data.py @@ -0,0 +1,59 @@ +import csv +import os +import sys +from findQA.models import Country +from findQA.models import Device +from findQA.models import Tester +from findQA.models import Bug +from findQA.models import Tester_Device + +country_file_path = 'csv_data/country.csv' +device_file_path = 'csv_data/devices.csv' +tester_file_path = 'csv_data/testers.csv' +bug_file_path = 'csv_data/bugs.csv' +tester_device_file_path = 'csv_data/tester_device.csv' + +# please do not change the import order +with open(country_file_path) as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + country_entity = Country(name=row['name'], country_code=row['countryCode']) + country_entity.save() + +with open(device_file_path) as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + device_entity = Device(device_id=row['deviceId'], description=row['description']) + device_entity.save() + +with open(tester_file_path) as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + country_entity = Country.objects.get(country_code=row['country']) + tester_entity = Tester(tester_id=row['testerId'], + first_name=row['firstName'], + last_name=row['lastName'], + country=country_entity, + lastLogin=row['lastLogin'] + ) + tester_entity.save() + +with open(bug_file_path) as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + tester_entity = Tester.objects.get(tester_id = row['testerId']) + device_entity = Device.objects.get(device_id = row['deviceId']) + bug_entity = Bug(bug_id=row['bugId'], + tester_id=tester_entity, + device_id=device_entity) + bug_entity.save() + +with open(tester_device_file_path) as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + tester_entity = Tester.objects.get(tester_id=row['testerId']) + device_entity = Device.objects.get(device_id=row['deviceId']) + tester_device_entity = Tester_Device( + tester_id=tester_entity, + device_id=device_entity) + tester_device_entity.save() diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..c8da569 --- /dev/null +++ b/manage.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "matchQA.settings") + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) diff --git a/matchQA/__pycache__/__init__.cpython-36.pyc b/matchQA/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..5887b98 Binary files /dev/null and b/matchQA/__pycache__/__init__.cpython-36.pyc differ diff --git a/matchQA/__pycache__/settings.cpython-36.pyc b/matchQA/__pycache__/settings.cpython-36.pyc new file mode 100644 index 0000000..17bbe0f Binary files /dev/null and b/matchQA/__pycache__/settings.cpython-36.pyc differ diff --git a/matchQA/__pycache__/urls.cpython-36.pyc b/matchQA/__pycache__/urls.cpython-36.pyc new file mode 100644 index 0000000..8c838fe Binary files /dev/null and b/matchQA/__pycache__/urls.cpython-36.pyc differ diff --git a/matchQA/__pycache__/wsgi.cpython-36.pyc b/matchQA/__pycache__/wsgi.cpython-36.pyc new file mode 100644 index 0000000..714a925 Binary files /dev/null and b/matchQA/__pycache__/wsgi.cpython-36.pyc differ diff --git a/matchQA/settings.py b/matchQA/settings.py new file mode 100644 index 0000000..f8ac0ce --- /dev/null +++ b/matchQA/settings.py @@ -0,0 +1,122 @@ +""" +Django settings for matchQA project. + +Generated by 'django-admin startproject' using Django 2.0.4. + +For more information on this file, see +https://docs.djangoproject.com/en/2.0/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/2.0/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = '7js#^1474zv+e23nh^#ohjf&@6e_h!t3(ek_*1$p^cc40l+$gy' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'findQA.apps.FindQAConfig', + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'matchQA.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'matchQA.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/2.0/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + + +# Password validation +# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/2.0/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +# this is to eliminate the time zone warning when we are not using datetime +USE_TZ = False + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/2.0/howto/static-files/ + +STATIC_URL = '/static/' diff --git a/matchQA/urls.py b/matchQA/urls.py new file mode 100644 index 0000000..8d108bf --- /dev/null +++ b/matchQA/urls.py @@ -0,0 +1,21 @@ +"""matchQA URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/2.0/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] diff --git a/matchQA/wsgi.py b/matchQA/wsgi.py new file mode 100644 index 0000000..c66b0c1 --- /dev/null +++ b/matchQA/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for matchQA project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "matchQA.settings") + +application = get_wsgi_application() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..4884cb7 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +Django==2.0.4 +pytz==2018.3 \ No newline at end of file