packages feed

cobot-io 0.1.5.5 → 0.1.5.7

raw patch · 14 files changed

+158/−108 lines, 14 filesdep −arraydep ~containersdep ~lensdep ~linearPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies removed: array

Dependency ranges changed: containers, lens, linear

API changes (from Hackage documentation)

+ Bio.Sequence: type family Marking s
- Bio.Sequence: bareSequ :: Lens' (BareSequence a) (Vector a)
+ Bio.Sequence: bareSequ :: forall a f. Functor f => (Vector a -> f (Vector a)) -> BareSequence a -> f (BareSequence a)
- Bio.Sequence: class (IsMarking (Marking s), IsWeight (Weight s)) => IsSequence s where {
+ Bio.Sequence: class (IsMarking Marking s, IsWeight Weight s) => IsSequence s where {
- Bio.Sequence: markings :: Getter (Sequence mk w a) [(mk, Range)]
+ Bio.Sequence: markings :: forall mk w a f. (Contravariant f, Functor f) => ([(mk, Range)] -> f [(mk, Range)]) -> Sequence mk w a -> f (Sequence mk w a)
- Bio.Sequence: sequ :: Getter (Sequence mk w a) (Vector a)
+ Bio.Sequence: sequ :: forall mk w a f. (Contravariant f, Functor f) => (Vector a -> f (Vector a)) -> Sequence mk w a -> f (Sequence mk w a)
- Bio.Sequence: type ContainsMarking s = (IsSequence s, NotUnit (Marking s))
+ Bio.Sequence: type ContainsMarking s = (IsSequence s, NotUnit Marking s)
- Bio.Sequence: type ContainsNoMarking s = (IsSequence s, Unit (Marking s))
+ Bio.Sequence: type ContainsNoMarking s = (IsSequence s, Unit Marking s)
- Bio.Sequence: type ContainsNoWeight s = (IsSequence s, Unit (Weight s))
+ Bio.Sequence: type ContainsNoWeight s = (IsSequence s, Unit Weight s)
- Bio.Sequence: type ContainsWeight s = (IsSequence s, NotUnit (Weight s))
+ Bio.Sequence: type ContainsWeight s = (IsSequence s, NotUnit Weight s)
- Bio.Sequence: type Element s :: Type;
+ Bio.Sequence: type Element s;
- Bio.Sequence: type IsBareSequence s = (IsSequence s, Unit (Marking s), Unit (Weight s))
+ Bio.Sequence: type IsBareSequence s = (IsSequence s, Unit Marking s, Unit Weight s)
- Bio.Sequence: type IsMarkedSequence s = (IsSequence s, NotUnit (Marking s), Unit (Weight s))
+ Bio.Sequence: type IsMarkedSequence s = (IsSequence s, NotUnit Marking s, Unit Weight s)
- Bio.Sequence: type IsWeightedSequence s = (IsSequence s, Unit (Marking s), NotUnit (Weight s))
+ Bio.Sequence: type IsWeightedSequence s = (IsSequence s, Unit Marking s, NotUnit Weight s)
- Bio.Sequence: type Marking s :: Type;
+ Bio.Sequence: type Marking s;
- Bio.Sequence: type Weight s :: Type;
+ Bio.Sequence: type Weight s;
- Bio.Sequence: weights :: Getter (Sequence mk w a) (Vector w)
+ Bio.Sequence: weights :: forall mk w a f. (Contravariant f, Functor f) => (Vector w -> f (Vector w)) -> Sequence mk w a -> f (Sequence mk w a)
- Bio.Sequence.Class: bareSequ :: Lens' (BareSequence a) (Vector a)
+ Bio.Sequence.Class: bareSequ :: forall a f. Functor f => (Vector a -> f (Vector a)) -> BareSequence a -> f (BareSequence a)
- Bio.Sequence.Class: class (IsMarking (Marking s), IsWeight (Weight s)) => IsSequence s where {
+ Bio.Sequence.Class: class (IsMarking Marking s, IsWeight Weight s) => IsSequence s where {
- Bio.Sequence.Class: markings :: Getter (Sequence mk w a) [(mk, Range)]
+ Bio.Sequence.Class: markings :: forall mk w a f. (Contravariant f, Functor f) => ([(mk, Range)] -> f [(mk, Range)]) -> Sequence mk w a -> f (Sequence mk w a)
- Bio.Sequence.Class: sequ :: Getter (Sequence mk w a) (Vector a)
+ Bio.Sequence.Class: sequ :: forall mk w a f. (Contravariant f, Functor f) => (Vector a -> f (Vector a)) -> Sequence mk w a -> f (Sequence mk w a)
- Bio.Sequence.Class: type ContainsMarking s = (IsSequence s, NotUnit (Marking s))
+ Bio.Sequence.Class: type ContainsMarking s = (IsSequence s, NotUnit Marking s)
- Bio.Sequence.Class: type ContainsNoMarking s = (IsSequence s, Unit (Marking s))
+ Bio.Sequence.Class: type ContainsNoMarking s = (IsSequence s, Unit Marking s)
- Bio.Sequence.Class: type ContainsNoWeight s = (IsSequence s, Unit (Weight s))
+ Bio.Sequence.Class: type ContainsNoWeight s = (IsSequence s, Unit Weight s)
- Bio.Sequence.Class: type ContainsWeight s = (IsSequence s, NotUnit (Weight s))
+ Bio.Sequence.Class: type ContainsWeight s = (IsSequence s, NotUnit Weight s)
- Bio.Sequence.Class: type Element s :: Type;
+ Bio.Sequence.Class: type Element s;
- Bio.Sequence.Class: type IsBareSequence s = (IsSequence s, Unit (Marking s), Unit (Weight s))
+ Bio.Sequence.Class: type IsBareSequence s = (IsSequence s, Unit Marking s, Unit Weight s)
- Bio.Sequence.Class: type IsMarkedSequence s = (IsSequence s, NotUnit (Marking s), Unit (Weight s))
+ Bio.Sequence.Class: type IsMarkedSequence s = (IsSequence s, NotUnit Marking s, Unit Weight s)
- Bio.Sequence.Class: type IsWeightedSequence s = (IsSequence s, Unit (Marking s), NotUnit (Weight s))
+ Bio.Sequence.Class: type IsWeightedSequence s = (IsSequence s, Unit Marking s, NotUnit Weight s)
- Bio.Sequence.Class: type Marking s :: Type;
+ Bio.Sequence.Class: type Marking s;
- Bio.Sequence.Class: type Weight s :: Type;
+ Bio.Sequence.Class: type Weight s;
- Bio.Sequence.Class: weights :: Getter (Sequence mk w a) (Vector w)
+ Bio.Sequence.Class: weights :: forall mk w a f. (Contravariant f, Functor f) => (Vector w -> f (Vector w)) -> Sequence mk w a -> f (Sequence mk w a)

Files

ChangeLog.md view
@@ -2,6 +2,9 @@  ## [Unreleased] +## [0.1.5.6] - 2024-12-18+- Fix for gb-parser: spaces in name in LOCUS+ ## [0.1.5.5] - 2024-05-16 - Add `5ROX` modification to Fasta parser. @@ -64,12 +67,12 @@ - Update dependency versions.  ## [0.1.3.20] - 2021-06-04-### Changed -- YLAB2-629: Fasta parser is now able to parse empty lines in the beginning. +### Changed+- YLAB2-629: Fasta parser is now able to parse empty lines in the beginning.  ## [0.1.3.19] - 2021-04-30-### Changed -- Exports and instances for Biosset. +### Changed+- Exports and instances for Biosset.  ## [0.1.3.18] - 2021-03-09 ### Fixed@@ -110,7 +113,7 @@  ## [0.1.3.9] - 2020-10-27 ### Fixed-- FASTA parser can now parse empty lines with spaces. +- FASTA parser can now parse empty lines with spaces.  ## [0.1.3.8] - 2020-10-22 ### Fixed
cobot-io.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.35.3.+-- This file has been generated from package.yaml by hpack version 0.36.0. -- -- see: https://github.com/sol/hpack  name:           cobot-io-version:        0.1.5.5+version:        0.1.5.7 synopsis:       Biological data file formats and IO description:    Please see the README on GitHub at <https://github.com/biocad/cobot-io#readme> category:       Bio@@ -24,6 +24,7 @@  || ==9.4.8  || ==9.6.3  || ==9.8.1+ || ==9.10.3  extra-source-files:     README.md@@ -33,6 +34,7 @@     test/GB/pAAV-GFP-CellBioLab.gb     test/GB/pAAV_CMV_RPE65_PolyA_linkers.gb     test/GB/pIntA-TRBV.gb+    test/GB/spaces_in_locus.gb     test/FASTA/correct.fasta     test/FASTA/order1.fasta     test/FASTA/order10.fasta@@ -188,20 +190,19 @@       TemplateHaskell       FlexibleContexts   build-depends:-      array ==0.5.*-    , attoparsec >=0.10 && <0.15+      attoparsec >=0.10 && <0.15     , base >=4.14 && <5     , binary >=0.8.3.0 && <1.0     , bytestring >=0.10.8.1 && <0.13     , cobot >=0.1.1.7-    , containers >=0.5.7.1 && <0.7+    , containers >=0.5.7.1 && <0.9     , data-msgpack >=0.0.9 && <0.1     , deepseq >=1.4 && <1.6     , filepath     , http-conduit ==2.3.*     , hyraxAbif >=0.2.3.27 && <0.2.5.0-    , lens >=4.16 && <5.3-    , linear >=1.20 && <1.23+    , lens >=4.16 && <5.4+    , linear >=1.20 && <1.24     , megaparsec >=9.0.1     , mtl >=2.2.1 && <2.4     , parser-combinators >=1.2.1@@ -241,14 +242,13 @@   ghc-options: -threaded -rtsopts -with-rtsopts=-N   build-depends:       QuickCheck >=2.9.2 && <2.15-    , array ==0.5.*     , attoparsec >=0.10 && <0.15     , base >=4.14 && <5     , binary >=0.8.3.0 && <1.0     , bytestring >=0.10.8.1 && <0.13     , cobot >=0.1.1.7     , cobot-io-    , containers >=0.5.7.1 && <0.7+    , containers >=0.5.7.1 && <0.9     , data-msgpack >=0.0.9 && <0.1     , deepseq >=1.4 && <1.6     , directory@@ -256,7 +256,7 @@     , hspec >=2.4.1 && <2.12     , http-conduit ==2.3.*     , hyraxAbif >=0.2.3.27 && <0.2.5.0-    , lens >=4.16 && <5.3+    , lens >=4.16 && <5.4     , linear     , megaparsec     , mtl >=2.2.1 && <2.4
src/Bio/GB/Parser.hs view
@@ -26,7 +26,7 @@ genBankP =  GenBankSequence         <$> (metaP <?> "Meta parser")         <*> (gbSeqP <?> "GB sequence parser")-        <*  string "//" <* eolSpaceP +        <*  string "//" <* eolSpaceP  -------------------------------------------------------------------------------- -- Block with meta-information.@@ -48,16 +48,19 @@  locusP :: Parser Locus locusP = string "LOCUS" *> space *> (Locus-       <$> textP <* space                                      -- name+       <$> nameP <* space                                      -- name        <*> decimal <* space <* string "bp" <* space            -- sequence length        <*> textP <* space                                      -- molecule type-       <*> optional formP <* space                               -- form of sequence-       <*> optional (pack <$> some (satisfy isUpper)) <* space   -- GenBank division+       <*> optional formP <* space                             -- form of sequence+       <*> optional (pack <$> some (satisfy isUpper)) <* space -- GenBank division        <*> textP                                               -- modification date        <*  eolSpaceP)   where     textP = takeWhile1P Nothing $ not . isSpace +    nameP :: Parser Text+    nameP = textP <> (try (string " " <> nameP) <|> "")+     formP :: Parser Form     formP = try (string "linear" $> Linear) <|> (string "circular" $> Circular) @@ -108,7 +111,7 @@ --------------------------------------------------------------------------------  featuresP :: Parser [(Feature, Range)]-featuresP = -- skip unknown fields and stop on line with "FEATURES" +featuresP = -- skip unknown fields and stop on line with "FEATURES"           manyTill (textWithSpacesP <* eolSpaceP) (string "FEATURES") *> space           *> textWithSpacesP <* eolSpaceP           *> some (featureP <?> "Single feature parser")@@ -128,8 +131,8 @@     pure (Feature featureName' props, shiftRange (-1) range)  rangeP :: Parser Range-rangeP =  try spanP -      <|> try betweenP +rangeP =  try spanP+      <|> try betweenP       <|> try pointP       <|> try joinP       <|> complementP@@ -141,8 +144,8 @@         _ <- string ".."         upperBorderType <- option Precise (try $ char '>' *> pure Exceeded)         upperBorderLocation <- decimal-        pure $ Span (RangeBorder lowerBorderType lowerBorderLocation) (RangeBorder upperBorderType upperBorderLocation) -                +        pure $ Span (RangeBorder lowerBorderType lowerBorderLocation) (RangeBorder upperBorderType upperBorderLocation)+     betweenP :: Parser Range     betweenP = do         before <- decimal@@ -152,14 +155,14 @@      pointP :: Parser Range     pointP = fmap Point decimal-   +     joinP :: Parser Range     joinP = string "join(" *> fmap Join (rangeP `sepBy1` char ',') <* char ')'      complementP :: Parser Range     complementP = fmap Complement $ string "complement(" *> rangeP <* char ')'-         + propsP :: Parser (Text, Text) propsP = do     _ <- string featureIndent2@@ -178,17 +181,17 @@     indLine = do         _ <- string featureIndent2         notFollowedBy (char '/')-        text <- textWithSpacesP +        text <- textWithSpacesP         eolSpaceP         pure text      multiLineProp :: Parser Text     multiLineProp = do-        fstText <- textWithSpacesP <* eolSpaceP +        fstText <- textWithSpacesP <* eolSpaceP         rest <- many (try indLine)-        pure $ T.concat (fstText : rest) +        pure $ T.concat (fstText : rest) -    +  -- | First level of identation in FEATURES table file. --
src/Bio/MMTF/Decode/MessagePack.hs view
@@ -43,7 +43,11 @@ asStr m _             = fail $ T.unpack m <> ": not a string data"  asChar :: MonadFail m => Text -> Object -> m Char-asChar m = (head . T.unpack <$>) . asStr m+asChar txt obj = do+  str <- asStr txt obj+  case T.unpack str of+    []      -> return ' '+    (c : _) -> return c  asInt :: (MonadFail m, Integral a) => Text -> Object -> m a asInt _ (ObjectInt i)  = pure (fromIntegral i)
src/Bio/PDB.hs view
@@ -72,15 +72,13 @@              mkResidue :: Map Text (Vector (Bond LocalID)) -> [PDB.Atom] -> Residue             mkResidue _ []    = error "Cound not make residue from empty list"-            mkResidue localBondsMap atoms' = Residue (T.strip $ PDB.atomResName firstResidueAtom)-                                                     (PDB.atomResSeq firstResidueAtom)-                                                     (PDB.atomICode firstResidueAtom)+            mkResidue localBondsMap atoms'@(firstAtom : _) = Residue (T.strip $ PDB.atomResName firstAtom)+                                                     (PDB.atomResSeq firstAtom)+                                                     (PDB.atomICode firstAtom)                                                      (V.fromList $ mkAtom <$> atoms')-                                                     (localBondsMap M.!?! residueID firstResidueAtom)+                                                     (localBondsMap M.!?! residueID firstAtom)                                                      Undefined -- now we do not read secondary structure                                                      ""        -- chemical component type?!-              where-                firstResidueAtom = head atoms'              mkAtom :: PDB.Atom -> Atom             mkAtom atom@PDB.Atom{..} = Atom (GlobalID $ atomToNilBasedIndex M.!?! atom)
src/Bio/PDB/BondRestoring.hs view
@@ -42,25 +42,28 @@     residueIDToLocalBonds = do       (residueAtoms, residueBonds) <- zip chainAtomsGroupedByResidue intraResidueGlobalBonds       let localBonds = V.fromList $ convertGlobalsToLocals residueAtoms residueBonds-      let _residueID = residueID $ head residueAtoms+      let _residueID =+            case residueAtoms of+              [] -> ""+              (atom : _) -> residueID atom       pure (_residueID, localBonds)-    +     intraResidueGlobalBonds :: [[Bond PDB.Atom]]     intraResidueGlobalBonds = fmap restoreIntraResidueBonds chainAtomsGroupedByResidue-    +     chainAtomsGroupedByResidue :: [[PDB.Atom]]     chainAtomsGroupedByResidue = groupChainByResidue chainAtoms-    +     convertGlobalsToLocals :: [PDB.Atom] -> [Bond PDB.Atom] -> [Bond LocalID]     convertGlobalsToLocals residueAtoms = map convertGlobalToLocal       where         convertGlobalToLocal :: Bond PDB.Atom -> Bond LocalID-        convertGlobalToLocal (Bond from to order) = +        convertGlobalToLocal (Bond from to order) =           Bond (LocalID $ atomToLocalIdMap ! from) (LocalID $ atomToLocalIdMap ! to) order-        +         atomToLocalIdMap :: Map PDB.Atom Int         atomToLocalIdMap = M.fromList $ zip sortedAtoms [0..]-        +         sortedAtoms :: [PDB.Atom]         sortedAtoms = sort residueAtoms @@ -70,19 +73,19 @@   where     convertToGlobalIDs :: Map PDB.Atom Int -> Vector (Bond PDB.Atom) -> Vector (Bond GlobalID)     convertToGlobalIDs mapping = reindexBonds (\atom -> GlobalID $ mapping ! atom)-    +     reindexBonds :: (a -> b) -> Vector (Bond a) -> Vector (Bond b)     reindexBonds convertID = fmap (\(Bond from to order) -> Bond (convertID from) (convertID to) order)      chainAtomsGroupedByResidue :: Vector [[PDB.Atom]]     chainAtomsGroupedByResidue = fmap groupChainByResidue chains-    +     _intraResidueBonds :: [Bond PDB.Atom]     _intraResidueBonds = concatMap restoreChainIntraResidueBonds chainAtomsGroupedByResidue-    +     peptideBonds :: [Bond PDB.Atom]     peptideBonds = concatMap restoreChainPeptideBonds chainAtomsGroupedByResidue-    +     disulfideBonds :: [Bond PDB.Atom]     disulfideBonds = restoreDisulfideBonds . concat $ V.toList chainAtomsGroupedByResidue @@ -116,7 +119,7 @@     restoreChainPeptideBonds' :: [[PDB.Atom]] -> [Maybe (Bond PDB.Atom)] -> [Maybe (Bond PDB.Atom)]     restoreChainPeptideBonds' [] acc = acc     restoreChainPeptideBonds' [_] acc = acc-    restoreChainPeptideBonds' (residue1:residue2:residues) acc = +    restoreChainPeptideBonds' (residue1:residue2:residues) acc =       restoreChainPeptideBonds' (residue2:residues) (constructBond residue1 residue2 : acc)      constructBond :: [PDB.Atom] -> [PDB.Atom] -> Maybe (Bond PDB.Atom)@@ -129,7 +132,7 @@         guard $ distance (coords carbonAtom1) (coords nitrogenAtom2) < peptideBondMaxLength          pure $ Bond carbonAtom1 nitrogenAtom2 1-    +     getAtomByName :: [PDB.Atom] -> Text -> Maybe PDB.Atom     getAtomByName atoms atomNameToFind = find ((atomNameToFind ==) . T.strip . PDB.atomName) atoms @@ -137,20 +140,21 @@ restoreChainIntraResidueBonds = concatMap restoreIntraResidueBonds  restoreIntraResidueBonds :: [PDB.Atom] -> [Bond PDB.Atom]-restoreIntraResidueBonds residueAtoms = catMaybes $ constructBond <$> residueBonds+restoreIntraResidueBonds [] = []+restoreIntraResidueBonds residueAtoms@(firstAtom : _) = catMaybes $ constructBond <$> residueBonds   where     -- TODO: support bond order somehow     constructBond :: (Text, Text) -> Maybe (Bond PDB.Atom)     constructBond (fromAtomName, toAtomName) = Bond <$> constructAtom fromAtomName <*> constructAtom toAtomName <*> Just 1-    +     constructAtom :: Text -> Maybe PDB.Atom     constructAtom atomName = atomNameToAtom !? atomName-    +     atomNameToAtom :: Map Text PDB.Atom     atomNameToAtom = M.fromList $ (\atom@PDB.Atom{..} -> (T.strip atomName, atom)) <$> residueAtoms-    +     residueBonds :: [(Text, Text)]-    residueBonds = intraResidueBonds . T.strip . PDB.atomResName $ head residueAtoms+    residueBonds = intraResidueBonds . T.strip . PDB.atomResName $ firstAtom  intraResidueBonds :: Text -> [(Text, Text)] intraResidueBonds "NMA" = [("CA", "N")]
src/Bio/PDB/Functions.hs view
@@ -7,20 +7,21 @@  import           Data.Map.Strict (Map) import qualified Data.Map.Strict as M (fromList)-import           Data.List       (groupBy, +import           Data.List       (groupBy,                                   sortOn) import           Data.Vector     (Vector) import qualified Data.Vector      as V (toList) import           Data.Char       (toUpper)  groupChainByResidue :: Vector PDB.Atom -> [[PDB.Atom]]-groupChainByResidue = sortOn (sortOnResidue . head) . groupBy atomsFromSameResidue . V.toList-  where +groupChainByResidue = sortOn sortOnResidue . groupBy atomsFromSameResidue . V.toList+  where     atomsFromSameResidue :: PDB.Atom -> PDB.Atom -> Bool     atomsFromSameResidue atom1 atom2 = PDB.atomResSeq atom1 == PDB.atomResSeq atom2 && PDB.atomICode atom1 == PDB.atomICode atom2-    -    sortOnResidue :: PDB.Atom -> Int-    sortOnResidue PDB.Atom{..} = atomSerial * 100 + (insertionCodeSortingCorrections M.!?! toUpper atomICode)-    ++    sortOnResidue :: [PDB.Atom] -> Int+    sortOnResidue [] = -1000000+    sortOnResidue (PDB.Atom{..} : _) = atomSerial * 100 + (insertionCodeSortingCorrections M.!?! toUpper atomICode)+     insertionCodeSortingCorrections :: Map Char Int     insertionCodeSortingCorrections = M.fromList $ zip (' ':['A'..'Z']) [0..]
src/Bio/PDB/Reader.hs view
@@ -48,7 +48,7 @@  checkRow :: [Int] -> Bool checkRow [] = True-checkRow xs = last xs - head xs + 1 == L.length xs+checkRow row@(x : _) = last row - x + 1 == L.length row  checkMdlLines :: ([PDBWarnings], Text) -> Bool checkMdlLines warnings'n'text = checkRow mdlLineNumbers
src/Bio/Sequence/Functions/Marking.hs view
@@ -16,7 +16,7 @@ import           Data.List.NonEmpty   (NonEmpty (..)) import           Data.Text            (Text) import qualified Data.Vector          as V (toList)-import           Prelude              hiding (drop, head, length, null, reverse, tail, take, (!!))+import           Prelude              hiding (length)  import Bio.NucleicAcid.Nucleotide      (Complementary (..)) import Bio.Sequence.Class              (ContainsMarking, IsBareSequence, IsMarkedSequence,
src/Bio/Sequence/Functions/Weight.hs view
@@ -25,9 +25,7 @@ import           Data.Vector                     (Vector) import qualified Data.Vector                     as V (drop, length, take,                                                        toList, (!))-import           Prelude                         hiding (drop, head, length,-                                                  null, reverse, tail, take,-                                                  (!!))+import           Prelude                         hiding (drop, length, take, (!!))  -- | Range of form [a, b]. --
src/Bio/Uniprot/Parser.hs view
@@ -8,7 +8,7 @@ module Bio.Uniprot.Parser where  import           Prelude              hiding (null)-import qualified Prelude              as P (concat, init, last, null, tail)+import qualified Prelude              as P (concat, init, last)  #if MIN_VERSION_base(4, 18, 0) import           Control.Applicative  ((<|>))@@ -127,7 +127,9 @@             string "="             pure ()         result <- pack . P.init <$> many1 (satisfy (not . isEndOfLine))-        pure . head $ " {ECO" `splitOn` result+        case " {ECO" `splitOn` result of+          [] -> pure ""+          (txt : _) -> pure txt      -- Parses internal DE entities     parseInternal :: Text -> Parser DE@@ -235,9 +237,11 @@     taxId <- pack <$> many1 (notChar ';')     char ';'     hostName' <- many' (satisfy $ not . isEndOfLine)-    let hostName = pack $ if P.null hostName'-                            then ""-                            else P.tail . P.init $ hostName'+    let hostName = pack $+          case hostName' of+            [] -> ""+            [x] -> ""+            (x : xs) -> init xs     pure OH{..}  -- | Parses RN, RP, RC, RX, RG, RA, RT and RL lines of UniProt-KB text file.@@ -300,7 +304,11 @@     topic <- pack <$> many1 (notChar ':')     char ':'     (char ' ' $> ()) <|> (endOfLine >> string "CC" >> count 7 space $> ())-    comment <- head . (" {ECO" `splitOn`) . pack <$> parseMultiLineComment "CC" 7+    splitedComments <- (" {ECO" `splitOn`) . pack <$> parseMultiLineComment "CC" 7+    let comment =+          case splitedComments of+            [] -> ""+            (x : _) -> x     pure CC{..}  -- | UniProt-KB copyright comment@@ -494,7 +502,10 @@ parseDefItem :: Text -> Parser Text parseDefItem name = do     string name >> char '='-    head . (" {" `splitOn`) . pack <$> parseTillChar ';'+    txt <- (" {" `splitOn`) . pack <$> parseTillChar ';'+    case txt of+      [] -> return ""+      (x : _) -> return x  -- | Parses line till specific char (e.g. semicolon or dot) before space/endOfLine/endOfInput. parseTillChar :: Char -> Parser String@@ -524,8 +535,8 @@ hyphenConcat (x:y:ys) = x ++ hyphenConcat (sy:ys)   where     sy :: String-    sy | last x == '-'                  = tail y-       | isAA (last x) && isAA (y !! 1) = tail y+    sy | last x == '-'                  = drop 1 y+       | isAA (last x) && isAA (y !! 1) = drop 1 y        | otherwise                      = y      isAA :: Char -> Bool
test/GB/pIntA-TRBV.gb view
@@ -1,6 +1,6 @@-LOCUS       P2-32_pIntA-TRBV5-1_J1-1-Fc-lama-knob-EPEA 5960 bp   circular 27-NOV-2020-SOURCE      -  ORGANISM  +LOCUS       P2-32_pIntA-TRBV5-1_J1-1-Fc-lama-knob-EPEA    5960 bp   circular 27-NOV-2020+SOURCE+  ORGANISM COMMENT     This file is created by Vector NTI             http://www.invitrogen.com/ COMMENT     ORIGDB|GenBank@@ -9,7 +9,7 @@ COMMENT     LSOWNER| COMMENT     VNTNAME|pIntA-mIgK-GFP-stuffer-KpnI-EPEA| COMMENT     VNTAUTHORNAME|Demo User|-BASE COUNT     1711 a      1577 c      1543 g      1830 t +BASE COUNT     1711 a      1577 c      1543 g      1830 t EMBL_ID     P1-79_pIntA-mIgK-GFP-stuffer-KpnI-EPEA 5945 bp   circular 14-OCT-2020 EMBL_ID     P1-79_pIntA-mIgK-GFP-stuffer-KpnI-EPEA 6661 bp   circular 29-JAN-2020 EMBL_ID     pIntA-mIgK-GFP-s        6661 bp    DNA     circular      4-OCT-2019
+ test/GB/spaces_in_locus.gb view
@@ -0,0 +1,20 @@+LOCUS       BLABLA BLABLA BLABLA        100 bp DNA     circular SYN 11-SEP-2024
+DEFINITION  synthetic circular DNA.
+ACCESSION   .
+VERSION     .
+KEYWORDS    .
+SOURCE      synthetic DNA construct
+  ORGANISM  synthetic DNA construct
+REFERENCE   1  (bases 1 to 100)
+  AUTHORS   hhh
+  TITLE     Direct Submission
+  JOURNAL   Exported Sep 12, 2024 from SnapGene 6.1.0
+            https://www.snapgene.com
+FEATURES             Location/Qualifiers
+     source          1..100
+                     /mol_type="other DNA"
+                     /organism="plasmid"
+ORIGIN
+        1 cctacagcgt cctacagcgt cctacagcgt cctacagcgt cctacagcgt cctacagcgt
+       61 cctacagcgt cctacagcgt cctacagcgt cctacagcgt
+//
test/GBParserSpec.hs view
@@ -20,50 +20,51 @@     dottedMetaSpecP "test/GB/pAAV-GFP-CellBioLab-dots.gb"     unknownFieldsSpecP "test/GB/pIntA-TRBV.gb"     baseCountWithSophisticatedRangesAndMultilineFeatures "test/GB/fromYanaWithLove.gb"+    spacesInLocusName "test/GB/spaces_in_locus.gb"  rangeTests :: Spec rangeTests = describe "Range parser" $ do-    it "correctly parses a simple span" $ +    it "correctly parses a simple span" $         greedyRangeP "69..420" `shouldBe` successful (Span (RangeBorder Precise 69) (RangeBorder Precise 420))     it "correctly parses a span with the lower border exceeded" $         greedyRangeP "<69..420" `shouldBe` successful (Span (RangeBorder Exceeded 69) (RangeBorder Precise 420))     it "correctly parses a span with the upper border exceeded" $         greedyRangeP "69..>420" `shouldBe` successful (Span (RangeBorder Precise 69) (RangeBorder Exceeded 420))-    it "correctly parses a span with both border exceeded" $ +    it "correctly parses a span with both border exceeded" $         greedyRangeP "<69..>420" `shouldBe` successful (Span (RangeBorder Exceeded 69) (RangeBorder Exceeded 420))-    it "does not parse a span with the lower border exceeded incorrectly" $ +    it "does not parse a span with the lower border exceeded incorrectly" $         greedyRangeP ">69..420" `shouldSatisfy` isFail-    it "does not parse a span with the upper border exceeded incorrectly" $ +    it "does not parse a span with the upper border exceeded incorrectly" $         greedyRangeP "69..<420" `shouldSatisfy` isFail -    it "correctly parses a 'between' statement" $ +    it "correctly parses a 'between' statement" $         greedyRangeP "41^42" `shouldBe` successful (Between 41 42)-    it "does not parse a 'between' statement witn border excession marks" $ +    it "does not parse a 'between' statement witn border excession marks" $         greedyRangeP "<41^42" `shouldSatisfy` isFail -    it "correctly parses a single point feature" $ +    it "correctly parses a single point feature" $         greedyRangeP "42" `shouldBe` successful (Point 42)-    it "does not parse a single point feature with border excession marks" $ +    it "does not parse a single point feature with border excession marks" $         greedyRangeP "<3" `shouldSatisfy` isFail -    it "correctly parses a join() statement" $ +    it "correctly parses a join() statement" $         greedyRangeP "join(2,12..56)" `shouldBe` successful (Join [Point 2, Span (RangeBorder Precise 12) (RangeBorder Precise 56)])-    it "correctly parses a sophisticated join() statement" $ +    it "correctly parses a sophisticated join() statement" $         greedyRangeP "join(2^3,<5..10,15,20..>28)" `shouldBe` successful (Join [Between 2 3, Span (RangeBorder Exceeded 5) (RangeBorder Precise 10), Point 15, Span (RangeBorder Precise 20) (RangeBorder Exceeded 28)]) -    it "correctly parses a complement() statement" $ +    it "correctly parses a complement() statement" $         greedyRangeP "complement(69..>420)" `shouldBe` successful (Complement (Span (RangeBorder Precise 69) (RangeBorder Exceeded 420)))-    it "correctly parses a join() incorporated into a complement()" $ +    it "correctly parses a join() incorporated into a complement()" $         greedyRangeP "complement(join(2^3,<5..10,15,20..>28))" `shouldBe` successful (Complement (Join [Between 2 3, Span (RangeBorder Exceeded 5) (RangeBorder Precise 10), Point 15, Span (RangeBorder Precise 20) (RangeBorder Exceeded 28)]))   where     greedyRangeP :: Text -> Either String Range     greedyRangeP = over _Left errorBundlePretty . parse (rangeP <* eof) ""-    +     successful :: a -> Either String a     successful = Right      isFail :: Either String a -> Bool-    isFail = null +    isFail = null  pAAVGFPSpecP :: FilePath -> Spec pAAVGFPSpecP path = describe "pAAVGFP" $ do@@ -101,7 +102,7 @@ baseCountWithSophisticatedRangesAndMultilineFeatures path = describe "" $ do     it "correctly parses the 'BASE COUNT' line and features with sophisticated ranges" $ do         gbS <- gbSeq <$> fromFile path-        gbS `shouldBe`  unsafeMarkedSequence sophisticatedFeaturesSeq sophisticatedFeatures +        gbS `shouldBe`  unsafeMarkedSequence sophisticatedFeaturesSeq sophisticatedFeatures  compPreciseSpan :: (Int, Int) -> Range compPreciseSpan = Complement . preciseSpan@@ -218,20 +219,20 @@ sophisticatedFeaturesSeq = "cctacagcgtgagctatgagaaagcgccacgcttcccgaagggagaaaggcggacaggtatccggtaagcggcagggtcggaacaggagagcgcacgagggagcttccagggggaaacgcctggtatctttatagtcctgtcgggtttcgccacctctgacttgagcgtcgatttttgtgatgctcgtcaggggggcggagcctatggaaaaacgccagcaacgcggcctttttacggttcctggccttttgctggccttttgctcacatgttctttcctgcgttatcccctgattctgtggataaccgtattaccgcctttgagtgagctgataccgctcgccgcagccgaacgaccgagcgcagcgagtcagtgagcgaggaagcgtacatttatattggctcatgtccaatatgaccgccatgttgacattgattattgactagaccgcgttacataacttacggtaaatggcccgcctggctgaccgcccaacgacccccgcccattgacgtcaataatgacgtatgttcccatagtaacgccaatagggactttccattgacgtcaatgggtggagtatttacggtaaactgcccacttggcagtacatcaagtgtatcatatgccaagtacgccccctattgacgtcaatgacggtaaatggcccgcctggcattatgcccagtacatgaccttatgggactttcctacttggcagtacatctacgtattagtcatcgctattaccatggtgatgcggttttggcagtacatcaatgggcgtggatagcggtttgactcacggggatttccaagtctccaccccattgacgtcaatgggagtttgttttggcaccaaaatcaacgggactttccaaaatgtcgtaacaactccgccccattgacgcaaatgggcggtaggcgtgtacggtgggaggtctatataagcagagctcgtttagtgaaccgtcagatcgcctggagacgccatccacgctgttttgacctccatagaagacaccgggaccgatccagcctccgcggccgggaacggtgcattggaacgcggattccccgtgccaagagtgacgtaagtaccgcctatagagtctataggcccacccccttggcttcttatgcatgctatactgtttttggcttggggtctatacacccccgcttcctcatgttataggtgatggtatagcttagcctataggtgtgggttattgaccattattgaccactcccctattggtgacgatactttccattactaatccataacatggctctttgccacaactctctttattggctatatgccaatacactgtccttcagagactgacacggactctgtatttttacaggatggggtctcatttattatttacaaattcacatatacaacaccaccgtccccagtgcccgcagtttttattaaacataacgtgggatctccacgcgaatctcgggtacgtgttccggacatgggctcatctccggtagcggcggagcttctacatccgagccctgctcccatgcctccagcgactcatggtcgctcggcagctccttgctcctaacagtggaggccagacttaggcacagcacgatgcccaccaccaccagtgtgccgcacaaggccgtggcggtagggtatgtgtctgaaaatgagctcggggagcgggcttgcaccgctgacgcatttggaagacttaaggcagcggcagaagaagatgcaggcagctgagttgttgtgttctgataagagtcagaggtaactcccgttgcggtgctgttaacggtggagggcagtgtagtctgagcagtactcgttgctgccgcgcgcgccaccagacataatagctgacagactaacagactgttcctttccatgggtcttttctgcagtcaccgtccttgacacgaagcttgccgccaccatggagaccgacaccctgctgctgtgggtgctgctgctgtgggtgcccgggtcgacgaagagctcatgagcggatacatatttgaatgtatttagaaaaataaacaaataggggtcagtgttacaaccaattaaccaattctgaacattatcgcgagcccatttatacctgaatatggctcataacaccccttgtttgcctggcggcagtagcgcggtggtcccacctgaccccatgccgaactcagaagtgaaacgccgtagcgccgatggtagtgtggggactccccatgcgagagtagggaactgccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgcccgggctaattatggggtgtcgcccttggggtgagaccctcgagtgtacagaattcttactgatacgtgtccagatcaaccgctttcacgacctctaccagacacatgtgatcacggcgctcgtcgcggtctttgctcagtttggtgtggtaggtaatgtgatgataacgcgggatatgcactgccgcggagcccgccaacggacgattcatttggctgcatttggtaaccagtttttcggtcacaccttcaatatcgtacgcctggttgaactcaacgcggatgccattgttaacggtgtcaggcagaatatacagaatgcttggcgggcattggaatgcaacgttcttacgcagaatgtgaccgtctttcttaaagttctcaccagtcagcgtgacacgattgtagatagaaccgcgttcgtaggtaaccatagcacgcgtcttgtacacgccgtcgccttcgaagctgatggtacgctcttgggtataaccttccggcatggcgctcttaaagaaatccttgatgtggctcgggtacttgcgaaacactgaacaccgtagctcagggtgctcaccagggttgcccacgggacccggcaggtcgcccgtagtgcagatgtatttcgctttaatggtacccgtggtcgcgtcacccggtaccctcgcctttaatgataaatttcataccttcgacgtcgccttccagttcggtgatatacgggatctctttctcaaacagttttgcaccttccgtcaatgccgtcatatgtttacctcctaaggtctcgaaaagttaaacaaaattatttctaaagggaaaccgttgtggaattgtgagcgctcacaattccacatattataattgttatccgctcacaaagcaaataaatttttcatgatttcactgtgcatgaagctcgtaattgttatccgctcacaattaagggcgacacaaaatttattctaaatgataataaatactgataacatcttatagtttgtattatattttgtattatcgttgacatgtataattttgatatcaaaaactgattttccctttattattttcgagatttattttcttaattctctttaacaaactagaaatattgtatatacaaaaaatcataaataatagatgaatagtttaattataggtgttcatcaatcgaaaaagcaacgtatcttatttaaagtgcgttgcttttttctcatttataaggttaaataattctcatatatcaagcaaagtgacaggcgcccttaaatattctgacaaatgctctttccctaaactccccccataaaaaaacccgccgaagcgggtttttacgttatttgcggattaacgattactcgttatcagaaccgcccagggggcccgagcttaagactggccgtcgttttacaacacaagctcttccgtacggtggctgcaccatctgtcttcatcttcccgccatctgatgagcagttgaaatctggaactgcctctgttgtgtgcctgctgaataacttctatcccagagaggccaaagtacagtggaaggtggataacgccctccaatcgggtaactcccaggagagtgtcacagagcaggacagcaaggacagcacctacagcctcagcagcaccctgacgctgagcaaagcagactacgagaaacacaaagtctacgcctgcgaagtcacccatcagggcctgagctcgcccgtcacaaagagcttcaacaggggagagtgttaatagtctagacctaggtgatcataatcagccataccacatttgtagaggttttacttgctttaaaaaacctcccacacctccccctgaacctgaaacataaaatgaatgcaattgttgttgttaacttgtttattgcagcttataatggttacaaataaagcaatagcatcacaaatttcacaaataaagcatttttttcactgcattctagttgtggtttgtccaaactcatcaatgtatcttatcatgtctggagatctctagctagaggatcgatccccgccccggacgaactaaacctgactacgacatctctgccccttcttcgcggggcagtgcatgtaatcccttcagttggttggtacaacttgccaactgaaccctaaacgggtagcatatgcttcccgggtagtagtatatactatccagactaaccctaattcaatagcatatgttacccaacgggaagcatatgctatcgaattagggttagtaaaagggtcctaaggaacagcgatgtaggtgggcgggccaagataggggcgcgattgctgcgatctggaggacaaattacacacacttgcgcctgagcgccaagcacagggttgttggtcctcatattcacgaggtcgctgagagcacggtgggctaatgttgccatgggtagcatatactacccaaatatctggatagcatatgctatcctaatctatatctgggtagcataggctatcctaatctatatctgggtagcatatgctatcctaatctatatctgggtagtatatgctatcctaatttatatctgggtagcataggctatcctaatctatatctgggtagcatatgctatcctaatctatatctgggtagtatatgctatcctaatctgtatccgggtagcatatgctatcctaatagagattagggtagtatatgctatcctaatttatatctgggtagcatatactacccaaatatctggatagcatatgctatcctaatctatatctgggtagcatatgctatcctaatctatatctgggtagcataggctatcctaatctatatctgggtagcatatgctatcctaatctatatctgggtagtatatgctatcctaatttatatctgggtagcataggctatcctaatctatatctgggtagcatatgctatcctaatctatatctgggtagtatatgctatcctaatctgtatccgggtagcatatgctatcctcatgataagctgtcaaacatgagaattaattcttgaagacgaaagggcctcgtgatacgcctatttttataggttaatgtcatgataataatggtttcttagacgtcaggtggcacttttcggggaaatgtgcgcggaacccctatttgtttatttttctaaatacattcaaatatgtatccgctcatgagacaataaccctgataaatgcttcaataatattgaaaaaggaagagtatgagtattcaacatttccgtgtcgcccttattcccttttttgcggcattttgccttcctgtttttgctcacccagaaacgctggtgaaagtaaaagatgctgaagatcagttgggtgcacgagtgggttacatcgaactggatctcaacagcggtaagatccttgagagttttcgccccgaagaacgttttccaatgatgagcacttttaaagttctgctatgtggcgcggtattatcccgtgttgacgccgggcaagagcaactcggtcgccgcatacactattctcagaatgacttggttgagtactcaccagtcacagaaaagcatcttacggatggcatgacagtaagagaattatgcagtgctgccataaccatgagtgataacactgcggccaacttacttctgacaacgatcggaggaccgaaggagctaaccgcttttttgcacaacatgggggatcatgtaactcgccttgatcgttgggaaccggagctgaatgaagccataccaaacgacgagcgtgacaccacgatgcctgcagcaatggcaacaacgttgcgcaaactattaactggcgaactacttactctagcttcccggcaacaattaatagactggatggaggcggataaagttgcaggaccacttctgcgctcggcccttccggctggctggtttattgctgataaatctggagccggtgagcgtgggtctcgcggtatcattgcagcactggggccagatggtaagccctcccgtatcgtagttatctacacgacggggagtcaggcaactatggatgaacgaaatagacagatcgctgagataggtgcctcactgattaagcattggtaactgtcagaccaagtttactcatatatactttagattgatttaaaacttcatttttaatttaaaaggatctaggtgaagatcctttttgataatctcatgaccaaaatcccttaacgtgagttttcgttccactgagcgtcagaccccgtagaaaagatcaaaggatcttcttgagatcctttttttctgcgcgtaatctgctgcttgcaaacaaaaaaaccaccgctaccagcggtggtttgtttgccggatcaagagctaccaactctttttccgaaggtaactggcttcagcagagcgcagataccaaatactgttcttctagtgtagccgtagttaggccaccacttcaagaactctgtagcaccgcctacatacctcgctctgctaatcctgttaccagtggctgctgccagtggcgataagtcgtgtcttaccgggttggactcaagacgatagttaccggataaggcgcagcggtcgggctgaacggggggttcgtgcacacagcccagcttggagcgaacgacctacaccgaactgagata"  sophisticatedFeatures :: [(Feature, Range)]-sophisticatedFeatures = -  [ (Feature "source" +sophisticatedFeatures =+  [ (Feature "source"       [ ("organism", "synthetic DNA construct")       , ("mol_type", "other DNA")       ]     , preciseSpan (0, 6950)) -  , (Feature "rep_origin" +  , (Feature "rep_origin"       [ ("label", "pUCorigin and also a multiline property")       , ("note", "/vntifkey=33")       ]     , Join [Point 0, preciseSpan (6550, 6950)]) -  , (Feature "enhancer" +  , (Feature "enhancer"       [ ("label", "cmv enhanser")       , ("label", "cmv\\enhanser")       , ("note", "/vntifkey=9")@@ -251,7 +252,7 @@       ]     , preciseSpan (1011, 1918)) -  , (Feature "primer_bind" +  , (Feature "primer_bind"       [ ("label", "inv olig1") ]     , preciseSpan (1501, 1521)) @@ -269,7 +270,7 @@       ]     , preciseSpan (1953, 2009)) -  , (Feature "misc_feature"   +  , (Feature "misc_feature"       [ ("label", "START")       , ("note", "START")       , ("note", "/ugene_name=START")@@ -277,7 +278,7 @@       ]     , preciseSpan (1953, 1955)) -  , (Feature "misc_feature"   +  , (Feature "misc_feature"       [ ("label", "GFP stuffer")       , ("note", "GFP stuffer")       , ("note", "/ugene_name=GFP\\ stuffer")@@ -285,7 +286,7 @@       ]     , preciseSpan (2010, 3738)) -  , (Feature "misc_feature"   +  , (Feature "misc_feature"       [ ("label", "CK")       , ("note", "CK")       , ("note", "/ugene_name=CK")@@ -293,7 +294,7 @@       ]     , preciseSpan (3739, 4059)) -  , (Feature "misc_feature"   +  , (Feature "misc_feature"       [ ("label", "STOP")       , ("note", "STOP")       , ("note", "/ugene_name=STOP")@@ -301,7 +302,7 @@       ]     , preciseSpan (4060, 4065)) -  , (Feature "misc_feature"  +  , (Feature "misc_feature"       [ ("gene", "SV40_PA term")       , ("label", "SV40_PA term")       , ("label", "SV40_PA\\term")@@ -309,18 +310,18 @@       ]     , preciseSpan (4078, 4316)) -  , (Feature "primer_bind"   +  , (Feature "primer_bind"       [ ("label", "pEE_Clab") ]     , preciseSpan (4349, 4369)) -  , (Feature "rep_origin"     +  , (Feature "rep_origin"       [ ("label", "EBV ori")       , ("label", "EBV\\ori")       , ("note", "/vntifkey=33")       ]     , preciseSpan (4581, 4974)) -  , (Feature "CDS"          +  , (Feature "CDS"       [ ("codon_start", "1")       , ("label", "AmpR")       , ("note", "/vntifkey=4")@@ -328,3 +329,10 @@       ]     , preciseSpan (5542, 6402))   ]++spacesInLocusName :: FilePath -> Spec+spacesInLocusName path =+  describe "should correct parse gb with spaces in plasmid name in locus" $+  it "" $ do+    mt <- meta <$> fromFile path+    name (locus mt) `shouldBe` "BLABLA BLABLA BLABLA"