Best Python code snippet using hypothesis
tag.py
Source:tag.py
1""" Audio tag handling code. """2import abc3import base644import calendar5import collections6import datetime7import functools8import itertools9import logging10import operator11import re12import string13from typing import Any, Deque, Dict, List, Optional, Sequence, Tuple14import more_itertools15import mutagen16import unidecode17from amg import sanitize18class TitleNormalizer:19 """20 Class to chain all title tag transformations.21 What was once a small concise function has grown into the largest part of this project.22 This chains many checks to remove crap from title tags, because record people do not have conventions or23 common sense for that matter, and often try to stuff their grocery list and the name of their cat into24 what should be a simple title for the song.25 """26 def __init__(self, artist: str, album: str): # noqa: C90127 self.cleaners: List[Tuple[TitleCleanerBase, Tuple[Any]]] = []28 # TODO separate cleaner from params and copy/reuse cleaners in TitleNormalizer.cleanup29 # remove consecutive spaces30 self.registerCleaner(FunctionCleaner(lambda x: " ".join(x.split()), execute_once=True))31 # detect and remove '#hashtag' suffix32 self.registerCleaner(RegexSuffixCleaner(r"(#[\w]+ ?)+", contains=("#"), execute_once=True))33 # detect and remove 'taken from album xxx, out (on) yyy' suffix34 self.registerCleaner(35 RegexSuffixCleaner("taken from .+, out ", contains=("taken from", "out"), execute_once=True)36 )37 # detect and remove 'a track of the upcoming xxx' suffix38 self.registerCleaner(39 RegexSuffixCleaner("a track of upcoming ", contains=("a track of upcoming"), execute_once=True)40 )41 # detect and remove 'album: xxx track yy'42 self.registerCleaner(RegexCleaner("(album: .+ )?track [0-9]+", contains=("track",), execute_once=True))43 # detect and remove 'from xxx LP' suffix44 self.registerCleaner(RegexSuffixCleaner("from .+ LP", contains=("from", "LP"), execute_once=True))45 # detect and remove 'from xxx album' suffix46 self.registerCleaner(RegexSuffixCleaner("from .*album", contains=("from", "album"), execute_once=True))47 # detect and remove 'xxx out: yy.zz.aa' suffix48 self.registerCleaner(49 RegexSuffixCleaner(r" [\[\(]?([^ ]+ out: )?[0-9]+\.[0-9]+\.[0-9]+[\]\)]?", execute_once=True)50 )51 # detect and remove 'out yy.zz' suffix52 self.registerCleaner(RegexSuffixCleaner(" out [0-9]+/[0-9]+", contains=(" out ",), execute_once=True))53 # detect and remove 'out month xxth' suffix54 self.registerCleaner(RegexSuffixCleaner(" out [a-z]+ [0-9]+th", contains=(" out ",), execute_once=True))55 # detect and remove 'new album out xxx' suffix56 self.registerCleaner(RegexSuffixCleaner("new album out .*$", contains=("new album out ",), execute_once=True))57 # detect and remove '[xxx music]' suffix58 self.registerCleaner(RegexSuffixCleaner(r"[\[\( ][a-z]+ music$", suffixes=("music",), execute_once=True))59 # detect and remove 'xxx entertainment' suffix60 self.registerCleaner(61 RegexSuffixCleaner(r"[\[\( ][a-z]+ entertainment$", suffixes=("entertainment",), execute_once=True)62 )63 # detect and remove 'record label xxx' suffix64 self.registerCleaner(65 RegexSuffixCleaner("record label:? [a-z0-9 ]+$", contains=("record label",), execute_once=True)66 )67 # detect and remove 'next concert: xxx' suffix68 self.registerCleaner(RegexSuffixCleaner("next concert: .+$", contains=("next concert: ",), execute_once=True))69 # detect and remove 'feat.xxx' suffix70 self.registerCleaner(RegexSuffixCleaner(r"feat\..+$", contains=("feat.",), execute_once=True))71 # detect and remove 'ft. xxx'72 self.registerCleaner(RegexCleaner(r"[\(\[ ]+ft\. [a-zA-Z\.\: ]+[\)\]]?", contains=("ft.",), execute_once=True))73 # detect and remove '(xxx productions)'74 self.registerCleaner(75 RegexCleaner(r"[^\w\s].+ productions?[^\w\s]", contains=("production",), execute_once=True)76 )77 # detect and remove 'xxx productions' prefix78 self.registerCleaner(RegexPrefixCleaner(r"^[\w\s]+ productions?", contains=("production",), execute_once=True))79 # detect and remove '- xxx metal' suffix80 base_genres = [81 "crust",82 "black",83 "death",84 "doom",85 "grind",86 "grindcore",87 "progressive",88 "sci-fi",89 "thrash",90 ]91 composed_genres = tuple(92 genre_sep.join(pair) for pair in itertools.permutations(base_genres, 2) for genre_sep in "/- "93 )94 metal_genres = tuple(f"{genre} metal" for genre in tuple(base_genres) + composed_genres)95 base_genres.append("metal")96 for too_common_word in ("black", "death", "thrash"):97 base_genres.remove(too_common_word)98 for genre in metal_genres + composed_genres + tuple(base_genres):99 self.registerCleaner(100 RegexSuffixCleaner(101 r"[|\(\[/\] -]+(?:[0-9a-z/-\\,]+[ ]*)*" + genre + "( song)?$",102 suffixes=(genre, f"{genre} song"),103 execute_once=True,104 remove_if_skipped=False,105 )106 )107 # detect and remove '(thrash/death from whatever)' suffix108 for genre in metal_genres + composed_genres + tuple(base_genres):109 self.registerCleaner(110 RegexSuffixCleaner(111 r"[|\(\[/]+[ ]*" + genre + r" from [a-zA-Z-, ]+[\)\]]?$",112 contains=(f"{genre} from ",),113 execute_once=True,114 )115 )116 # detect and remove 'xxx metal' prefix117 for genre in metal_genres + composed_genres:118 self.registerCleaner(SimplePrefixCleaner(execute_once=True), (genre,))119 # detect and remove 'xxx productions' suffix120 self.registerCleaner(RegexSuffixCleaner(r"[\[\( ][a-z ]+ productions$", suffixes=(" productions",)))121 # detect and remove track number prefix122 self.registerCleaner(RegexPrefixCleaner("^[0-9]+[ -.]+"))123 # detect and remove 'xxx records' suffix124 self.registerCleaner(RecordsSuffixCleaner("recordings"))125 self.registerCleaner(RecordsSuffixCleaner("records"))126 # detect and remove ' | xxx' suffixes127 self.registerCleaner(RegexSuffixCleaner(r" \| .*$", suffixes=" | ", execute_once=True))128 # build list of common useless expressions129 expressions = set()130 words1 = ("", "explicit", "full", "including", "new", "official", "stop motion", "the new")131 words2 = (132 "",133 "360",134 "album",135 "album/tour",136 "audio",137 "game",138 "lyric",139 "lyrics",140 "music",141 "promo",142 "single",143 "song",144 "stream",145 "studio",146 "track",147 "video",148 "visual",149 )150 words3 = (151 "4k",152 "album",153 "audio",154 "clip",155 "discovery",156 "edit",157 "excerpt",158 "hq",159 "in 4k",160 "lyric",161 "lyrics",162 "only",163 "premier",164 "premiere",165 "presentation",166 "promo",167 "single",168 "song",169 "stream",170 "streaming",171 "teaser",172 "track",173 "trailer",174 "version",175 "video",176 "visualizer",177 "vr",178 )179 for w1 in words1:180 for w2 in words2:181 for w3 in words3:182 if w3 != w2:183 if w1 or w2:184 for rsep in (" ", "-", ""):185 rpart = rsep.join((w2, w3)).strip()186 expressions.add(" ".join((w1, rpart)).strip())187 else:188 expressions.add(w3)189 expressions.update(190 (191 "full ep",192 "full-length",193 "hd",194 "official",195 "pre-listening",196 "pre-order now",197 "pre-orders available",198 "prelistening",199 "preorders available",200 "s/t",201 "sw exclusive",202 "trailer for the upcoming album",203 "transcending obscurity",204 "transcending obscurity india",205 "trollzorn",206 "uncensored",207 )208 )209 year = datetime.datetime.today().year210 for y in range(2016, year + 1):211 expressions.add(str(y))212 for month_name, month_abbr in zip(MONTH_NAMES, MONTH_NAMES_ABBR):213 expressions.add(f"{month_name} {y}")214 expressions.add(f"{month_abbr} {y}")215 expressions_list = list(sorted(expressions, key=len, reverse=True))216 expressions_list.remove("song")217 suffix_cleaner = SimpleSuffixCleaner()218 for expression in expressions_list:219 self.registerCleaner(suffix_cleaner, (expression,))220 prefix_cleaner = SimplePrefixCleaner()221 for expression in expressions_list:222 self.registerCleaner(prefix_cleaner, (expression,))223 # detect and remove artist prefix ot suffix224 self.registerCleaner(ArtistCleaner(), (artist,))225 # detect and remove starting parenthesis expression226 self.registerCleaner(StartParenthesesCleaner(execute_once=True))227 # detect and remove album prefix or suffix228 self.registerCleaner(AlbumCleaner(execute_once=True), (album,))229 # fix paired chars230 self.registerCleaner(PairedCharCleaner(execute_once=True))231 # remove some punctuation232 self.registerCleaner(FunctionCleaner(lambda x: x.strip("-"), execute_once=True))233 # normalize case234 self.registerCleaner(FunctionCleaner(sanitize.normalize_tag_case, execute_once=True))235 # post normalize case fix236 self.registerCleaner(FunctionCleaner(lambda x: x.replace("PT.", "pt."), execute_once=True))237 def registerCleaner(self, cleaner, args=()):238 """Register a new cleaner object."""239 assert isinstance(cleaner, TitleCleanerBase)240 self.cleaners.append((cleaner, args))241 def cleanup(self, title: str) -> str:242 """Do the string cleanup by running all cleaners."""243 cur_title = title244 to_del_indexes: Deque[int] = collections.deque()245 start_index = 0246 while self.cleaners:247 cleaner: TitleCleanerBase248 for i, (cleaner, args) in enumerate(itertools.islice(self.cleaners, start_index, None), start_index):249 remove_cur_cleaner = False250 restart_loop = False251 if cleaner.doSkip(cur_title, *args):252 if cleaner.remove_if_skipped and not cleaner.doKeep():253 remove_cur_cleaner = True254 else:255 new_title = cleaner.cleanup(cur_title, *args)256 if new_title and (new_title != cur_title):257 logging.getLogger().debug(258 f"{cleaner.__class__.__name__} changed title tag: "259 f"{repr(cur_title)} -> {repr(new_title)}"260 )261 # update string and remove this cleaner to avoid calling it several times262 cur_title = new_title263 remove_cur_cleaner = not cleaner.doKeep()264 restart_loop = True265 elif cleaner.execute_once:266 remove_cur_cleaner = True267 # this cleaner did not match and we will remove it, continue from same index268 if start_index == 0:269 start_index = i270 if remove_cur_cleaner:271 to_del_indexes.append(i)272 if restart_loop:273 start_index = 0274 break275 else:276 # all cleaners have been called and string did not change title277 break278 while to_del_indexes:279 del self.cleaners[to_del_indexes.pop()]280 if cur_title != title:281 logging.getLogger().info(f"Fixed title tag: {repr(title)} -> {repr(cur_title)}")282 return cur_title283class TitleCleanerBase:284 """Base class for all title cleaner subclasses."""285 RCLEAN_CHARS = "".join(c for c in (string.punctuation + string.whitespace) if c not in "!?)-]")286 LCLEAN_CHARS = "".join(c for c in (string.punctuation + string.whitespace) if c not in "(")287 def __init__(self, *, execute_once: bool = False, remove_if_skipped: bool = None):288 self.execute_once = execute_once289 self.remove_if_skipped = remove_if_skipped if (remove_if_skipped is not None) else execute_once290 def doSkip(self, title: str, *args) -> bool:291 """Return True if this cleaner can be skipped for this title string."""292 return False293 def doKeep(self) -> bool:294 """Return True if this cleaner should not be removed even if it matched."""295 return False296 @abc.abstractmethod297 def cleanup(self, title: str, *args: Tuple[Any]) -> str:298 """Cleanup a title string, and return the updated string."""299 pass300 def rclean(self, s: str) -> str:301 """Remove garbage at right of string."""302 r = s.rstrip(self.__class__.RCLEAN_CHARS)303 if r.endswith(" -"):304 r = r[:-2].rstrip(self.__class__.RCLEAN_CHARS)305 return r306 def lclean(self, s: str) -> str:307 """Remove garbage at left of string."""308 r = s.lstrip(self.__class__.LCLEAN_CHARS)309 c = unidecode.unidecode_expect_ascii(r.lstrip(self.__class__.LCLEAN_CHARS)).lstrip(self.__class__.LCLEAN_CHARS)310 if c != r:311 r = c312 return r313 @functools.lru_cache(maxsize=32768)314 def rnorm(self, s: str) -> str:315 """Normalize string unicode chars and remove useless chars from its right."""316 return unidecode.unidecode_expect_ascii(s.rstrip(string.punctuation)).rstrip(string.punctuation).lower()317 @functools.lru_cache(maxsize=32768)318 def lnorm(self, s: str) -> str:319 """Normalize string unicode chars and remove useless chars from its left."""320 return unidecode.unidecode_expect_ascii(s.lstrip(string.punctuation)).lstrip(string.punctuation).lower()321 def startslike(self, s: str, pattern: str, *, sep: Optional[str] = None) -> bool:322 """Return True if start of string s is similar to pattern."""323 s = self.lnorm(s)324 pattern = self.rnorm(pattern)325 cut = s[len(pattern) :]326 return s.startswith(pattern) and ((not sep) or (not cut) or (cut[0] in sep))327 def endslike(self, s: str, pattern: str) -> bool:328 """Return True if end of string s is similar to pattern."""329 return self.rnorm(s).endswith(self.rnorm(pattern))330 def rmsuffix(self, s: str, e: str) -> str:331 """Remove string suffix."""332 return s.rstrip(string.punctuation)[: -len(unidecode.unidecode_expect_ascii(e))]333 def rmprefix(self, s: str, e: str) -> str:334 """Remove string prefix."""335 return s.lstrip(string.punctuation)[len(unidecode.unidecode_expect_ascii(e)) :]336class FunctionCleaner(TitleCleanerBase):337 """Cleaner to apply a function to the title string."""338 def __init__(self, func, **kwargs):339 super().__init__(**kwargs)340 assert callable(func)341 self.func = func342 def cleanup(self, title: str) -> str: # type: ignore343 """See TitleCleanerBase.cleanup."""344 return self.func(title)345class SimplePrefixCleaner(TitleCleanerBase):346 """Cleaner to remove a static string prefix."""347 def cleanup(self, title: str, prefix: str) -> str: # type: ignore348 """See TitleCleanerBase.cleanup."""349 if self.startslike(title, prefix, sep=string.punctuation + string.whitespace):350 title = self.lclean(self.rmprefix(title, prefix))351 return title352class SimpleSuffixCleaner(TitleCleanerBase):353 """Cleaner to remove a static string suffix."""354 def cleanup(self, title: str, suffix: str) -> str: # type: ignore355 """See TitleCleanerBase.cleanup."""356 if self.endslike(title, suffix):357 new_title = self.rclean(self.rmsuffix(title, suffix))358 if new_title.lower() != "the":359 title = new_title360 return title361class ArtistCleaner(SimplePrefixCleaner, SimpleSuffixCleaner):362 """Cleaner to remove artist prefix/suffix."""363 def __init__(self, *args, **kwargs):364 self.prefix_removed = False365 self.suffix_removed = False366 super().__init__(*args, **kwargs)367 def doKeep(self) -> bool:368 """See TitleCleanerBase.doKeep."""369 return not self.suffix_removed370 def cleanup(self, title: str, artist: str) -> str: # type: ignore371 """See TitleCleanerBase.cleanup."""372 artist_variants = tuple(373 more_itertools.unique_everseen(374 (375 f"{artist} band",376 artist,377 artist.replace(" ", ""),378 artist.replace("and", "&"),379 artist.replace("&", "and"),380 artist.replace(", ", " and "),381 artist.replace(" and ", ", "),382 artist.replace("â", ""),383 )384 )385 )386 for s, suffix_only in itertools.zip_longest(("by " + artist,) + artist_variants, (True,), fillvalue=False):387 # detect and remove artist prefix388 if (not suffix_only) and (not self.prefix_removed) and self.startslike(title, s):389 r = SimplePrefixCleaner.cleanup(self, title, s)390 self.prefix_removed = True391 return r392 # detect and remove artist suffix393 elif (not self.suffix_removed) and self.endslike(title, s):394 r = SimpleSuffixCleaner.cleanup(self, title, s)395 self.suffix_removed = True396 return r397 return title398class AlbumCleaner(SimplePrefixCleaner, SimpleSuffixCleaner):399 """Cleaner to remove album prefix/suffix."""400 def cleanup(self, title: str, album: str) -> str: # type: ignore401 """See TitleCleanerBase.cleanup."""402 # detect and remove album prefix403 if self.startslike(title, album):404 return SimplePrefixCleaner.cleanup(self, title, album)405 # detect and remove album suffix406 elif self.endslike(title, album):407 title = SimpleSuffixCleaner.cleanup(self, title, album)408 # detect and remove album suffix's prefix409 for suffix in ("taken from", "from the album", "from"):410 if self.endslike(title, suffix):411 new_title = SimpleSuffixCleaner.cleanup(self, title, suffix)412 if new_title:413 title = new_title414 break415 return title416class RegexCleaner(TitleCleanerBase):417 """Cleaner to remove a regex match."""418 def __init__(self, regex: str, *, contains: Sequence[str] = (), flags: int = re.IGNORECASE, **kwargs):419 super().__init__(**kwargs)420 self.regex = re.compile(regex, flags)421 self.contains = contains422 def doSkip(self, title: str, *args) -> bool:423 """See TitleCleanerBase.doSkip."""424 if self.contains:425 lower_title = title.lower()426 skip = not any(map(lower_title.__contains__, self.contains))427 if skip:428 self.remove_if_skipped = True429 return skip430 return super().doSkip(title, *args)431 def cleanup(self, title: str) -> str: # type: ignore432 """See TitleCleanerBase.cleanup."""433 rstripped = title.rstrip(string.punctuation)434 match = self.regex.search(rstripped)435 if match:436 title = f"{self.rclean(rstripped[:match.start(0)])} {self.lclean(rstripped[match.end(0):])}".rstrip()437 return title438class RegexSuffixCleaner(RegexCleaner):439 """Cleaner to remove a regex suffix match."""440 def __init__(self, regex: str, *, suffixes: Sequence[str] = (), **kwargs):441 super().__init__(regex, **kwargs)442 self.suffixes = suffixes443 def doSkip(self, title: str, *args):444 """See TitleCleanerBase.doSkip."""445 if self.suffixes:446 return not any(self.endslike(title, suffix) for suffix in self.suffixes)447 return super().doSkip(title, *args)448 def cleanup(self, title: str) -> str: # type: ignore449 """See TitleCleanerBase.cleanup."""450 match = self.regex.search(title.rstrip(string.punctuation))451 if match:452 title = self.rclean(title[: match.start(0)])453 return title454class RegexPrefixCleaner(RegexCleaner):455 """Cleaner to remove a regex prefix match."""456 def cleanup(self, title: str) -> str: # type: ignore457 """See TitleCleanerBase.cleanup."""458 match = self.regex.search(title)459 if match:460 title = self.lclean(title[match.end(0) :])461 return title462class RecordsSuffixCleaner(RegexSuffixCleaner, SimpleSuffixCleaner):463 """Cleaner to remove record suffix."""464 def __init__(self, record_word, **kwargs):465 self.record_word = record_word466 super().__init__(r"([|\)\(\[]|on)[0-9a-z,/ ]+" + record_word + "$", suffixes=(record_word,), **kwargs)467 def cleanup(self, title: str) -> str: # type: ignore468 """See TitleCleanerBase.cleanup."""469 # detect and remove 'xxx records' suffix470 match = self.regex.search(title.rstrip(string.punctuation))471 if match:472 # '(xxx yyy records)' suffix473 title = self.rclean(title[: match.start(0)])474 else:475 title = SimpleSuffixCleaner.cleanup(self, title, self.record_word)476 title = self.rclean(" ".join(title.split()[:-1]))477 return title478class StartParenthesesCleaner(TitleCleanerBase):479 """Cleaner to remove parentheses string prefix."""480 def cleanup(self, title: str) -> str: # type: ignore481 """See TitleCleanerBase.cleanup."""482 # detect and remove starting parenthesis expression483 closing_pos = title.find(")")484 if title.startswith("(") and (closing_pos != (len(title) - 1)) and (len(title[1:closing_pos]) > 1):485 return self.lclean(title[closing_pos + 1 :])486 return title487class PairedCharCleaner(TitleCleanerBase):488 """Cleaner to fix chars that go by pair."""489 def cleanup(self, title: str) -> str: # type: ignore490 """See TitleCleanerBase.cleanup."""491 # detect and remove unpaired chars492 char_pairs = ((("(", ")"), False), (('"', '"'), False), (("'", "'"), True))493 c1: str494 c2: str495 for (c1, c2), only_at_edges in char_pairs:496 if only_at_edges:497 if title.endswith(c2) and (c1 not in title[:-1]):498 title = title[:-1]499 elif title.startswith(c1) and (c2 not in title[1:]):500 title = title[1:]501 else:502 if c1 != c2:503 if (title.count(c1) + title.count(c2)) == 1:504 title = title.translate(str.maketrans("", "", c1 + c2))505 else:506 if title.count(c1) == 1:507 title = title.translate(str.maketrans("", "", c1))508 # detect and remove parenthesis at start and end509 if title.startswith("(") and title.endswith(")"):510 title = title[1:-1]511 return title512def normalize_title_tag(title: str, artist: str, album: str) -> str:513 """Remove useless prefix and suffix from title tag string."""514 normalizer = TitleNormalizer(artist, album)515 return normalizer.cleanup(title)516def tag(track_filepath: str, review, metadata: Dict[str, str], cover_data: Optional[bytes]):517 """Tag an audio file, return tag dict excluding RG/R128 info and album art."""518 logging.getLogger().info(f"Tagging file {track_filepath!r}")519 mf = mutagen.File(track_filepath, easy=True)520 # sanitize tags521 mf["artist"] = sanitize.normalize_tag_case(review.artist)522 mf["album"] = sanitize.normalize_tag_case(review.album)523 try:524 mf["title"] = normalize_title_tag(metadata["title"], review.artist, review.album)525 except KeyError:526 mf["title"] = mf["album"]527 try:528 mf["comment"] = metadata["description"]529 except KeyError:530 pass531 tags = dict(mf)532 if cover_data is not None:533 if isinstance(mf, mutagen.mp3.EasyMP3) or isinstance(mf, mutagen.easymp4.EasyMP4):534 # EasyXXX helpers do not allow embedding album art, reopen as normal mutagen file535 mf.save()536 mf = mutagen.File(track_filepath)537 # embed album art538 embed_album_art(mf, cover_data)539 mf.save()540 return tags541def has_embedded_album_art(filepath: str) -> bool:542 """Return True if file already has an embedded album art, False instead."""543 mf = mutagen.File(filepath)544 if isinstance(mf, mutagen.ogg.OggFileType):545 return "metadata_block_picture" in mf546 elif isinstance(mf, mutagen.mp3.MP3):547 return any(map(operator.methodcaller("startswith", "APIC:"), mf.keys()))548 elif isinstance(mf, mutagen.mp4.MP4):549 return "covr" in mf550 return False551def embed_album_art(mf: mutagen.File, cover_data: bytes):552 """Embed album art into audio file."""553 if isinstance(mf, mutagen.ogg.OggFileType):554 picture = mutagen.flac.Picture()555 picture.data = cover_data556 picture.type = mutagen.id3.PictureType.COVER_FRONT557 picture.mime = "image/jpeg"558 encoded_data = base64.b64encode(picture.write())559 mf["metadata_block_picture"] = encoded_data.decode("ascii")560 elif isinstance(mf, mutagen.mp3.MP3):561 mf.tags.add(mutagen.id3.APIC(mime="image/jpeg", type=mutagen.id3.PictureType.COVER_FRONT, data=cover_data))562 mf.save()563 elif isinstance(mf, mutagen.mp4.MP4):564 mf["covr"] = [mutagen.mp4.MP4Cover(cover_data, imageformat=mutagen.mp4.AtomDataType.JPEG)]565# copy month names before changing locale566MONTH_NAMES = calendar.month_name[1:]...
config.py
Source:config.py
...235 for x in s.stdout:236 if re.search(process.encode(), x):237 return True238 return False239def execute_once(command): 240 process = shlex.split(command)241 if process and not is_running(process[0]):242 return Popen(process)243def cmd_get(process):244 return check_output("%s; exit 0;" % process, stderr=STDOUT, shell=True)245def get_num_screens():246 return int(cmd_get("xrandr|grep -c \ connected")) 247def get_screens():248 lines = (line for line in cmd_get("xrandr | grep -A 1 \ connected").splitlines() if line != "--")249 screens = {}250 got_primary = False251 for screen, resolution in zip(lines, lines):252 scr = screen.split()[0]253 screens[scr] = {254 "resolution": resolution.split()[0],255 "screen": scr,256 }257 # first screen not being the laptop one gets to be the primary258 if not got_primary and not scr.startswith(b"LVDS"):259 screens[scr]["primary"] = True260 got_primary = True261 return screens262def gen_screen_line(screen, resolution=None, position=None, primary=None):263 s = "--output {screen} ".format(screen=screen)264 if resolution:265 s += "--mode {resolution} --rotate normal ".format(resolution=resolution)266 if position:267 s += "--pos {position} ".format(position=position)268 if primary:269 s += "--primary "270 else:271 s += " --off "272 return s273def gen_xrand():274 modes = []275 screen_port=["LVDS", "HDMI", "VGA", "DP"]276 active_screens = get_screens()277 for port in screen_port:278 screen_name = "%s1" % port279 screen = (active_screens.get(screen_name, None) or 280 {"screen": screen_name})281 modes.append(gen_screen_line(**screen))282 return "xrandr " + " ".join(modes)283def setup_screens():284 execute_once(gen_xrand())285 # if len(screens) == 1:286 # execute_once("xrandr " +287 # "--output HDMI1 --off " +288 # "--output LVDS1 --mode 1366x768 --pos 0x0 --rotate normal " +289 # "--output DP1 --off " +290 # "--output VGA1 --off")291 # else:292 # execute_once("xbacklight -set 100")293 # if bool(int(cmd_get("xrandr|grep -c \"VGA[0-9]* connected\""))):294 # execute_once("xrandr --output HDMI1 --off " + 295 # "--output LVDS1 --mode 1366x768 --pos 0x232 --rotate normal " +296 # "--output DP1 --off " +297 # "--output VGA1 --primary --mode 1920x1080")298 # # execute_once("xrandr " +299 # # "--output HDMI1 --off " +300 # # "--output DP1 --off " +301 # # "--output VGA1 --primary --mode 1920x1080 --rotate normal --right-of " +302 # # "--output LVDS1 --mode 1366x768 --pos 0x0 --rotate normal --pos 277x1080")303 # elif bool(int(cmd_get("xrandr|grep -c \"HDMI[0-9]* connected\""))):304 # execute_once("xrandr --output VGA1 --off " + 305 # "--output LVDS1 --mode 1366x768 --pos 0x232 --rotate normal " +306 # "--output DP1 --off " +307 # "--output HDMI1 --primary --mode 1920x1080")308 # # execute_once("xrandr " +309 # # "--output VGA1 --off " +310 # # "--output DP1 --off " +311 # # "--output HDMI1 --primary --mode 1920x1080 --rotate normal --right-of " +312 # # "--output LVDS1 --mode 1366x768 --pos 0x0 --rotate normal --pos 1920x312")313 # else:314 # execute_once("xrandr " +315 # "--output HDMI1 --off " +316 # "--output LVDS1 --mode 1366x768 --pos 0x0 --rotate normal " +317 # "--output DP1 --off " +318 # "--output VGA1 --off")319def gen_locker(time=5):320 lockerstring = LOCKER321 if LOCKIMAGE and path.exists(LOCKIMAGE):322 lockerstring += " -i %s -t" % LOCKIMAGE323 else:324 lockerstring += " -c 131a13"325 return "xautolock -time %s -locker '%s'" % (time, lockerstring)326def update_wallpaper(image_path):327 if path.exists(image_path):328 execute_once("feh --bg-scale %s" % image_path)329 # TODO: log error330@hook.subscribe.startup331def startup():332 execute_once("xbacklight -set 40")333 execute_once("xcompmgr")334 execute_once("nm-applet")335 #execute_once("xcaliber --bR=256 --bG=256 --bB=200 --gR=1.0 --gG=1.0 --gB=0.85")336 execute_once("dunst")337 execute_once(gen_locker())338 #execute_once("nice -n 19 dropbox start")339 execute_once("nice -n 19 xrdb -merge %s" % path.expandvars("$HOME/.Xresources"))340 setup_screens()341 update_wallpaper(WALLPAPER)342 execute_once("dropbox")343 execute_once("seafile-applet")344@hook.subscribe.screen_change 345def restart_on_screen_change(qtile, ev): 346 setup_screens()347 update_wallpaper(WALLPAPER)...
original-config.py
Source:original-config.py
...234 for x in s.stdout:235 if re.search(process, x):236 return True237 return False238def execute_once(process):239 if not is_running(process):240 return Popen(process.split())241def cmd_get(process):242 return check_output("%s; exit 0;" % process, stderr=STDOUT, shell=True)243@hook.subscribe.client_new244def dialogs(window):245 if (window.window.get_wm_type() == 'dialog'246 or window.window.get_wm_transient_for()247 ):248 window.floating = True249 try:250 wm_class = window.window.get_wm_class() or []251 if ("gmrun" in wm_class252 or "feh" in wm_class253 or "keepass2" in wm_class254 or "crx_gclkcflnjahgejhappicbhcpllkpakej" in wm_class255 or "xcaliber-gui.tcl" in wm_class256 or "gksu" in wm_class257 or "xcalc" in wm_class258 or "wmshutdown" in wm_class259 or "thunar" in wm_class260 or "soffice" in wm_class261 ):262 window.floating = True263 except Exception as e:264 with open('/tmp/logfile', 'a') as logfile:265 logfile.write(''.join(['\n', str(e)]))266 return267def setup_screens():268 num_screens = int(cmd_get("xrandr|grep -c \ connected"))269 if num_screens == 1:270 execute_once("xrandr " +271 "--output HDMI1 --off " +272 "--output LVDS1 --mode 1366x768 --pos 0x0 --rotate normal " +273 "--output DP1 --off " +274 "--output VGA1 --off")275 else:276 execute_once("xbacklight -set 100")277 if bool(int(cmd_get("xrandr|grep -c \"VGA[0-9]* connected\""))):278 execute_once("xrandr --output HDMI1 --off " + 279 "--output LVDS1 --mode 1366x768 --pos 0x232 --rotate normal " +280 "--output DP1 --off " +281 "--output VGA1 --primary --mode 1920x1080")282 # execute_once("xrandr " +283 # "--output HDMI1 --off " +284 # "--output DP1 --off " +285 # "--output VGA1 --primary --mode 1920x1080 --rotate normal --right-of " +286 # "--output LVDS1 --mode 1366x768 --pos 0x0 --rotate normal --pos 277x1080")287 elif bool(int(cmd_get("xrandr|grep -c \"HDMI[0-9]* connected\""))):288 execute_once("xrandr --output VGA1 --off " + 289 "--output LVDS1 --mode 1366x768 --pos 0x232 --rotate normal " +290 "--output DP1 --off " +291 "--output HDMI1 --primary --mode 1920x1080")292 # execute_once("xrandr " +293 # "--output VGA1 --off " +294 # "--output DP1 --off " +295 # "--output HDMI1 --primary --mode 1920x1080 --rotate normal --right-of " +296 # "--output LVDS1 --mode 1366x768 --pos 0x0 --rotate normal --pos 1920x312")297 else:298 execute_once("xrandr " +299 "--output HDMI1 --off " +300 "--output LVDS1 --mode 1366x768 --pos 0x0 --rotate normal " +301 "--output DP1 --off " +302 "--output VGA1 --off")303@hook.subscribe.startup304def startup():305 execute_once("xbacklight -set 30")306 #execute_once("xcompmgr")307 execute_once("sh ~/.fehbg")308 #execute_once("nm-applet")309 #execute_once("xcaliber --bR=256 --bG=256 --bB=200 --gR=1.0 --gG=1.0 --gB=0.85")310 #execute_once("sudan")311 #execute_once("xautolock -time 1 -locker screenlock")312 execute_once("xscreensaver -no-logo")313 #execute_once("nice -n 19 dropbox start")314 #execute_once("nice -n 19 xrdb -merge ~/.Xresources")315 #execute_once("irssi_notifier")316 setup_screens()317@hook.subscribe.screen_change 318def restart_on_screen_change(qtile, ev): 319 setup_screens()...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!