Ejemplo n.º 1
0
    def testExtractPackageSpecUnixWindows(self):
        projectPath = 'D:/Development/Python/seqdiagbuilder'
        classFilePath = 'D:\\Development\\Python\\seqdiagbuilder\\testclasses\\subtestpackage\\'

        SeqDiagBuilder.activate(projectPath, '', '')
        self.assertEqual('testclasses.subtestpackage.',
                         SeqDiagBuilder._extractPackageSpec(classFilePath))
Ejemplo n.º 2
0
    def _buildFullDateAndTimeStrings(self, commandDic, timezoneStr):
        '''
		This method ensures that the full command string is unified whatever the completness of the
		dated/time components specified in the request by the user.

		Ex: btc usd 1/1 bitfinex or btc usd 1/01/18 bitfinex or btc usd 1/1 12:23 bitfinex all return
			a full commaand of btc usd 01/01/18 00:00 bitfinex, btc usd 01/01/18 12:23 bitfinex
			respectively.

		This is important since the ful command string is what is stored in the command history list, with
		no duplicates. Otherwxise, btc usd 1/1 00:00 bitfinex and btc usd 01/01/18 00:00 bitfinex would
		be stored as 2 entries !

		:param commandDic:
		:param timezoneStr:
		:seqdiag_return requestDateDMY, requestDateHM
		:return:
		'''
        day = commandDic[CommandPrice.DAY]
        month = commandDic[CommandPrice.MONTH]
        year = commandDic[CommandPrice.YEAR]
        hour = commandDic[CommandPrice.HOUR]
        minute = commandDic[CommandPrice.MINUTE]

        requestDateDMY, requestDateHM = DateTimeUtil.formatPrintDateTimeFromStringComponents(
            day, month, year, hour, minute, timezoneStr,
            self.configurationMgr.dateTimeFormat)

        from seqdiagbuilder import SeqDiagBuilder
        SeqDiagBuilder.recordFlow()

        return requestDateDMY, requestDateHM
Ejemplo n.º 3
0
    def testExtractPackageSpecUnixUnix(self):
        projectPath = 'D:/Development/Python/seqdiagbuilder'
        classFilePath = 'D:/Development/Python/seqdiagbuilder/testclasses/subtestpackage/'

        SeqDiagBuilder.activate(projectPath, '', '')
        self.assertEqual('testclasses.subtestpackage.',
                         SeqDiagBuilder._extractPackageSpec(classFilePath))
Ejemplo n.º 4
0
    def analyse(self):
        '''

        :seqdiag_return Analysis
        :return:
        '''
        SeqDiagBuilder.recordFlow()
Ejemplo n.º 5
0
    def doC1(self, p1):
        '''
        This the first leaf method of our sequence diagram.
        '''

        # The next instruction causes SeqDiagBuilder to record the
        # whole control flow which conducted to call the present method.
        SeqDiagBuilder.recordFlow()
Ejemplo n.º 6
0
    def d2(self, d2_p1):
        '''

        :param d2_p1:
        :seqdiag_return Dd2Return
        :return:
        '''
        SeqDiagBuilder.recordFlow()
Ejemplo n.º 7
0
    def d1(self, d1_p1):
        '''

        :param d1_p1:
        :seqdiag_return Dd1Return
        :return:
        '''
        SeqDiagBuilder.recordFlow()
Ejemplo n.º 8
0
    def getCurrentPrice(self, crypto, fiat, exchange):
        url = "https://min-api.cryptocompare.com/data/price?fsym={}&tsyms={}&e={}".format(
            crypto, fiat, exchange)
        resultData = ResultData()

        resultData.setValue(ResultData.RESULT_KEY_CRYPTO, crypto)
        resultData.setValue(ResultData.RESULT_KEY_FIAT, fiat)
        resultData.setValue(ResultData.RESULT_KEY_EXCHANGE, exchange)
        resultData.setValue(ResultData.RESULT_KEY_PRICE_TYPE,
                            resultData.PRICE_TYPE_RT)

        try:
            if self.ctx == None:
                #here, run in QPython under Python 3.2
                webURL = urllib.request.urlopen(url)
            else:
                webURL = urllib.request.urlopen(url, context=self.ctx)
        except HTTPError as e:
            resultData.setValue(
                ResultData.RESULT_KEY_ERROR_MSG,
                'ERROR - could not complete request ' + url + '. Reason: ' +
                str(e.reason))
        except URLError as e:
            resultData.setValue(
                ResultData.RESULT_KEY_ERROR_MSG,
                'ERROR - could not complete request ' + url + '. Reason: ' +
                str(e.reason))
        except:
            the_type, the_value, the_traceback = sys.exc_info()
            resultData.setValue(
                ResultData.RESULT_KEY_ERROR_MSG,
                'ERROR - could not complete request ' + url + '. Reason: ' +
                str(the_type))
        else:
            page = webURL.read()
            soup = BeautifulSoup(page, 'html.parser')
            dic = json.loads(soup.prettify())

            if fiat in dic:
                resultData.setValue(ResultData.RESULT_KEY_PRICE_TIME_STAMP,
                                    DateTimeUtil.utcNowTimeStamp())
                resultData.setValue(
                    ResultData.RESULT_KEY_PRICE, dic[fiat]
                )  #current price is indexed by fiat symbol in returned dic
            else:
                resultData = self._handleProviderError(dic,
                                                       resultData,
                                                       url,
                                                       crypto,
                                                       fiat,
                                                       exchange,
                                                       isRealTime=True)

        from seqdiagbuilder import SeqDiagBuilder
        SeqDiagBuilder.recordFlow()

        return resultData
Ejemplo n.º 9
0
    def _buildFullDateAndTimeStrings(self, commandDic, timezoneStr):
        '''
        This method ensures that the full command string is unified whatever the completness of the
        dated/time components specified in the request by the user.

        Ex: btc usd 1/1 bitfinex or btc usd 1/01/18 bitfinex or btc usd 1/1 12:23 bitfinex all return
            a full commaand of btc usd 01/01/18 00:00 bitfinex, btc usd 01/01/18 12:23 bitfinex
            respectively.

        This is important since the ful command string is what is stored in the command history list, with
        no duplicates. Otherwxise, btc usd 1/1 00:00 bitfinex and btc usd 01/01/18 00:00 bitfinex would
        be stored as 2 entries !

        :param commandDic:
        :param timezoneStr:
        :seqdiag_return requestDateDMY, requestDateHM
        :return:
        '''
        dayInt = int(commandDic[CommandPrice.DAY])
        monthInt = int(commandDic[CommandPrice.MONTH])
        year = commandDic[CommandPrice.YEAR]

        if year == None:
            now = DateTimeUtil.localNow(timezoneStr)
            yearInt = now.year
        else:
            yearInt = int(year)

        hour = commandDic[CommandPrice.HOUR]
        minute = commandDic[CommandPrice.MINUTE]

        if hour != None and minute != None:
            # hour can not exist without minute and vice versa !
            hourInt = int(hour)
            minuteInt = int(minute)
        else:
            hourInt = 0
            minuteInt = 0

        requestArrowDate = DateTimeUtil.dateTimeComponentsToArrowLocalDate(
            dayInt, monthInt, yearInt, hourInt, minuteInt, 0, timezoneStr)
        dateTimeComponentSymbolList, separatorsList, dateTimeComponentValueList = DateTimeUtil.getFormattedDateTimeComponents(
            requestArrowDate, self.configurationMgr.dateTimeFormat)
        dateSeparator = separatorsList[0]
        timeSeparator = separatorsList[1]
        requestDateDMY = dateTimeComponentValueList[0] + dateSeparator + dateTimeComponentValueList[1] + dateSeparator + \
                         dateTimeComponentValueList[2]
        requestDateHM = dateTimeComponentValueList[
            3] + timeSeparator + dateTimeComponentValueList[4]

        from seqdiagbuilder import SeqDiagBuilder
        SeqDiagBuilder.recordFlow()

        return requestDateDMY, requestDateHM
Ejemplo n.º 10
0
    def test__buildClassNoteSection(self):
        participantDocOrderedDic = collections.OrderedDict()
        participantDocOrderedDic[
            'Controller'] = 'Entry point of the business layer'
        participantDocOrderedDic['Requester'] = 'Parses the user commands'
        participantDocOrderedDic['CommandPrice'] = ''
        participantDocOrderedDic['Processor'] = ''
        participantDocOrderedDic[
            'PriceRequester'] = 'Obtains the RT or historical rates from the Cryptocompare web site'
        maxNoteLineLen = 30

        participantSection = SeqDiagBuilder._buildParticipantSection(
            participantDocOrderedDic, maxNoteLineLen)
        self.assertEqual(
            '''participant Controller
	/note over of Controller
		Entry point of the business layer
	end note
participant Requester
	/note over of Requester
		Parses the user commands
	end note
participant CommandPrice
participant Processor
participant PriceRequester
	/note over of PriceRequester
		Obtains the RT or historical rates from the
		Cryptocompare web site
	end note
''', participantSection)
Ejemplo n.º 11
0
    def test_splitNoteToLinesEmptyNote(self):
        note = ''
        maxNoteLineLen = 30

        multilineNote = SeqDiagBuilder._splitNoteToLines(note, maxNoteLineLen)

        self.assertEqual(len(multilineNote), 0)
Ejemplo n.º 12
0
    def test_splitNoteToLinesTwoWordsNoteLenEqualsMaxNoteLineLen(self):
        note = '12345678911234 567892123456789'
        maxNoteLineLen = 30

        multilineNote = SeqDiagBuilder._splitNoteToLines(note, maxNoteLineLen)

        self.assertEqual(len(multilineNote), 1)
        self.assertEqual(multilineNote[0], '12345678911234 567892123456789')
    def test_splitNoteToLinesLargeNote(self):
        note = 'ERROR - :seqdiag_loop_start tag located on line 53 of file containing class ClassLoopTagOnMethodNotInRecordFlow is placed on an instruction calling method doC4NotRecordedInFlow() which is not part of the execution flow recorded by SeqDiagBuilder.'
        maxNoteLineLen = 150

        multilineNote = SeqDiagBuilder._splitNoteToLines(note, maxNoteLineLen)

        self.assertEqual(len(multilineNote), 2)
        self.assertEqual(multilineNote[0], 'ERROR - :seqdiag_loop_start tag located on line 53 of file containing class ClassLoopTagOnMethodNotInRecordFlow is placed on an instruction calling')
        self.assertEqual(multilineNote[1], 'method doC4NotRecordedInFlow() which is not part of the execution flow recorded by SeqDiagBuilder.')
Ejemplo n.º 14
0
    def test_splitNoteToLines(self):
        note = 'a long class description. Which occupies several lines.'
        maxNoteLineLen = 30

        multilineNote = SeqDiagBuilder._splitNoteToLines(note, maxNoteLineLen)

        self.assertEqual(len(multilineNote), 2)
        self.assertEqual(multilineNote[0], 'a long class description.')
        self.assertEqual(multilineNote[1], 'Which occupies several lines.')
Ejemplo n.º 15
0
    def test_splitNoteToLinesTwoWordsFirstAndSecondEqualsMaxLenPlusOne(self):
        note = '1234567891123456789212345678931 1234567891123456789212345678931'
        maxNoteLineLen = 30

        multilineNote = SeqDiagBuilder._splitNoteToLines(note, maxNoteLineLen)

        self.assertEqual(len(multilineNote), 2)
        self.assertEqual(multilineNote[0], '1234567891123456789212345678931')
        self.assertEqual(multilineNote[1], '1234567891123456789212345678931')
    def test_splitLongWarningWithBackslashNToFormattedLines(self):
        longWarning = "No control flow recorded.\nMethod activate() called with arguments projectPath=<D:\Development\Python\seqdiagbuilder>, entryClass=<Caller>, entryMethod=<call>, classArgDic=<{'FileReader_1': ['testfile.txt'], 'FileReader_2': ['testfile2.txt']}>: True.\nMethod recordFlow() called: True\nSpecified entry point: Caller.call reached: False."

        multiLineFormattedWarning = SeqDiagBuilder._splitLongWarningToFormattedLines(longWarning)

        self.assertEqual(
"""<b><font color=red size=14>  No control flow recorded.</font></b>
<b><font color=red size=14>  Method activate() called with arguments projectPath=<D:\Development\Python\seqdiagbuilder>, entryClass=<Caller>, entryMethod=<call>, classArgDic=<{'FileReader_1': ['testfile.txt'], 'FileReader_2': ['testfile2.txt']}>: True.</font></b>
<b><font color=red size=14>  Method recordFlow() called: True</font></b>
<b><font color=red size=14>  Specified entry point: Caller.call reached: False.</font></b>
""", multiLineFormattedWarning)
    def testWithSlash(self):
        from configurationmanager import ConfigurationManager
        from guioutputformater import GuiOutputFormater
        from controller import Controller
        import os

        SeqDiagBuilder.activate('Controller', 'getPrintableResultForInput')  # activate sequence diagram building

        if os.name == 'posix':
            FILE_PATH = '/sdcard/cryptopricer.ini'
        else:
            FILE_PATH = 'c:\\temp\\cryptopricer.ini'

        configMgr = ConfigurationManager(FILE_PATH)
        controller = Controller(GuiOutputFormater(configMgr), configMgr)

        inputStr = 'mcap btc 0 all'
        _, _, _, _ = controller.getPrintableResultForInput(
            inputStr)

        SeqDiagBuilder.createDiagram('c:/temp', 'GUI', None, 20)
Ejemplo n.º 18
0
def createSeqDiagram():
    a = ClassA()
    currentdir = os.path.dirname(
        os.path.abspath(inspect.getfile(inspect.currentframe())))

    SeqDiagBuilder.activate(projectPath=currentdir,
                            entryClass='ClassA',
                            entryMethod='doWork')

    a.doWork(1)

    SeqDiagBuilder.createDiagram(targetDriveDirName='c:/temp',
                                 actorName='User')
    SeqDiagBuilder.deactivate()
Ejemplo n.º 19
0
 def j(self):
     SeqDiagBuilder.recordFlow()
    def getContentAsListFromSuper(self):
        SeqDiagBuilder.recordFlow()

        return super().getContentAsList()
    def getContentAsList(self):
        SeqDiagBuilder.recordFlow()

        return self.content
Ejemplo n.º 22
0
    def getFullCommandString(self, resultData):
        '''
        Recreate the full command string corresponding to a full or partial price request entered by the user.

        The full command string contains a full date and time which is formatted according to the date time
        format as specified in the configuration file. Even if the request only contained partial date time info,
        the full command string ccontains a full date time specification.

        The full command string will be stored in the command history list so it can be replayed or saved to file.
        An empty string is returned if the command generated an error (empty string will not be added to history !

        In case an option to the command with save mode is in effect - for example -vs -, then the full
        command with the save mode option is returned aswell. Othervise, if no command option in save mode
        is in effect (no option or -v for example), then None is returned as second return value.

        :param resultData: result of the last full or partial request
        :seqdiag_return printResult, fullCommandStr, fullCommandStrWithOptions, fullCommandStrWithSaveModeOptions
        :return: 1/ full command string with no command option corresponding to a full or partial price request
                    entered by the user or empty string if the command generated an error msg.
                 2/ full request command with any non save command option
                 3/ full command string with command option in save mode or none if no command option in save mode
                    is in effect or if the command option generated a warning.

                 Ex: 1/ eth usd 0 bitfinex
                     2/ None
                     3/ eth usd 0 bitfinex -vs0.1eth

                     1/ eth usd 0 bitfinex
                     2/ eth usd 0 bitfinex -v0.1btc (even if warning generated !)
                     3/ None (-v0.1btc command was entered, which generated a warning)

                     1/ eth usd 0 bitfinex
                     2/ None (no value command in effect)
                     3/ None (no value command with save option in effect)
        '''
        if resultData.isError():
            return '', None, None

        commandDic = resultData.getValue(
            resultData.RESULT_KEY_INITIAL_COMMAND_PARMS)
        priceType = resultData.getValue(resultData.RESULT_KEY_PRICE_TYPE)

        if priceType == resultData.PRICE_TYPE_RT:
            fullCommandStr = commandDic[CommandPrice.CRYPTO] + ' ' + \
                             commandDic[CommandPrice.FIAT] + ' 0 ' + \
                             commandDic[CommandPrice.EXCHANGE]
        else:
            requestDateDMY, requestDateHM = self._buildFullDateAndTimeStrings(
                commandDic, self.configurationMgr.localTimeZone)

            fullCommandStr = commandDic[CommandPrice.CRYPTO] + ' ' + \
                             commandDic[CommandPrice.FIAT] + ' ' + \
                             requestDateDMY + ' ' + \
                             requestDateHM + ' ' + \
                             commandDic[CommandPrice.EXCHANGE]

        fullCommandStrWithSaveModeOptions = None
        fullCommandStrWithOptions = None

        if resultData.getValue(resultData.RESULT_KEY_PRICE_VALUE_SAVE):
            if not resultData.containsWarning(
                    resultData.WARNING_TYPE_COMMAND_VALUE):
                #in case the value command generated a warning, if the value command data contains a crypto or fiat
                #different from the crypto or fiat of tthe request, the fullCommandStrWithSaveModeOptions remains
                #None and wont't be stored in the request history list of the GUI !
                fullCommandStrWithSaveModeOptions = fullCommandStr + ' -vs' + commandDic[
                    CommandPrice.PRICE_VALUE_AMOUNT] + commandDic[
                        CommandPrice.PRICE_VALUE_SYMBOL]
        else:
            valueCommandAmountStr = commandDic[CommandPrice.PRICE_VALUE_AMOUNT]
            valueCommandSymbolStr = commandDic[CommandPrice.PRICE_VALUE_SYMBOL]
            if valueCommandAmountStr and valueCommandSymbolStr:
                #even in case the value command generated a warning, it will be displayed in the status bar !
                fullCommandStrWithOptions = fullCommandStr + ' -v' + valueCommandAmountStr + valueCommandSymbolStr

        from seqdiagbuilder import SeqDiagBuilder
        SeqDiagBuilder.recordFlow()

        return fullCommandStr, fullCommandStrWithOptions, fullCommandStrWithSaveModeOptions
Ejemplo n.º 23
0
    def _buildFullCommandPriceOptionalParmsDic(self, optionalParmList):
        '''
        Since DAY_MONTH_YEAR, HOUR_MINUTE and EXCHANGE can be provided in any order after CRYPTO
        and FIAT, this method differentiate them build an optional command price parm data dictionary
        with the right key. This dictionary will be added to the CommandPrice parmData dictionary.

        :seqdiag_return optionalParsedParmDataDic
        :return optionalParsedParmDataDic or None in case of syntax error.
        '''
        '''
        ° 0 is legal for both date and time parms. Zero for either date or/and time means now, real time !
        ° Date must be 0 or contain a '/'.
        ° Time must be composed of two numerical groups separated by ':', the second group being a 2 digits
          group. Note 00:00 does not mean now, but midnight !
        ° Exchange name must start with a letter. May contain digits.

        Ex:
        Date can be 0, accepted. 1, rejected. 10, rejected. 01, rejected. 01/1, accepted. 01/10, accepted. 
                    1/1, accepted. 1/10, accepted. 01/12/16, accepted. 01/12/2015, accepted. 
        Hour minute can be 0, rejected. 1, rejected. 10, rejected. 01, rejected. 01:1, rejected. 01:01, accepted. 
                           01:10, accepted. 1:10, accepted. 00:00, accepted. 0:00, accepted. 0:0, rejected. 
        '''

        COMMAND_OR_OPTION = 'commandOrOption'

        # changed r"\d+/\d+(?:/\d+)*|^0$" into r"\d+/\d+(?:/\d+)*|^\d+$" was required so
        # that a full request like btc usd 1 12:45 bitfinex does generate an ERROR - date not valid
        # in CommandPrice. With the old versionk of th pattern, CommandPrice.DAY_MONTH_YEAR was none,
        # which was considered like a valid full request with only the time providded, a feature which
        # was not supported before !
        #
        # So, allowing the user to provide only the time in the full request implied that we are
        # more permissive at the level of the Requester in order for CommandPrice to be able
        # to correctly identify the invalid date/time full request component in the form of
        # D HH:MM or DD HH:MM
        patternCommandDic = {
            r"\d+/\d+(?:/\d+)*|^\d+$":
            CommandPrice.DAY_MONTH_YEAR,
            r"\d+:\d\d":
            CommandPrice.HOUR_MINUTE,
            r"[A-Za-z]+":
            CommandPrice.EXCHANGE,
            r"(?:-[vV])([sS]?)([\w\d/:\.]+)":
            CommandPrice.PRICE_VALUE_DATA,
            r"(?:-[vV])([sS]?)([\w\d/:\.]+)" + COMMAND_OR_OPTION:
            CommandPrice.PRICE_VALUE_SAVE,
            r"(-[^vV]{1}[sS]?)([\w\d/:\.]+)":
            CommandPrice.
            UNSUPPORTED_COMMAND_DATA,  # see scn capture https://pythex.org/ in Evernote for test of this regexp !
            r"(-[^vV]{1}[sS]?)([\w\d/:\.]+)" + COMMAND_OR_OPTION:
            CommandPrice.UNSUPPORTED_COMMAND
        }

        optionalParsedParmDataDic = {}

        for pattern in patternCommandDic.keys():
            for group in optionalParmList:
                if group and re.search(pattern, group):
                    if patternCommandDic[
                            pattern] not in optionalParsedParmDataDic:
                        #if for example DMY already found in optional full command parms,
                        #it will not be overwritten ! Ex: 12/09/17 0: both token match DMY
                        #pattern !
                        data, optionalCommandModifier = self._extractData(
                            pattern, group)
                        if data != None:
                            optionalParsedParmDataDic[
                                patternCommandDic[pattern]] = data
                            patternCommandModifierKey = pattern + COMMAND_OR_OPTION
                            if optionalCommandModifier != None and optionalCommandModifier != '':
                                optionalParsedParmDataDic[patternCommandDic[
                                    patternCommandModifierKey]] = optionalCommandModifier
                            elif patternCommandModifierKey in optionalParsedParmDataDic.keys(
                            ):
                                optionalParsedParmDataDic[patternCommandDic[
                                    patternCommandModifierKey]] = None

                        else:
                            #full command syntax error !
                            return None

        from seqdiagbuilder import SeqDiagBuilder
        SeqDiagBuilder.recordFlow()

        return optionalParsedParmDataDic
Ejemplo n.º 24
0
    def _getHistoDayPriceAtUTCTimeStamp(self, crypto, fiat, timeStampUTC,
                                        exchange, resultData):
        '''

        :param crypto:
        :param fiat:
        :param timeStampUTC:
        :param exchange:
        :param resultData:
        :seqdiag_return ResultData
        :return:
        '''
        timeStampUTCStr = str(timeStampUTC)
        url = "https://min-api.cryptocompare.com/data/histoday?fsym={}&tsym={}&limit=1&aggregate=1&toTs={}&e={}".format(
            crypto, fiat, timeStampUTCStr, exchange)
        resultData.setValue(ResultData.RESULT_KEY_PRICE_TYPE,
                            resultData.PRICE_TYPE_HISTO_DAY)

        try:
            if self.ctx == None:
                #here, run in QPython under Python 3.2
                webURL = urllib.request.urlopen(url)
            else:
                webURL = urllib.request.urlopen(url, context=self.ctx)
        except HTTPError as e:
            resultData.setValue(
                ResultData.RESULT_KEY_ERROR_MSG,
                'ERROR - could not complete request ' + url + '. Reason: ' +
                str(e.reason))
        except URLError as e:
            resultData.setValue(
                ResultData.RESULT_KEY_ERROR_MSG,
                'ERROR - could not complete request ' + url + '. Reason: ' +
                str(e.reason))
        except:
            the_type, the_value, the_traceback = sys.exc_info()
            resultData.setValue(
                ResultData.RESULT_KEY_ERROR_MSG,
                'ERROR - could not complete request ' + url + '. Reason: ' +
                str(the_type))
        else:
            page = webURL.read()
            soup = BeautifulSoup(page, 'html.parser')
            dic = json.loads(soup.prettify())
            if dic['Data'] != []:
                dataDic = dic['Data'][IDX_DATA_ENTRY_TO]
                resultData.setValue(ResultData.RESULT_KEY_PRICE_TIME_STAMP,
                                    dataDic['time'])
                resultData.setValue(ResultData.RESULT_KEY_PRICE,
                                    dataDic['close'])
            else:
                resultData = self._handleProviderError(dic,
                                                       resultData,
                                                       url,
                                                       crypto,
                                                       fiat,
                                                       exchange,
                                                       isRealTime=False)

        from seqdiagbuilder import SeqDiagBuilder
        SeqDiagBuilder.recordFlow()

        return resultData
Ejemplo n.º 25
0
    def getFullCommandString(self, resultData):
        '''
		Recreate the full command string corresponding to a full or partial price request entered by the user.

		The full command string no options contains a full date and time which is formatted according to the date time
		format as specified in the configuration file. Even if the request only contained partial date time info,
		the full command string no options contains a full date time specification.

		The full command string no options will be stored in the command history list so it can be replayed or
		saved to file. An empty string is returned if the command generated an error (an empty string will not
		be added to the history list !)

		In case an option with save mode is added to the command - for example -vs -, then the full
		command with the save mode option is returned as well (fullCommandStrWithSaveOptionsForHistoryList).
		In the GUI, the full command with save mode option will	replace the corresponding full command string
		no options (fullCommandStrNoOptions) in the command history list. If the added command option is not
		in save mode (no option or -v... or -f... for example), then None is returned for
		fullCommandStrWithSaveOptionsForHistoryList	and	the corresponding full command string no options
		(fullCommandStrNoOptions) will NOT have	to be replaced in the command history list.

		Finally, what is the usefulness of the fullCommandStrWithNoSaveOptions returned string ? It
		serves to differentiate a partial request with option(s) without save mode from a full request
		with with option(s) without save mode. In case of partial request, the status bar content is
		different from in the case of a full request.

		:param copyResultToClipboard:
		:param resultData: result of the last full or partial request
		:seqdiag_return printResult, fullCommandStrNoOptions, fullCommandStrWithNoSaveOptions, fullCommandStrWithSaveOptionsForHistoryList, fullCommandStrForStatusBar

		:return: 1/ full command string with no command option corresponding to a full or partial price request
					entered by the user or empty string if the command generated an error msg.
				 2/ full request command with any non save command option
				 3/ full command string with command option in save mode or none if no command option in save mode
					is in effect or if the command option generated a warning.
				 4/ full command string for status bar

				 Ex: 1/ eth usd 0 bitfinex
					 2/ None
					 3/ eth usd 0 bitfinex -vs0.1eth

					 1/ eth usd 0 bitfinex
					 2/ eth usd 0 bitfinex -v0.1btc (even if warning generated !)
					 3/ None (-v0.1btc command was entered, which generated a warning)

					 1/ eth usd 0 bitfinex
					 2/ None (no value command in effect)
					 3/ None (no value command with save option in effect)
		'''
        if not resultData.noError():
            return '', None, None, None

        commandDic = resultData.getValue(
            resultData.RESULT_KEY_INITIAL_COMMAND_PARMS)
        priceType = resultData.getValue(resultData.RESULT_KEY_PRICE_TYPE)

        if priceType == resultData.PRICE_TYPE_RT:
            fullCommandStrNoOptions = commandDic[CommandPrice.CRYPTO] + ' ' + \
                    commandDic[CommandPrice.UNIT] + ' 0 ' + \
                    commandDic[CommandPrice.EXCHANGE]
        else:
            requestDateDMY, requestDateHM = self._buildFullDateAndTimeStrings(
                commandDic, self.configurationMgr.localTimeZone)

            fullCommandStrNoOptions = commandDic[CommandPrice.CRYPTO] + ' ' + \
                    commandDic[CommandPrice.UNIT] + ' ' + \
                    requestDateDMY + ' ' + \
                    requestDateHM + ' ' + \
                    commandDic[CommandPrice.EXCHANGE]

        # the three next full command string, unless they are set to None, all start with
        # the content of fullCommandStrNoOptions

        fullCommandStrWithSaveOptionsForHistoryList = fullCommandStrNoOptions
        fullCommandStrWithNoSaveOptions = fullCommandStrNoOptions
        fullCommandStrForStatusBar = fullCommandStrNoOptions

        # handling value option

        if resultData.getValue(resultData.RESULT_KEY_OPTION_VALUE_CRYPTO):
            # if the ResultData contains the computed value option crypto amount,
            # this means that the specified value option is valid and so has to be added
            # to the returned GuiOutputFormatter fields !
            fullCommandStrWithNoSaveOptions, \
            fullCommandStrWithSaveOptionsForHistoryList, \
            fullCommandStrForStatusBar = self._addOptionValueInfo(resultData,
                           commandDic,
                           fullCommandStrWithNoSaveOptions,
                           fullCommandStrWithSaveOptionsForHistoryList,
                           fullCommandStrForStatusBar)

        # handling fiat option

        fiatOptionSymbol = commandDic[CommandPrice.OPTION_FIAT_SYMBOL]
        fullCommandStrForStatusBarFiatComplement = ''

        if fiatOptionSymbol:
            fullCommandStrWithNoSaveOptions, \
            fullCommandStrWithSaveOptionsForHistoryList, \
            fullCommandStrForStatusBar, \
            fullCommandStrForStatusBarFiatComplement = self._addOptionFiatInfo(resultData,
                               commandDic,
                               fiatOptionSymbol,
                               fullCommandStrWithNoSaveOptions,
                               fullCommandStrWithSaveOptionsForHistoryList,
                               fullCommandStrForStatusBar)

        # handling price option

        priceOptionAmountStr = commandDic[CommandPrice.OPTION_PRICE_AMOUNT]

        if priceOptionAmountStr:
            fullCommandStrWithNoSaveOptions, \
            fullCommandStrWithSaveOptionsForHistoryList, \
            fullCommandStrForStatusBar = self._addOptionPriceInfo(resultData,
                           priceOptionAmountStr,
                           fullCommandStrWithNoSaveOptions,
                           fullCommandStrWithSaveOptionsForHistoryList,
                           fullCommandStrForStatusBar)

        from seqdiagbuilder import SeqDiagBuilder

        SeqDiagBuilder.recordFlow()

        if fullCommandStrWithSaveOptionsForHistoryList == fullCommandStrNoOptions:
            fullCommandStrWithSaveOptionsForHistoryList = None

        if fullCommandStrWithNoSaveOptions == fullCommandStrNoOptions:
            fullCommandStrWithNoSaveOptions = None

        fullCommandStrForStatusBar += fullCommandStrForStatusBarFiatComplement

        if fullCommandStrForStatusBar == fullCommandStrNoOptions:
            fullCommandStrForStatusBar = None

        return fullCommandStrNoOptions, fullCommandStrWithNoSaveOptions, fullCommandStrWithSaveOptionsForHistoryList, fullCommandStrForStatusBar
Ejemplo n.º 26
0
    def _getHistoDayPriceAtUTCTimeStamp(self, crypto, unit, timeStampUTC,
                                        exchange, resultData):
        '''

        :param crypto:
        :param unit:
        :param timeStampUTC:
        :param exchange:
        :param resultData:
        :seqdiag_return ResultData
        :return: resultData
        '''
        timeStampUTCStr = str(timeStampUTC)
        url = "https://min-api.cryptocompare.com/data/histoday?fsym={}&tsym={}&limit=1&aggregate=1&toTs={}&e={}".format(
            crypto, unit, timeStampUTCStr, exchange)
        resultData.setValue(ResultData.RESULT_KEY_PRICE_TYPE,
                            resultData.PRICE_TYPE_HISTO_DAY)

        try:
            if self.ctx == None:
                #here, run in QPython under Python 3.2
                webURL = urllib.request.urlopen(url)
            else:
                webURL = urllib.request.urlopen(url, context=self.ctx)
        except HTTPError as e:
            resultData.setError('ERROR - could not complete request ' + url +
                                '. Reason: ' + str(e.reason) + '.')
        except URLError as e:
            resultData.setError(
                'ERROR - No internet. Fix the problem and retry !')
        except:
            the_type, the_value, the_traceback = sys.exc_info()
            resultData.setError('ERROR - could not complete request ' + url +
                                '. Reason: ' + str(the_type) + '.')
        else:
            page = webURL.read()
            soup = BeautifulSoup(page, 'html.parser')
            dic = json.loads(soup.prettify())
            #            if dic['Data'] != [] and unit in dic:
            dataListOrDic = dic['Data']
            if dataListOrDic != []:
                try:
                    dataEntryDic = dataListOrDic[IDX_DATA_ENTRY_TO]
                    resultData.setValue(ResultData.RESULT_KEY_PRICE_TIME_STAMP,
                                        dataEntryDic['time'])
                    resultData.setValue(ResultData.RESULT_KEY_PRICE,
                                        dataEntryDic['close'])
                except IndexError:  # does not happen in any test case
                    resultData = self._handleProviderError(dic,
                                                           resultData,
                                                           url,
                                                           crypto,
                                                           unit,
                                                           exchange,
                                                           isRealTime=False)
                except KeyError:
                    # happens when pair coupled to exchange do not return ay data.
                    # Either the exchange does not exist or the pair is not
                    # supported by the exchange.
                    resultData = self._handleProviderError(dic,
                                                           resultData,
                                                           url,
                                                           crypto,
                                                           unit,
                                                           exchange,
                                                           isRealTime=False)
            else:
                resultData = self._handleProviderError(dic,
                                                       resultData,
                                                       url,
                                                       crypto,
                                                       unit,
                                                       exchange,
                                                       isRealTime=False)

        from seqdiagbuilder import SeqDiagBuilder
        SeqDiagBuilder.recordFlow()

        return resultData