From bbfaf4c828d9b1ed3da643f375a9b2ed5dce564a Mon Sep 17 00:00:00 2001 From: Mauro Fujihara Date: Wed, 9 Sep 2026 08:42:48 +0900 Subject: [PATCH 1/9] Fix publish failures when using embedded db credentials (#458) * Require --db-server for embedded credentials/oauth workbook publishing, fix connections payload * Translations for publish.options.db-server message * Simplify changes * Adjust tests --- .../publish_command.py | 4 +- tabcmd/execution/global_options.py | 1 + tabcmd/locales/de/LC_MESSAGES/tabcmd.mo | Bin 19443 -> 20705 bytes .../locales/de/tabcmd_messages_de.properties | 1 + .../locales/en/tabcmd_messages_en.properties | 1 + tabcmd/locales/es/LC_MESSAGES/tabcmd.mo | Bin 19175 -> 20423 bytes .../locales/es/tabcmd_messages_es.properties | 1 + tabcmd/locales/fr/LC_MESSAGES/tabcmd.mo | Bin 19599 -> 20860 bytes .../locales/fr/tabcmd_messages_fr.properties | 1 + tabcmd/locales/ga/LC_MESSAGES/tabcmd.mo | Bin 19517 -> 20739 bytes .../locales/ga/tabcmd_messages_ga.properties | 1 + tabcmd/locales/it/LC_MESSAGES/tabcmd.mo | Bin 19329 -> 20566 bytes .../locales/it/tabcmd_messages_it.properties | 1 + tabcmd/locales/ja/LC_MESSAGES/tabcmd.mo | Bin 21856 -> 23120 bytes .../locales/ja/tabcmd_messages_ja.properties | 1 + tabcmd/locales/ko/LC_MESSAGES/tabcmd.mo | Bin 19611 -> 20852 bytes .../locales/ko/tabcmd_messages_ko.properties | 1 + tabcmd/locales/pt/LC_MESSAGES/tabcmd.mo | Bin 18559 -> 19726 bytes .../locales/pt/tabcmd_messages_pt.properties | 1 + tabcmd/locales/sv/LC_MESSAGES/tabcmd.mo | Bin 17966 -> 19192 bytes .../locales/sv/tabcmd_messages_sv.properties | 1 + tabcmd/locales/zh/LC_MESSAGES/tabcmd.mo | Bin 16694 -> 17876 bytes .../locales/zh/tabcmd_messages_zh.properties | 1 + tests/commands/test_publish_command.py | 39 ++++++++++++++++++ 24 files changed, 54 insertions(+), 1 deletion(-) diff --git a/tabcmd/commands/datasources_and_workbooks/publish_command.py b/tabcmd/commands/datasources_and_workbooks/publish_command.py index 1dd2bfc1..dfd26b28 100644 --- a/tabcmd/commands/datasources_and_workbooks/publish_command.py +++ b/tabcmd/commands/datasources_and_workbooks/publish_command.py @@ -69,11 +69,13 @@ def run_command(cls, args): if args.db_username: creds = TSC.models.ConnectionCredentials(args.db_username, args.db_password, embed=args.save_db_password) workbook_connections = TSC.ConnectionItem() + workbook_connections.server_address = args.db_server workbook_connections.connection_credentials = creds datasource_credentials = creds elif args.oauth_username: creds = TSC.models.ConnectionCredentials(args.oauth_username, None, embed=False, oauth=args.save_oauth) workbook_connections = TSC.ConnectionItem() + workbook_connections.server_address = args.db_server workbook_connections.connection_credentials = creds datasource_credentials = creds else: @@ -183,7 +185,7 @@ def publish_workbook_file(args, logger, server, project_id, str_filename, publis publish_mode, # args.thumbnail_username, not yet implemented in tsc # args.thumbnail_group, - connections=credentials, + connections=[credentials] if credentials else None, as_job=False, skip_connection_check=args.skip_connection_check, ) diff --git a/tabcmd/execution/global_options.py b/tabcmd/execution/global_options.py index 1a24133c..142aed58 100644 --- a/tabcmd/execution/global_options.py +++ b/tabcmd/execution/global_options.py @@ -258,6 +258,7 @@ def set_publish_args(parser): creds.add_argument("--db-username", help=_("publish.options.db-username")) parser.add_argument("--save-oauth", action="store_true", help=_("publish.options.save-oauth")) + parser.add_argument("--db-server", help=_("publish.options.db-server")) parser.add_argument("--db-password", help=_("publish.options.db-password")) parser.add_argument("--save-db-password", action="store_true", help=_("publish.options.save-db-password")) diff --git a/tabcmd/locales/de/LC_MESSAGES/tabcmd.mo b/tabcmd/locales/de/LC_MESSAGES/tabcmd.mo index cac49e59979b37c6f1ff8c94d05485f8d51a94ca..91b71d3f466b8beee63ab0fca808d4ff020665cd 100644 GIT binary patch delta 4245 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 Cu-=>i delta 3034 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 ad%n|lZ~s1b-?h4@y}cUV(>7z}@c#iT*GHrP diff --git a/tabcmd/locales/fr/tabcmd_messages_fr.properties b/tabcmd/locales/fr/tabcmd_messages_fr.properties index 4121acbb..32744778 100644 --- a/tabcmd/locales/fr/tabcmd_messages_fr.properties +++ b/tabcmd/locales/fr/tabcmd_messages_fr.properties @@ -77,6 +77,7 @@ publish.errors.unexpected_server_response=Réponse imprévue du serveur : {0} publish.errors.server_resource_not_found=La ressource spécifiée n’existe pas, ou vous n’êtes pas autorisé à la voir. Consultez le nom de votre projet et les autorisations. publish.options.append=Ajout d’un fichier d’extrait à une source de données existante publish.options.db-password=Mot de passe de base de données pour toutes les sources de données. +publish.options.db-server=Adresse du serveur de la base de données à associer aux informations d’identification de connexion intégrées. Obligatoire lors de l’utilisation de --db-username ou --oauth-username pour publier un classeur. publish.options.db-username=Nom d’utilisateur de base de données pour toutes les sources de données. publish.options.encrypt_extracts=Crypter les extraits sur le serveur publish.options.name=Nom du classeur/de la source de données sur le serveur. S’il est omis, le classeur/la source de données prend le nom du fichier sans l’extension twb(x), tds(x) ou tde. La publication d’un fichier .tde crée une source de données diff --git a/tabcmd/locales/ga/LC_MESSAGES/tabcmd.mo b/tabcmd/locales/ga/LC_MESSAGES/tabcmd.mo index ecc45de222bfa7f4ac973c88497140198c7e605d..27474b6b2ace2a884da58613bf07cf3246e12699 100644 GIT binary patch delta 4236 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 delta 3034 zcmYM#3v8Cv83*u#4$`em$E|i;b( zMkF8zcErWV#AIHuP3G8KHn*`gQz4A7W+P@ocEeycFx$FFvfrP+$(r{2o%4R@J?D9z zbKbY#e0JFD+lSTP8U2y1#m{U0Ci*)vJiY(_e7CWb@wz*CE??ti{0(PtkW)BiWGUmg zfah~5Yuv!|xTA6p$LjZUR4MiHjz(_$2PbjF$A@m5$_w>xVkTV63%IHJzLyz)h@*Lu z33T{5rA%gxS*VSl;u0poZ?MLloMip-)9Q;O6j2#uGHR4=7Py#MU=e5Wb4*~}%(y-_ z@i4Q{2{yC&6Qzi$T+YlhpEcgY1p4*#tzULj1NJft4KNwJ$7IkbszhF60=&*g7Vcoi zujNdBi#5K;Ebul{`oCBGVFrt>Ol0oAi1kE%hsGR!fz#N-7XF-B_|MElXN^$}j%PAm z$ee)(nR$9>XnD2j|BBh#Bh~ejmBVHAN!Odls(&(^?IR_-g(=zRX&1^G&f~*O0DGw@ zYqb(%7tXsB#kW4&P=qV>aS%2 zc$5kBX1PsrkJ;LfStNlrQvmfcLn9?z#6-57)+}GE+{Q%y zN@YJ2$Whw0GdHCoO>Ry}FJ=O}k=gTQ%>7-=)^1?}dyb>>{O{8cTp3^{I(6m?ky<6! zC(^sA%%zuIX=fJrG&Au^Cg4X{V-HiIpD_3Dr{8kiN9J!(j*OoitzWLz$iO?RFV-*% zbTg;;dzHUtCVHQlV5Iae;dD;r66O$hG2icID*Fa|c$mrjftqCaB4EmYO|HPDhklr!n9Ft^AYRm$yyq;?~z!#Z>zGLIN(r;1!c8!_B zH%D2`RzATR_c0m&l~-}Nx6@s`o{PDad0`#(A-U3E_Ed5vuiyfvBAv{OY8U75EoS`L zGwMSNwfHsz+I`IDDy9-Y;C1|v3G5mVc`{qeWcC7Y<=@!O*&cr9vUD;5Z($O6lh^P# z6W}zj&&<sCXNFy2a(D^98U?TksGw>`QnW&Zd{>#i+*~rO!g{oQ( zF!TJEIkXqJ$y()Z*0_<1T3%-6`2(lr`9G~;tJ|besCCTDej>$!rzx z|Ikfbj5x5Z5cJDxwr4!fyUnNPxxxX V*$=JzV(-+cKW^%M;@WlN{s*ShOjZB@ diff --git a/tabcmd/locales/ga/tabcmd_messages_ga.properties b/tabcmd/locales/ga/tabcmd_messages_ga.properties index cbcff215..320638ea 100644 --- a/tabcmd/locales/ga/tabcmd_messages_ga.properties +++ b/tabcmd/locales/ga/tabcmd_messages_ga.properties @@ -77,6 +77,7 @@ publish.errors.unexpected_server_response=dbf6-表:Unexpected response from the publish.errors.server_resource_not_found=b7e8-表:The resource you specified does not exist, or you do not have permission to see it. Check your project name and permissions|桜 publish.options.append=6393-表:Append extract file to existing data source|桜 publish.options.db-password=ab47-表:Database password for all data sources|桜 +publish.options.db-server=3166-表:Server address of the database to associate with the embedded connection credentials. Required when using --db-username or --oauth-username to publish a workbook.|桜 publish.options.db-username=139f-表:Database username for all data sources|桜 publish.options.encrypt_extracts=cfbc-表:Encrypt extracts on the server|桜 publish.options.name=b1bc-表:Workbook/data source name on the server. If omitted, the workbook/data source will be named after the file name, without the twb(x), tds(x), or tde extension. Publishing a .tde file will create a data source|桜 diff --git a/tabcmd/locales/it/LC_MESSAGES/tabcmd.mo b/tabcmd/locales/it/LC_MESSAGES/tabcmd.mo index 50a2e9f7482bc20238163ed7a34ee46fb1377735..3535bc68479601021d43f43153c2d30ec4a2a17d 100644 GIT binary patch delta 4237 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 diff --git a/tabcmd/locales/it/tabcmd_messages_it.properties b/tabcmd/locales/it/tabcmd_messages_it.properties index 02ce5f78..e31ef9b8 100644 --- a/tabcmd/locales/it/tabcmd_messages_it.properties +++ b/tabcmd/locales/it/tabcmd_messages_it.properties @@ -77,6 +77,7 @@ publish.errors.unexpected_server_response=Risposta inaspettata dal server: {0} publish.errors.server_resource_not_found=La risorsa specificata non esiste o non si ha l’autorizzazione a visualizzarla. Controlla il nome del progetto e le autorizzazioni publish.options.append=Aggiungi un file di estrazione all’origine dati esistente publish.options.db-password=Password del database per tutte le origini dati +publish.options.db-server=Indirizzo del server del database da associare alle credenziali di connessione incorporate. Obbligatorio quando si usa --db-username o --oauth-username per pubblicare una cartella di lavoro. publish.options.db-username=Nome utente del database per tutte le origini dati publish.options.encrypt_extracts=Crittografare le estrazioni su un server publish.options.name=Cartella di lavoro/nome dell’origine dati sul server. Se omessa, la cartella di lavoro/origine dati sarà rinominata secondo il nome del file, senza l’estensione twb(x), tds(x) o tde. La pubblicazione di un file .tde creerà un’origine dati diff --git a/tabcmd/locales/ja/LC_MESSAGES/tabcmd.mo b/tabcmd/locales/ja/LC_MESSAGES/tabcmd.mo index ce6b79faf1cfce2aa07564598b25344c194db3db..7d06038c6d3d0505c10eda266bf184663cd3364d 100644 GIT binary patch delta 4262 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 diff --git a/tabcmd/locales/ja/tabcmd_messages_ja.properties b/tabcmd/locales/ja/tabcmd_messages_ja.properties index 28f1b0b9..27c911a2 100644 --- a/tabcmd/locales/ja/tabcmd_messages_ja.properties +++ b/tabcmd/locales/ja/tabcmd_messages_ja.properties @@ -77,6 +77,7 @@ publish.errors.unexpected_server_response=サーバーからの予期しない publish.errors.server_resource_not_found=指定されたリソースは存在しないか、そのリソースを表示できるパーミッションがありません。プロジェクト名とパーミッションを確認してください。 publish.options.append=抽出ファイルを既存のデータ ソースに追加 publish.options.db-password=すべてのデータ ソースのデータベース パスワード +publish.options.db-server=埋め込まれた接続資格情報に関連付けるデータベースのサーバー アドレス。ワークブックの発行時に --db-username または --oauth-username を使用する場合は必須です。 publish.options.db-username=すべてのデータ ソースのデータベース ユーザー名 publish.options.encrypt_extracts=サーバーで抽出を暗号化する publish.options.name=サーバー上のワークブック/データ ソース名。省略した場合は、ファイル名から twb(x)、tds(x)、または tde 拡張子を除いた名前に従ってワークブック/データ ソースの名前が付けられます。.tde ファイルをパブリッシュすると、データ ソースが作成されます diff --git a/tabcmd/locales/ko/LC_MESSAGES/tabcmd.mo b/tabcmd/locales/ko/LC_MESSAGES/tabcmd.mo index 0b1ea7d1b37198615bba9ed3bd786b4c6803ae1e..54c8d41cffc8916eb2e18c5e5ddb8640a1b41025 100644 GIT binary patch delta 4259 zcmYM$3vgA%9mnwv#1KUuLP)|R$q6VBB!P-RXu`_`C@(Dqazr7XX`%|yjkfD4?3?Q!EXUxB`zAFbxMGs^8;bG*@oaQhRe~Clz4yI#D zPhi#dV z7v4e*G=@eR4nTF3i^FgZYJ%I*!NZtB|K_Z{a0PjWxr3Tfm)_A1GLTbd8fM^P)WH0x z`@)!rmr)&kgUOgc@7*vHHP9S%a1m;t+tj9i6S6lnqdNK>Y6gEn{!ACrqmd6l4R9Q) ziuoLOa9KsQJ3R!N`idurdqV~uDeyog4MLlOJ2f8p@ZTlcPv`_h{C<9-h zW^f&KV=Q@BhpE;v=+J%=>BAJGI@pI=s-vihTta2;CTgv}LkGK%2HiIlHGx^kCF3i! z7j|1uAY(9}VLIMG2jdwXRg+N%~*pNU}|w8RcFP@l=7 zqLGb9rLq7uvW=)r9I)1-M*fMl6*ZuLp!Pzd6V1qQR7Ueq16zpPVqQf3K8RZ4I!yQ8 ze=2&dzCw-s7Am#(Gi;rAQ0E`R2XQv)c8FL0NVGHgU#m>iE zrm+Nz@k#tOvTCOP=%{(fpIOU6*NqrPn4pziypwKof@>zSzU#{y*4ObN0tO)V-zpCEHJ*RZ$V|3ns6 z4;qGy$mF9kvIQIP46>;V8tF>ZNQ1Zrn{h3svD21g0B53$+Wpy+qPw{k^J!l|4KR-0Sbj4G z_1djQ`ZNtV16`bpW1k@ZDO3Vfv?=P4Wi@ATAiAjQJ@TUeCS;;AG#$_54s3 zWzl5?LjaF)R9^T7&E>j#j7|Nvl*pQy9{HHd3fbP>j`U|mABArB97U%s3pALv4QWEz0?AP zcCKc+izp=45KV;As3p_-RuS(Kbwnp(9-;EnDBgR|3Yq1ECiN_Fn9zh&*b_c)<1l%z z@W$LLT3?k);t)|n6cH-JiJyBl))vYwaLtEAw$8ai48#UDw+BO59`X4r*zS+V&HeMGPcLiRXyT9qUHjLk z&BSYj$|FPpu~QAon^Eo^bEusr^u>JHo_!IA+4>UPXzT1@@1Nh7(Dxw+_LNsvapY_4 zmF*nY6Xit6J7dhxFp*eH=rue*yh5nd6Y0bbqCXKPI!bpcXNbp%E%szJvf+K+mr3X5 z5+jKu!cVAdAb1nK@AW?HM>G(tiBp8iPoj9Qt*UxU?ziW7+YGO~_usHVc#`-#^Hl^POh3gM4PfBPCCcPZr zdH%eqP2HU@6MgM()VGJ;js&Y5w>;d|76|^^9;$UB`@?Sa z>2`lO(pXEy-FMuru5es`Rix4HxW~@9ua&tqdm@3-NZ@#u;~pt%-&G%J-sM*Nowmj@ zH&Eq0Bvj^PX0BY3xsfrg%PS}E@WGKK}znV-9@) delta 3034 zcmYM#4~*Ak9S88|P~6q22zMNZApFP!tUMG=&`uQO1OfGEMjI3dB7a;l76sT)`&BYy zG0F{f!%J6=5zQHNM@m#S-PCRkWu!(*G^JK#u|hXT>)-3`eK&7+zt{78zt8V^KF{a# ze82bZ;|;w#8|ueLoc&PobHLwNf5(QV_rcG1n@YJ*_fZbx0bb5uaWcE@C$LHP-kjFS34lrn+&AA}VK?9W~i*7U*CWSiq06hY4&eGj2ay z`5Lp(-`U2t3rZ1Fnaa#_J!@Rb1p3wVtzULl0}e6^9c6a#HnW2!Q6=&k6W|OVS-6`S zzn+(H3u}CmS>Pom^(U)-gTZ1eW0~(?%6cNdRpTnI;zaiHVm`|({3m9jAa;RO6cD=1d{|2b6exR9N-+C~=WVkTNt_17~2 ze1i$}5njfA+Eh8gl;Az)jMNO)Ec2OpZm+zTHT|6wb2(VoNaQawDLF;IrO_&}#u~3? zcDk6Ecmq?SZOjJtG8sF<)c8%-_)lis2$O4;X-rAGnd|knRpS9B(*2yk!>sW%lfq`J z$Ei$>yO{u2RQ=8LTekbCaSt=k0JFijnbLmPA_=sO0;reC8cE>-CbDI;X1S;GVJ7l@ zl>dQ%K2NT#0OwE@t-`~uXb_WyKE)LK0|AL0#%28&bciz7tQmf?p zSb8^=>GZNIUCaUtnThXY0{%K{>}4|abLRUm({K5!kIdgF9T`79TEASQk%6~WH`Xx= zY-LXI_bOjxCOXATaIWo5;UuOEoVeZfE@*jYAqaM6d7; zzQ;@XS$WDS-^!%!05g7|>K|q@^Cr*YDW=A!c`Y;P9L(UqxP=L{uJ8|Y*TwQbU!&92 z?D&38Zs1B@$=?lLub1=moQHA=b82s9p6k`LnQ{+ht^AOAv;Bq{ccSt?)%{WO z?a3{(n19bbbS%oZm<;Wsn956RW}+UQ=f6e69AyfVk`??Bzfb3+ER^Rw1$Qwi{sD7F zPBIf;rjVl=97rzKU*&{l+%K84)8JzqJ1Kc(2@~KpPPBe`TH{Xso?qY`1zgTPE?~2K zuHiD)_#(Ub7bdU{&srv4$~pWtQ}b6jpUpbAv4;t`k2wp6S(lA+TqBP|v+ZZVG>+k? znaq5Vzu+#`xWXfF0qr8-;FlS?LSKXth z@u~~=ak9c@f+zS#9%489xRl>c*GLVADRc&2&&S!rrEIu)@DMIzBEO&I_LVDl3~z4h-#_eVQ~&NUcQ>B3 Sal`8V_Vzbg`=9IV8~J}t$43GH diff --git a/tabcmd/locales/ko/tabcmd_messages_ko.properties b/tabcmd/locales/ko/tabcmd_messages_ko.properties index 23608130..3a764340 100644 --- a/tabcmd/locales/ko/tabcmd_messages_ko.properties +++ b/tabcmd/locales/ko/tabcmd_messages_ko.properties @@ -77,6 +77,7 @@ publish.errors.unexpected_server_response=서버의 예기치 않은 응답: {0} publish.errors.server_resource_not_found=지정한 리소스가 존재하지 않거나 사용자에게 리소스를 볼 수 있는 권한이 없습니다. 프로젝트 이름 및 사용 권한을 확인하십시오. publish.options.append=기존 데이터 원본에 추출 파일 추가 publish.options.db-password=모든 데이터 원본에 대한 데이터베이스 비밀번호 +publish.options.db-server=포함된 연결 자격 증명과 연결할 데이터베이스의 서버 주소입니다. 워크북을 게시할 때 --db-username 또는 --oauth-username을 사용하는 경우 필수입니다. publish.options.db-username=모든 데이터 원본에 대한 데이터베이스 사용자 이름 publish.options.encrypt_extracts=서버에서 추출 암호화 publish.options.name=서버에 있는 통합 문서/데이터 원본 이름입니다. 생략된 경우 통합 문서/데이터 원본의 이름은 twb(x), tds(x) 또는 tde 확장명을 제외한 파일 이름으로 지정됩니다. .tde 파일을 게시하면 데이터 원본이 만들어집니다. diff --git a/tabcmd/locales/pt/LC_MESSAGES/tabcmd.mo b/tabcmd/locales/pt/LC_MESSAGES/tabcmd.mo index fa709d8ac9072a1809f9e6a84bcb9f9820df907a..2b6036af3e07644934115957dbfd020780d42deb 100644 GIT binary patch delta 4191 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 VwNYbUu6iz*p8l6FxO;A0!hdAHMn?bu diff --git a/tabcmd/locales/pt/tabcmd_messages_pt.properties b/tabcmd/locales/pt/tabcmd_messages_pt.properties index 32427c37..c9dbfddd 100644 --- a/tabcmd/locales/pt/tabcmd_messages_pt.properties +++ b/tabcmd/locales/pt/tabcmd_messages_pt.properties @@ -77,6 +77,7 @@ publish.errors.unexpected_server_response=Resposta inesperada do servidor: {0} publish.errors.server_resource_not_found=O recurso especificado não existe ou você não tem permissão para vê-lo. Verifique o nome e as permissões do projeto publish.options.append=Anexe o arquivo de extração à fonte de dados existente publish.options.db-password=Senha do banco de dados para todas as fontes de dados +publish.options.db-server=Endereço do servidor do banco de dado associado as credenciais. Obrigatório ao usar --db-username ou --oauth-username. publish.options.db-username=Nome de usuário do banco de dados para todas as fontes de dados publish.options.encrypt_extracts=Criptografar extrações no servidor publish.options.name=O nome da pasta de trabalho/fonte de dados no servidor. Se omitido, a pasta de trabalho/fonte de dados será nomeado de acordo com nome de arquivo, sem a extensão twb(x), tds(x) ou tde. Publicar um arquivo .tde criará uma fonte de dados diff --git a/tabcmd/locales/sv/LC_MESSAGES/tabcmd.mo b/tabcmd/locales/sv/LC_MESSAGES/tabcmd.mo index e329a6a88f01698761fa98826e41d1f6b652ae22..d854d2f15868faf65e9aad94521d9805e325b2f5 100644 GIT binary patch delta 4228 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 PH+%L+O?~@2&Tjr6SoT0M diff --git a/tabcmd/locales/sv/tabcmd_messages_sv.properties b/tabcmd/locales/sv/tabcmd_messages_sv.properties index 448381a7..ccf9ea64 100644 --- a/tabcmd/locales/sv/tabcmd_messages_sv.properties +++ b/tabcmd/locales/sv/tabcmd_messages_sv.properties @@ -77,6 +77,7 @@ publish.errors.unexpected_server_response=Oväntat svar från servern: {0} publish.errors.server_resource_not_found=Den resurs du angav finns inte, eller så har du inte behörighet att se den. Kontrollera ditt projektnamn och dina behörigheter publish.options.append=Lägg till extraktfil till befintlig datakälla publish.options.db-password=Databaslösenord för alla datakällor +publish.options.db-server=Serveradress för databasen som ska associeras med de inbäddade anslutningsuppgifterna. Krävs när --db-username eller --oauth-username används för att publicera en arbetsbok. publish.options.db-username=Databasanvändarnamn för alla datakällor publish.options.encrypt_extracts=Kryptera extrakt på servern publish.options.name=Arbetsbokens/datakällans namn på servern. Om det inte anges namnges arbetsboken/datakällan efter filnamnet, utan filnamnstillägget twb(x), tds(x) eller tde. Om du publicerar en .tde-fil skapas en datakälla diff --git a/tabcmd/locales/zh/LC_MESSAGES/tabcmd.mo b/tabcmd/locales/zh/LC_MESSAGES/tabcmd.mo index 3c25206721c3c5bbd400a93c13294fed41fbd0e6..c9d0e60fcf79751f9f4c64884b70b4c0801b22b8 100644 GIT binary patch delta 4200 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 diff --git a/tabcmd/locales/zh/tabcmd_messages_zh.properties b/tabcmd/locales/zh/tabcmd_messages_zh.properties index 58beb33a..8a1d0825 100644 --- a/tabcmd/locales/zh/tabcmd_messages_zh.properties +++ b/tabcmd/locales/zh/tabcmd_messages_zh.properties @@ -77,6 +77,7 @@ publish.errors.unexpected_server_response=来自服务器的意外响应: {0} publish.errors.server_resource_not_found=指定的资源不存在,或者您没有查看该资源的权限。请检查您的项目名称和权限 publish.options.append=将数据提取文件追加到现有数据源 publish.options.db-password=用于所有数据源的数据库密码 +publish.options.db-server=要与嵌入式连接凭据关联的数据库的服务器地址。使用 --db-username 或 --oauth-username 发布工作簿时必需。 publish.options.db-username=用于所有数据源的数据库用户名 publish.options.encrypt_extracts=在服务器上对数据提取进行加密 publish.options.name=服务器上的工作簿/数据源名称。如果省略,将使用文件名作为工作簿/数据源名称(无 twb(x)、tds(x) 或 tde 扩展名)。发布 .tde 文件将会创建数据源 diff --git a/tests/commands/test_publish_command.py b/tests/commands/test_publish_command.py index 368fd997..df4b7115 100644 --- a/tests/commands/test_publish_command.py +++ b/tests/commands/test_publish_command.py @@ -55,6 +55,7 @@ def test_publish_with_creds(self, mock_path, mock_glob, mock_session): mock_args.db_username = "username" mock_args.db_password = "oauth_u" + mock_args.db_server = "db.example.com" mock_args.save_db_password = True mock_args.oauth_username = None mock_args.embed = False @@ -66,6 +67,44 @@ def test_publish_with_creds(self, mock_path, mock_glob, mock_session): PublishCommand.run_command(mock_args) mock_session.internal_server.workbooks.publish.assert_called() + call_kwargs = mock_session.internal_server.workbooks.publish.call_args.kwargs + connections = call_kwargs["connections"] + self.assertEqual(len(connections), 1) + self.assertEqual(connections[0].server_address, "db.example.com") + + def test_publish_with_creds_no_db_server(self, mock_path, mock_glob, mock_session): + set_up_mock_server(mock_session) + mock_path = set_up_mock_path(mock_path) + + mock_args.overwrite = False + mock_args.append = True + mock_args.replace = False + + mock_args.filename = "existing_file.twbx" + mock_args.project_name = "project-name" + mock_args.parent_project_path = "projects" + mock_args.name = "" + mock_args.tabbed = True + + mock_args.db_username = "username" + mock_args.db_password = "oauth_u" + mock_args.db_server = None + mock_args.save_db_password = True + mock_args.oauth_username = None + mock_args.embed = False + + mock_args.thumbnail_username = None + mock_args.thumbnail_group = None + mock_args.skip_connection_check = False + + PublishCommand.run_command(mock_args) + mock_session.internal_server.workbooks.publish.assert_called() + + call_kwargs = mock_session.internal_server.workbooks.publish.call_args.kwargs + connections = call_kwargs["connections"] + self.assertEqual(len(connections), 1) + self.assertIsNone(connections[0].server_address) + def test_get_files_to_publish_twbx(self, mock_path, mock_glob, mock_session): set_up_mock_server(mock_session) mock_path = set_up_mock_path(mock_path) From d59ee65767d3ea009aec87afe83ae3c81c10fb96 Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Tue, 8 Sep 2026 16:54:07 -0700 Subject: [PATCH 2/9] Require --db-server when publishing with embedded credentials PR #458 fixed the two publish crashes when using --db-username / --db-password / --save-db-password, but callers who omit --db-server still hit a raw ValueError from tableauserverclient's _add_connections_element. Fail fast in run_command with a clear, localizable message before we build the ConnectionItem so users get an actionable error instead of an internal stack trace. Update the existing no-db-server test to assert the exit path and add the parallel coverage for the --oauth-username branch. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../publish_command.py | 4 ++ .../locales/en/tabcmd_messages_en.properties | 1 + tests/commands/test_publish_command.py | 42 +++++++++++++++---- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/tabcmd/commands/datasources_and_workbooks/publish_command.py b/tabcmd/commands/datasources_and_workbooks/publish_command.py index dfd26b28..40d90160 100644 --- a/tabcmd/commands/datasources_and_workbooks/publish_command.py +++ b/tabcmd/commands/datasources_and_workbooks/publish_command.py @@ -46,6 +46,10 @@ def define_args(publish_parser): def run_command(cls, args): logger = log(cls.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) + + if (args.db_username or args.oauth_username) and not args.db_server: + Errors.exit_with_error(logger, _("publish.errors.db_server_required")) + session = Session() server = session.create_session(args, logger) diff --git a/tabcmd/locales/en/tabcmd_messages_en.properties b/tabcmd/locales/en/tabcmd_messages_en.properties index e5274230..2624e726 100644 --- a/tabcmd/locales/en/tabcmd_messages_en.properties +++ b/tabcmd/locales/en/tabcmd_messages_en.properties @@ -75,6 +75,7 @@ logout.short_description=Sign out from the server publish.description=Publish a workbook, data source, or extract to the server publish.errors.unexpected_server_response=Unexpected response from the server: {0} publish.errors.server_resource_not_found=The resource you specified does not exist, or you do not have permission to see it. Check your project name and permissions +publish.errors.db_server_required=--db-server is required when publishing a workbook with --db-username or --oauth-username. Use --db-server to specify the database server address the embedded credentials should be associated with. publish.options.append=Append extract file to existing data source publish.options.db-password=Database password for all data sources publish.options.db-server=Server address of the database to associate with the embedded connection credentials. Required when using --db-username or --oauth-username to publish a workbook. diff --git a/tests/commands/test_publish_command.py b/tests/commands/test_publish_command.py index df4b7115..57e2ef9a 100644 --- a/tests/commands/test_publish_command.py +++ b/tests/commands/test_publish_command.py @@ -72,7 +72,7 @@ def test_publish_with_creds(self, mock_path, mock_glob, mock_session): self.assertEqual(len(connections), 1) self.assertEqual(connections[0].server_address, "db.example.com") - def test_publish_with_creds_no_db_server(self, mock_path, mock_glob, mock_session): + def test_publish_with_db_username_missing_db_server_exits(self, mock_path, mock_glob, mock_session): set_up_mock_server(mock_session) mock_path = set_up_mock_path(mock_path) @@ -87,7 +87,7 @@ def test_publish_with_creds_no_db_server(self, mock_path, mock_glob, mock_sessio mock_args.tabbed = True mock_args.db_username = "username" - mock_args.db_password = "oauth_u" + mock_args.db_password = "password" mock_args.db_server = None mock_args.save_db_password = True mock_args.oauth_username = None @@ -97,13 +97,39 @@ def test_publish_with_creds_no_db_server(self, mock_path, mock_glob, mock_sessio mock_args.thumbnail_group = None mock_args.skip_connection_check = False - PublishCommand.run_command(mock_args) - mock_session.internal_server.workbooks.publish.assert_called() + with self.assertRaises(SystemExit): + PublishCommand.run_command(mock_args) + mock_session.internal_server.workbooks.publish.assert_not_called() - call_kwargs = mock_session.internal_server.workbooks.publish.call_args.kwargs - connections = call_kwargs["connections"] - self.assertEqual(len(connections), 1) - self.assertIsNone(connections[0].server_address) + def test_publish_with_oauth_username_missing_db_server_exits(self, mock_path, mock_glob, mock_session): + set_up_mock_server(mock_session) + mock_path = set_up_mock_path(mock_path) + + mock_args.overwrite = False + mock_args.append = True + mock_args.replace = False + + mock_args.filename = "existing_file.twbx" + mock_args.project_name = "project-name" + mock_args.parent_project_path = "projects" + mock_args.name = "" + mock_args.tabbed = True + + mock_args.db_username = None + mock_args.db_password = None + mock_args.db_server = None + mock_args.save_db_password = False + mock_args.oauth_username = "oauth_user" + mock_args.save_oauth = True + mock_args.embed = False + + mock_args.thumbnail_username = None + mock_args.thumbnail_group = None + mock_args.skip_connection_check = False + + with self.assertRaises(SystemExit): + PublishCommand.run_command(mock_args) + mock_session.internal_server.workbooks.publish.assert_not_called() def test_get_files_to_publish_twbx(self, mock_path, mock_glob, mock_session): set_up_mock_server(mock_session) From 95813292e5ccd677101a99ab28827439d85800f4 Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Tue, 8 Sep 2026 17:04:32 -0700 Subject: [PATCH 3/9] Add e2e coverage for --db-server requirement Extend the online publish suite with: - A positive assertion for the happy path: test_wb_publish_embedded now passes --db-server matching the connection host baked into EmbeddedCredentials.twb (see-internal-slack). Without a matching server_address, tableauserverclient silently drops the embedded credentials at publish time, so covering the match is what actually proves the fix. - A negative assertion: test_wb_publish_embedded_missing_db_server_fails runs publish with --db-username but no --db-server and expects a non-zero exit. The check now fires in run_command before any network work, so hardcoded placeholder creds are sufficient. Threads a db_server keyword through the _publish_creds_args helper and records the workbook's connection host as a class constant. Co-Authored-By: Claude Opus 4.7 (1M context) --- tests/e2e/online_tests.py | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/tests/e2e/online_tests.py b/tests/e2e/online_tests.py index 741af663..b4e7a6fb 100644 --- a/tests/e2e/online_tests.py +++ b/tests/e2e/online_tests.py @@ -75,6 +75,9 @@ def get_publishable_name(file_value: str) -> str: TDS_FILE_LIVE = "live_mysql.tds" TWB_FILE_WITH_EMBEDDED_CONNECTION = "EmbeddedCredentials.twb" + # server_address baked into the workbook's element; the server-side + # embed only sticks when --db-server matches this value. + TWB_FILE_EMBEDDED_CONNECTION_SERVER = "see-internal-slack" USERS_DETAILS_FILE = "detailed_users.csv" USERNAMES_FILE = "usernames.csv" @@ -142,7 +145,9 @@ def _publish_args(file, name, optional_args=None): return arguments @staticmethod - def _publish_creds_args(arguments, db_user=None, db_pass=None, db_save=None, oauth_user=None, oauth_save=None): + def _publish_creds_args( + arguments, db_user=None, db_pass=None, db_save=None, oauth_user=None, oauth_save=None, db_server=None + ): if db_user: arguments.append("--db-username") arguments.append(db_user) @@ -156,6 +161,9 @@ def _publish_creds_args(arguments, db_user=None, db_pass=None, db_save=None, oau arguments.append(oauth_user) if oauth_save: arguments.append("--save-oauth") + if db_server: + arguments.append("--db-server") + arguments.append(db_server) return arguments @staticmethod @@ -471,11 +479,32 @@ def test_wb_publish_embedded(self): file = os.path.join("tests", "assets", TestAssets.TWB_FILE_WITH_EMBEDDED_CONNECTION) name_on_server = TestAssets.get_publishable_name(TestAssets.TWB_FILE_WITH_EMBEDDED_CONNECTION) arguments = TabcmdCall._publish_args(file, name_on_server) - arguments = TabcmdCall._publish_creds_args(arguments, database_user, database_password, True) + arguments = TabcmdCall._publish_creds_args( + arguments, + database_user, + database_password, + True, + db_server=TestAssets.TWB_FILE_EMBEDDED_CONNECTION_SERVER, + ) arguments.append("--tabbed") arguments.append("--skip-connection-check") _test_command(arguments) + @pytest.mark.order(11) + def test_wb_publish_embedded_missing_db_server_fails(self): + # publish with --db-username but no --db-server must exit non-zero with + # a friendly message rather than a raw tableauserverclient traceback. + # Hardcoded placeholder creds are fine here: the check fires in + # run_command before we touch the database. + file = os.path.join("tests", "assets", TestAssets.TWB_FILE_WITH_EMBEDDED_CONNECTION) + name_on_server = TestAssets.get_publishable_name(TestAssets.TWB_FILE_WITH_EMBEDDED_CONNECTION) + "-no-server" + arguments = TabcmdCall._publish_args(file, name_on_server) + arguments = TabcmdCall._publish_creds_args(arguments, "placeholder_user", "placeholder_pass", True) + arguments.append("--tabbed") + arguments.append("--skip-connection-check") + with pytest.raises(subprocess.CalledProcessError): + _test_command(arguments) + @pytest.mark.order(12) def test_publish_ds(self): file = os.path.join("tests", "assets", TestAssets.TDSX_FILE_WITH_EXTRACT) From cfe52c10524f43b2c9530fe2da99d14eef5ca522 Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Tue, 8 Sep 2026 22:24:12 -0700 Subject: [PATCH 4/9] Address code-review findings on the --db-server guard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Scope the guard to workbook publishes only. Datasource publishes go through _add_credentials_element on the TSC side, which never requires server_address, so the previous unconditional check was a regression for `tabcmd publish live_mysql.tds --db-username ...` and similar. The guard now checks the target filename extension early (before auth, for fast failure) and repeats per-file inside the workbook branch of the loop for the folder-publish case. Rename the `credentials` parameter of `publish_workbook_file` to `connection` — it holds a single ConnectionItem, not a list. Tests: - Add test_publish_with_oauth_creds covering the oauth branch's server_address assignment (previously untested). - Add test_publish_datasource_with_db_username_no_db_server verifying datasource publishes are not blocked when --db-server is omitted. - Strengthen the e2e negative test to run tabcmd via subprocess.run, capture stdout/stderr, and assert on the localized guard message (or the raw key when .mo has not been regenerated). Any earlier unrelated failure — bad auth, missing asset, session expiry — now fails the test rather than passing it. - Trim the misleading class-constant comment on TWB_FILE_EMBEDDED_ CONNECTION_SERVER; reword the "before we touch the database" comment to reference the guard's contract instead of a specific location. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../publish_command.py | 18 +++-- tests/commands/test_publish_command.py | 72 +++++++++++++++++++ tests/e2e/online_tests.py | 25 ++++--- 3 files changed, 103 insertions(+), 12 deletions(-) diff --git a/tabcmd/commands/datasources_and_workbooks/publish_command.py b/tabcmd/commands/datasources_and_workbooks/publish_command.py index 40d90160..46945659 100644 --- a/tabcmd/commands/datasources_and_workbooks/publish_command.py +++ b/tabcmd/commands/datasources_and_workbooks/publish_command.py @@ -47,8 +47,14 @@ def run_command(cls, args): logger = log(cls.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) + # Fail fast before auth when the direct target is clearly a workbook file: + # TSC's workbook publish path requires ConnectionItem.server_address whenever + # embedded credentials are supplied. Datasource publishes never need it, so + # this check is deliberately scoped to workbook extensions. if (args.db_username or args.oauth_username) and not args.db_server: - Errors.exit_with_error(logger, _("publish.errors.db_server_required")) + filename = (args.filename or "").lower() + if filename.endswith(".twb") or filename.endswith(".twbx"): + Errors.exit_with_error(logger, _("publish.errors.db_server_required")) session = Session() server = session.create_session(args, logger) @@ -92,6 +98,10 @@ def run_command(cls, args): source = PublishCommand.get_filename_extension_if_tableau_type(logger, str_filename) logger.info(_("publish.status").format(str_filename)) if source in ["twbx", "twb"]: + # TSC's workbook publish path requires ConnectionItem.server_address whenever + # embedded connection credentials are supplied; datasource publish does not. + if (args.db_username or args.oauth_username) and not args.db_server: + Errors.exit_with_error(logger, _("publish.errors.db_server_required")) try: published_item = PublishCommand.publish_workbook_file( args=args, @@ -100,7 +110,7 @@ def run_command(cls, args): project_id=project_id, str_filename=str_filename, publish_mode=publish_mode, - credentials=workbook_connections, + connection=workbook_connections, ) except Exception as e: Errors.exit_with_error(logger, exception=e) @@ -176,7 +186,7 @@ def get_publish_mode(args, logger): return publish_mode @staticmethod - def publish_workbook_file(args, logger, server, project_id, str_filename, publish_mode, credentials): + def publish_workbook_file(args, logger, server, project_id, str_filename, publish_mode, connection): if args.thumbnail_group: raise AttributeError("Generating thumbnails for a group is not yet implemented.") if args.thumbnail_username and args.thumbnail_group: @@ -189,7 +199,7 @@ def publish_workbook_file(args, logger, server, project_id, str_filename, publis publish_mode, # args.thumbnail_username, not yet implemented in tsc # args.thumbnail_group, - connections=[credentials] if credentials else None, + connections=[connection] if connection else None, as_job=False, skip_connection_check=args.skip_connection_check, ) diff --git a/tests/commands/test_publish_command.py b/tests/commands/test_publish_command.py index 57e2ef9a..5c54bc6e 100644 --- a/tests/commands/test_publish_command.py +++ b/tests/commands/test_publish_command.py @@ -131,6 +131,78 @@ def test_publish_with_oauth_username_missing_db_server_exits(self, mock_path, mo PublishCommand.run_command(mock_args) mock_session.internal_server.workbooks.publish.assert_not_called() + def test_publish_with_oauth_creds(self, mock_path, mock_glob, mock_session): + set_up_mock_server(mock_session) + mock_path = set_up_mock_path(mock_path) + + mock_args.overwrite = False + mock_args.append = True + mock_args.replace = False + + mock_args.filename = "existing_file.twbx" + mock_args.project_name = "project-name" + mock_args.parent_project_path = "projects" + mock_args.name = "" + mock_args.tabbed = True + + mock_args.db_username = None + mock_args.db_password = None + mock_args.save_db_password = False + mock_args.oauth_username = "oauth_user" + mock_args.save_oauth = True + mock_args.db_server = "db.example.com" + mock_args.embed = False + + mock_args.thumbnail_username = None + mock_args.thumbnail_group = None + mock_args.skip_connection_check = False + + PublishCommand.run_command(mock_args) + mock_session.internal_server.workbooks.publish.assert_called() + + call_kwargs = mock_session.internal_server.workbooks.publish.call_args.kwargs + connections = call_kwargs["connections"] + self.assertEqual(len(connections), 1) + self.assertEqual(connections[0].server_address, "db.example.com") + + def test_publish_datasource_with_db_username_no_db_server(self, mock_path, mock_glob, mock_session): + # Datasource publishes send credentials via _add_credentials_element on the TSC side, + # which does not require server_address. --db-server must not be required here. + set_up_mock_server(mock_session) + # set_up_mock_server only wires .workbooks on the mocked server (TSC.Server class-spec + # doesn't expose instance attributes from __init__); wire .datasources by hand. + mock_session.internal_server.datasources = mock.MagicMock() + mock_path = set_up_mock_path(mock_path) + # set_up_mock_path hardcodes splitext -> [_, 'twbx']; override so extension routing + # actually sees a datasource here. + mock_path.splitext = lambda x: ["file", "tdsx"] + + mock_args.overwrite = False + mock_args.append = True + mock_args.replace = False + + mock_args.filename = "existing_file.tdsx" + mock_args.project_name = "project-name" + mock_args.parent_project_path = "projects" + mock_args.name = "" + mock_args.tabbed = True + + mock_args.db_username = "username" + mock_args.db_password = "password" + mock_args.db_server = None + mock_args.save_db_password = True + mock_args.oauth_username = None + mock_args.embed = False + mock_args.use_tableau_bridge = False + + mock_args.thumbnail_username = None + mock_args.thumbnail_group = None + mock_args.skip_connection_check = False + + PublishCommand.run_command(mock_args) + mock_session.internal_server.datasources.publish.assert_called() + mock_session.internal_server.workbooks.publish.assert_not_called() + def test_get_files_to_publish_twbx(self, mock_path, mock_glob, mock_session): set_up_mock_server(mock_session) mock_path = set_up_mock_path(mock_path) diff --git a/tests/e2e/online_tests.py b/tests/e2e/online_tests.py index b4e7a6fb..b8ea4bfa 100644 --- a/tests/e2e/online_tests.py +++ b/tests/e2e/online_tests.py @@ -75,8 +75,7 @@ def get_publishable_name(file_value: str) -> str: TDS_FILE_LIVE = "live_mysql.tds" TWB_FILE_WITH_EMBEDDED_CONNECTION = "EmbeddedCredentials.twb" - # server_address baked into the workbook's element; the server-side - # embed only sticks when --db-server matches this value. + # server_address baked into the workbook's element. TWB_FILE_EMBEDDED_CONNECTION_SERVER = "see-internal-slack" USERS_DETAILS_FILE = "detailed_users.csv" @@ -492,18 +491,28 @@ def test_wb_publish_embedded(self): @pytest.mark.order(11) def test_wb_publish_embedded_missing_db_server_fails(self): - # publish with --db-username but no --db-server must exit non-zero with - # a friendly message rather than a raw tableauserverclient traceback. - # Hardcoded placeholder creds are fine here: the check fires in - # run_command before we touch the database. + # Publish with --db-username but no --db-server must exit non-zero with our + # friendly message rather than a raw tableauserverclient traceback. The guard + # short-circuits before any real work, so throwaway credentials are safe here. file = os.path.join("tests", "assets", TestAssets.TWB_FILE_WITH_EMBEDDED_CONNECTION) name_on_server = TestAssets.get_publishable_name(TestAssets.TWB_FILE_WITH_EMBEDDED_CONNECTION) + "-no-server" arguments = TabcmdCall._publish_args(file, name_on_server) arguments = TabcmdCall._publish_creds_args(arguments, "placeholder_user", "placeholder_pass", True) arguments.append("--tabbed") arguments.append("--skip-connection-check") - with pytest.raises(subprocess.CalledProcessError): - _test_command(arguments) + + login_args = setup_e2e.get_login_args() + if login_args is None: + pytest.skip("No credentials available (credentials.py not found)") + calling_args = ["python", "-m", "tabcmd"] + arguments + login_args + [debug_log] + ["--no-certcheck"] + result = subprocess.run(calling_args, capture_output=True, text=True) + + assert result.returncode != 0, "expected non-zero exit for missing --db-server" + # Localized string OR the raw key (if .mo has not been regenerated yet) both signal our guard. + combined = (result.stdout or "") + (result.stderr or "") + assert "publish.errors.db_server_required" in combined or "--db-server is required" in combined, ( + "expected guard message in output; got:\n" + combined + ) @pytest.mark.order(12) def test_publish_ds(self): From c7b06db458843bf55d0ca61615f732849472971f Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Thu, 10 Sep 2026 13:06:55 -0700 Subject: [PATCH 5/9] Revert "Address code-review findings on the --db-server guard" This reverts commit cfe52c10524f43b2c9530fe2da99d14eef5ca522. --- .../publish_command.py | 18 ++--- tests/commands/test_publish_command.py | 72 ------------------- tests/e2e/online_tests.py | 25 +++---- 3 files changed, 12 insertions(+), 103 deletions(-) diff --git a/tabcmd/commands/datasources_and_workbooks/publish_command.py b/tabcmd/commands/datasources_and_workbooks/publish_command.py index 46945659..40d90160 100644 --- a/tabcmd/commands/datasources_and_workbooks/publish_command.py +++ b/tabcmd/commands/datasources_and_workbooks/publish_command.py @@ -47,14 +47,8 @@ def run_command(cls, args): logger = log(cls.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) - # Fail fast before auth when the direct target is clearly a workbook file: - # TSC's workbook publish path requires ConnectionItem.server_address whenever - # embedded credentials are supplied. Datasource publishes never need it, so - # this check is deliberately scoped to workbook extensions. if (args.db_username or args.oauth_username) and not args.db_server: - filename = (args.filename or "").lower() - if filename.endswith(".twb") or filename.endswith(".twbx"): - Errors.exit_with_error(logger, _("publish.errors.db_server_required")) + Errors.exit_with_error(logger, _("publish.errors.db_server_required")) session = Session() server = session.create_session(args, logger) @@ -98,10 +92,6 @@ def run_command(cls, args): source = PublishCommand.get_filename_extension_if_tableau_type(logger, str_filename) logger.info(_("publish.status").format(str_filename)) if source in ["twbx", "twb"]: - # TSC's workbook publish path requires ConnectionItem.server_address whenever - # embedded connection credentials are supplied; datasource publish does not. - if (args.db_username or args.oauth_username) and not args.db_server: - Errors.exit_with_error(logger, _("publish.errors.db_server_required")) try: published_item = PublishCommand.publish_workbook_file( args=args, @@ -110,7 +100,7 @@ def run_command(cls, args): project_id=project_id, str_filename=str_filename, publish_mode=publish_mode, - connection=workbook_connections, + credentials=workbook_connections, ) except Exception as e: Errors.exit_with_error(logger, exception=e) @@ -186,7 +176,7 @@ def get_publish_mode(args, logger): return publish_mode @staticmethod - def publish_workbook_file(args, logger, server, project_id, str_filename, publish_mode, connection): + def publish_workbook_file(args, logger, server, project_id, str_filename, publish_mode, credentials): if args.thumbnail_group: raise AttributeError("Generating thumbnails for a group is not yet implemented.") if args.thumbnail_username and args.thumbnail_group: @@ -199,7 +189,7 @@ def publish_workbook_file(args, logger, server, project_id, str_filename, publis publish_mode, # args.thumbnail_username, not yet implemented in tsc # args.thumbnail_group, - connections=[connection] if connection else None, + connections=[credentials] if credentials else None, as_job=False, skip_connection_check=args.skip_connection_check, ) diff --git a/tests/commands/test_publish_command.py b/tests/commands/test_publish_command.py index 5c54bc6e..57e2ef9a 100644 --- a/tests/commands/test_publish_command.py +++ b/tests/commands/test_publish_command.py @@ -131,78 +131,6 @@ def test_publish_with_oauth_username_missing_db_server_exits(self, mock_path, mo PublishCommand.run_command(mock_args) mock_session.internal_server.workbooks.publish.assert_not_called() - def test_publish_with_oauth_creds(self, mock_path, mock_glob, mock_session): - set_up_mock_server(mock_session) - mock_path = set_up_mock_path(mock_path) - - mock_args.overwrite = False - mock_args.append = True - mock_args.replace = False - - mock_args.filename = "existing_file.twbx" - mock_args.project_name = "project-name" - mock_args.parent_project_path = "projects" - mock_args.name = "" - mock_args.tabbed = True - - mock_args.db_username = None - mock_args.db_password = None - mock_args.save_db_password = False - mock_args.oauth_username = "oauth_user" - mock_args.save_oauth = True - mock_args.db_server = "db.example.com" - mock_args.embed = False - - mock_args.thumbnail_username = None - mock_args.thumbnail_group = None - mock_args.skip_connection_check = False - - PublishCommand.run_command(mock_args) - mock_session.internal_server.workbooks.publish.assert_called() - - call_kwargs = mock_session.internal_server.workbooks.publish.call_args.kwargs - connections = call_kwargs["connections"] - self.assertEqual(len(connections), 1) - self.assertEqual(connections[0].server_address, "db.example.com") - - def test_publish_datasource_with_db_username_no_db_server(self, mock_path, mock_glob, mock_session): - # Datasource publishes send credentials via _add_credentials_element on the TSC side, - # which does not require server_address. --db-server must not be required here. - set_up_mock_server(mock_session) - # set_up_mock_server only wires .workbooks on the mocked server (TSC.Server class-spec - # doesn't expose instance attributes from __init__); wire .datasources by hand. - mock_session.internal_server.datasources = mock.MagicMock() - mock_path = set_up_mock_path(mock_path) - # set_up_mock_path hardcodes splitext -> [_, 'twbx']; override so extension routing - # actually sees a datasource here. - mock_path.splitext = lambda x: ["file", "tdsx"] - - mock_args.overwrite = False - mock_args.append = True - mock_args.replace = False - - mock_args.filename = "existing_file.tdsx" - mock_args.project_name = "project-name" - mock_args.parent_project_path = "projects" - mock_args.name = "" - mock_args.tabbed = True - - mock_args.db_username = "username" - mock_args.db_password = "password" - mock_args.db_server = None - mock_args.save_db_password = True - mock_args.oauth_username = None - mock_args.embed = False - mock_args.use_tableau_bridge = False - - mock_args.thumbnail_username = None - mock_args.thumbnail_group = None - mock_args.skip_connection_check = False - - PublishCommand.run_command(mock_args) - mock_session.internal_server.datasources.publish.assert_called() - mock_session.internal_server.workbooks.publish.assert_not_called() - def test_get_files_to_publish_twbx(self, mock_path, mock_glob, mock_session): set_up_mock_server(mock_session) mock_path = set_up_mock_path(mock_path) diff --git a/tests/e2e/online_tests.py b/tests/e2e/online_tests.py index b8ea4bfa..b4e7a6fb 100644 --- a/tests/e2e/online_tests.py +++ b/tests/e2e/online_tests.py @@ -75,7 +75,8 @@ def get_publishable_name(file_value: str) -> str: TDS_FILE_LIVE = "live_mysql.tds" TWB_FILE_WITH_EMBEDDED_CONNECTION = "EmbeddedCredentials.twb" - # server_address baked into the workbook's element. + # server_address baked into the workbook's element; the server-side + # embed only sticks when --db-server matches this value. TWB_FILE_EMBEDDED_CONNECTION_SERVER = "see-internal-slack" USERS_DETAILS_FILE = "detailed_users.csv" @@ -491,28 +492,18 @@ def test_wb_publish_embedded(self): @pytest.mark.order(11) def test_wb_publish_embedded_missing_db_server_fails(self): - # Publish with --db-username but no --db-server must exit non-zero with our - # friendly message rather than a raw tableauserverclient traceback. The guard - # short-circuits before any real work, so throwaway credentials are safe here. + # publish with --db-username but no --db-server must exit non-zero with + # a friendly message rather than a raw tableauserverclient traceback. + # Hardcoded placeholder creds are fine here: the check fires in + # run_command before we touch the database. file = os.path.join("tests", "assets", TestAssets.TWB_FILE_WITH_EMBEDDED_CONNECTION) name_on_server = TestAssets.get_publishable_name(TestAssets.TWB_FILE_WITH_EMBEDDED_CONNECTION) + "-no-server" arguments = TabcmdCall._publish_args(file, name_on_server) arguments = TabcmdCall._publish_creds_args(arguments, "placeholder_user", "placeholder_pass", True) arguments.append("--tabbed") arguments.append("--skip-connection-check") - - login_args = setup_e2e.get_login_args() - if login_args is None: - pytest.skip("No credentials available (credentials.py not found)") - calling_args = ["python", "-m", "tabcmd"] + arguments + login_args + [debug_log] + ["--no-certcheck"] - result = subprocess.run(calling_args, capture_output=True, text=True) - - assert result.returncode != 0, "expected non-zero exit for missing --db-server" - # Localized string OR the raw key (if .mo has not been regenerated yet) both signal our guard. - combined = (result.stdout or "") + (result.stderr or "") - assert "publish.errors.db_server_required" in combined or "--db-server is required" in combined, ( - "expected guard message in output; got:\n" + combined - ) + with pytest.raises(subprocess.CalledProcessError): + _test_command(arguments) @pytest.mark.order(12) def test_publish_ds(self): From 6cd6e060186507659ecacb7731b3830b623274ff Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Thu, 10 Sep 2026 13:06:56 -0700 Subject: [PATCH 6/9] Revert "Add e2e coverage for --db-server requirement" This reverts commit 95813292e5ccd677101a99ab28827439d85800f4. --- tests/e2e/online_tests.py | 33 ++------------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) diff --git a/tests/e2e/online_tests.py b/tests/e2e/online_tests.py index b4e7a6fb..741af663 100644 --- a/tests/e2e/online_tests.py +++ b/tests/e2e/online_tests.py @@ -75,9 +75,6 @@ def get_publishable_name(file_value: str) -> str: TDS_FILE_LIVE = "live_mysql.tds" TWB_FILE_WITH_EMBEDDED_CONNECTION = "EmbeddedCredentials.twb" - # server_address baked into the workbook's element; the server-side - # embed only sticks when --db-server matches this value. - TWB_FILE_EMBEDDED_CONNECTION_SERVER = "see-internal-slack" USERS_DETAILS_FILE = "detailed_users.csv" USERNAMES_FILE = "usernames.csv" @@ -145,9 +142,7 @@ def _publish_args(file, name, optional_args=None): return arguments @staticmethod - def _publish_creds_args( - arguments, db_user=None, db_pass=None, db_save=None, oauth_user=None, oauth_save=None, db_server=None - ): + def _publish_creds_args(arguments, db_user=None, db_pass=None, db_save=None, oauth_user=None, oauth_save=None): if db_user: arguments.append("--db-username") arguments.append(db_user) @@ -161,9 +156,6 @@ def _publish_creds_args( arguments.append(oauth_user) if oauth_save: arguments.append("--save-oauth") - if db_server: - arguments.append("--db-server") - arguments.append(db_server) return arguments @staticmethod @@ -479,32 +471,11 @@ def test_wb_publish_embedded(self): file = os.path.join("tests", "assets", TestAssets.TWB_FILE_WITH_EMBEDDED_CONNECTION) name_on_server = TestAssets.get_publishable_name(TestAssets.TWB_FILE_WITH_EMBEDDED_CONNECTION) arguments = TabcmdCall._publish_args(file, name_on_server) - arguments = TabcmdCall._publish_creds_args( - arguments, - database_user, - database_password, - True, - db_server=TestAssets.TWB_FILE_EMBEDDED_CONNECTION_SERVER, - ) + arguments = TabcmdCall._publish_creds_args(arguments, database_user, database_password, True) arguments.append("--tabbed") arguments.append("--skip-connection-check") _test_command(arguments) - @pytest.mark.order(11) - def test_wb_publish_embedded_missing_db_server_fails(self): - # publish with --db-username but no --db-server must exit non-zero with - # a friendly message rather than a raw tableauserverclient traceback. - # Hardcoded placeholder creds are fine here: the check fires in - # run_command before we touch the database. - file = os.path.join("tests", "assets", TestAssets.TWB_FILE_WITH_EMBEDDED_CONNECTION) - name_on_server = TestAssets.get_publishable_name(TestAssets.TWB_FILE_WITH_EMBEDDED_CONNECTION) + "-no-server" - arguments = TabcmdCall._publish_args(file, name_on_server) - arguments = TabcmdCall._publish_creds_args(arguments, "placeholder_user", "placeholder_pass", True) - arguments.append("--tabbed") - arguments.append("--skip-connection-check") - with pytest.raises(subprocess.CalledProcessError): - _test_command(arguments) - @pytest.mark.order(12) def test_publish_ds(self): file = os.path.join("tests", "assets", TestAssets.TDSX_FILE_WITH_EXTRACT) From ee70e71f79907a3216bccbccd467efeba20ef9c9 Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Thu, 10 Sep 2026 13:06:57 -0700 Subject: [PATCH 7/9] Revert "Require --db-server when publishing with embedded credentials" This reverts commit d59ee65767d3ea009aec87afe83ae3c81c10fb96. --- .../publish_command.py | 4 -- .../locales/en/tabcmd_messages_en.properties | 1 - tests/commands/test_publish_command.py | 42 ++++--------------- 3 files changed, 8 insertions(+), 39 deletions(-) diff --git a/tabcmd/commands/datasources_and_workbooks/publish_command.py b/tabcmd/commands/datasources_and_workbooks/publish_command.py index 40d90160..dfd26b28 100644 --- a/tabcmd/commands/datasources_and_workbooks/publish_command.py +++ b/tabcmd/commands/datasources_and_workbooks/publish_command.py @@ -46,10 +46,6 @@ def define_args(publish_parser): def run_command(cls, args): logger = log(cls.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) - - if (args.db_username or args.oauth_username) and not args.db_server: - Errors.exit_with_error(logger, _("publish.errors.db_server_required")) - session = Session() server = session.create_session(args, logger) diff --git a/tabcmd/locales/en/tabcmd_messages_en.properties b/tabcmd/locales/en/tabcmd_messages_en.properties index 2624e726..e5274230 100644 --- a/tabcmd/locales/en/tabcmd_messages_en.properties +++ b/tabcmd/locales/en/tabcmd_messages_en.properties @@ -75,7 +75,6 @@ logout.short_description=Sign out from the server publish.description=Publish a workbook, data source, or extract to the server publish.errors.unexpected_server_response=Unexpected response from the server: {0} publish.errors.server_resource_not_found=The resource you specified does not exist, or you do not have permission to see it. Check your project name and permissions -publish.errors.db_server_required=--db-server is required when publishing a workbook with --db-username or --oauth-username. Use --db-server to specify the database server address the embedded credentials should be associated with. publish.options.append=Append extract file to existing data source publish.options.db-password=Database password for all data sources publish.options.db-server=Server address of the database to associate with the embedded connection credentials. Required when using --db-username or --oauth-username to publish a workbook. diff --git a/tests/commands/test_publish_command.py b/tests/commands/test_publish_command.py index 57e2ef9a..df4b7115 100644 --- a/tests/commands/test_publish_command.py +++ b/tests/commands/test_publish_command.py @@ -72,7 +72,7 @@ def test_publish_with_creds(self, mock_path, mock_glob, mock_session): self.assertEqual(len(connections), 1) self.assertEqual(connections[0].server_address, "db.example.com") - def test_publish_with_db_username_missing_db_server_exits(self, mock_path, mock_glob, mock_session): + def test_publish_with_creds_no_db_server(self, mock_path, mock_glob, mock_session): set_up_mock_server(mock_session) mock_path = set_up_mock_path(mock_path) @@ -87,7 +87,7 @@ def test_publish_with_db_username_missing_db_server_exits(self, mock_path, mock_ mock_args.tabbed = True mock_args.db_username = "username" - mock_args.db_password = "password" + mock_args.db_password = "oauth_u" mock_args.db_server = None mock_args.save_db_password = True mock_args.oauth_username = None @@ -97,39 +97,13 @@ def test_publish_with_db_username_missing_db_server_exits(self, mock_path, mock_ mock_args.thumbnail_group = None mock_args.skip_connection_check = False - with self.assertRaises(SystemExit): - PublishCommand.run_command(mock_args) - mock_session.internal_server.workbooks.publish.assert_not_called() - - def test_publish_with_oauth_username_missing_db_server_exits(self, mock_path, mock_glob, mock_session): - set_up_mock_server(mock_session) - mock_path = set_up_mock_path(mock_path) - - mock_args.overwrite = False - mock_args.append = True - mock_args.replace = False - - mock_args.filename = "existing_file.twbx" - mock_args.project_name = "project-name" - mock_args.parent_project_path = "projects" - mock_args.name = "" - mock_args.tabbed = True - - mock_args.db_username = None - mock_args.db_password = None - mock_args.db_server = None - mock_args.save_db_password = False - mock_args.oauth_username = "oauth_user" - mock_args.save_oauth = True - mock_args.embed = False - - mock_args.thumbnail_username = None - mock_args.thumbnail_group = None - mock_args.skip_connection_check = False + PublishCommand.run_command(mock_args) + mock_session.internal_server.workbooks.publish.assert_called() - with self.assertRaises(SystemExit): - PublishCommand.run_command(mock_args) - mock_session.internal_server.workbooks.publish.assert_not_called() + call_kwargs = mock_session.internal_server.workbooks.publish.call_args.kwargs + connections = call_kwargs["connections"] + self.assertEqual(len(connections), 1) + self.assertIsNone(connections[0].server_address) def test_get_files_to_publish_twbx(self, mock_path, mock_glob, mock_session): set_up_mock_server(mock_session) From bcf81246bd3ab491a056674364a3ef370cb8d684 Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Thu, 10 Sep 2026 14:24:40 -0700 Subject: [PATCH 8/9] Fix NameError in uniquify_file when no lines are discarded The success-print branch referenced uniques instead of unique_lines, breaking doit properties when input files contained no non-'=' non- codestring lines. Co-Authored-By: Claude Opus 4.7 (1M context) --- dodo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dodo.py b/dodo.py index 9d193c9b..82ac894c 100644 --- a/dodo.py +++ b/dodo.py @@ -455,7 +455,7 @@ def uniquify_file(filename): ) ) else: - print("Saved {} sorted unique lines to {}".format(len(uniques), filename)) + print("Saved {} sorted unique lines to {}".format(len(unique_lines), filename)) def task_clean_all(): From a3066475e30c676274e8ee47abdb3e848fe3c489 Mon Sep 17 00:00:00 2001 From: Jac Fitzgerald Date: Thu, 10 Sep 2026 14:25:58 -0700 Subject: [PATCH 9/9] Regenerate localized .mo files after doit localize Compiles the new `publish.options.db-server` help-text key added by #458 (backported in PR A) into the runtime gettext catalogs. Without this, English users see the raw msgid key in `tabcmd publish --help`. Non-English locales fall back to English until translators supply their versions. Co-Authored-By: Claude Opus 4.7 (1M context) --- tabcmd/locales/de/LC_MESSAGES/tabcmd.mo | Bin 20705 -> 19849 bytes tabcmd/locales/en/LC_MESSAGES/tabcmd.mo | Bin 20732 -> 22763 bytes tabcmd/locales/es/LC_MESSAGES/tabcmd.mo | Bin 20423 -> 19590 bytes tabcmd/locales/fr/LC_MESSAGES/tabcmd.mo | Bin 20860 -> 20033 bytes tabcmd/locales/ga/LC_MESSAGES/tabcmd.mo | Bin 20739 -> 19877 bytes tabcmd/locales/it/LC_MESSAGES/tabcmd.mo | Bin 20566 -> 19743 bytes tabcmd/locales/ja/LC_MESSAGES/tabcmd.mo | Bin 23120 -> 22297 bytes tabcmd/locales/ko/LC_MESSAGES/tabcmd.mo | Bin 20852 -> 20047 bytes tabcmd/locales/pt/LC_MESSAGES/tabcmd.mo | Bin 19726 -> 18896 bytes tabcmd/locales/sv/LC_MESSAGES/tabcmd.mo | Bin 19192 -> 18383 bytes tabcmd/locales/zh/LC_MESSAGES/tabcmd.mo | Bin 17876 -> 17094 bytes 11 files changed, 0 insertions(+), 0 deletions(-) diff --git a/tabcmd/locales/de/LC_MESSAGES/tabcmd.mo b/tabcmd/locales/de/LC_MESSAGES/tabcmd.mo index 91b71d3f466b8beee63ab0fca808d4ff020665cd..30f3641a567ff848658726defeab0404fb80aa38 100644 GIT binary patch delta 3750 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 Hv&a1h?g=N3 diff --git a/tabcmd/locales/en/LC_MESSAGES/tabcmd.mo b/tabcmd/locales/en/LC_MESSAGES/tabcmd.mo index a067f324e46517169c6aa3b84575f9fb3f72e1a8..7238ce249e974c5f16f0720ce49c643d155464fa 100644 GIT binary patch delta 7352 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 eSwmgBDUyg<6C^-++^gjUCzW2`n diff --git a/tabcmd/locales/es/LC_MESSAGES/tabcmd.mo b/tabcmd/locales/es/LC_MESSAGES/tabcmd.mo index fdbbd2bfcd42143ddf7559980594a6b10e38f15f..aef0790b028f4d8629e57907ccabfa93bd5bfc9f 100644 GIT binary patch delta 3750 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 Z>i+)*pBvkDTl^{w&aF!A6tAkO`Y(PoHXr~1 diff --git a/tabcmd/locales/fr/LC_MESSAGES/tabcmd.mo b/tabcmd/locales/fr/LC_MESSAGES/tabcmd.mo index 7a160340d039e4af37964f986c43fa5501bbb260..b421c6f1772785f1cadd51e472c29fe8b8c01ae9 100644 GIT binary patch delta 3753 zcmZwJ4{(%68OQNWVnW(LAt5CE3v3_|2;o920SOUB^NP4+@lbpGKy?d`I zb?Pxzlonb#y{1(x)j?~uimf@dcAzsV?WncjfQ8zjsW@Y;btog!QtH6q_jmU;wT_v~ zecs)BclUXo-FuUZ`wD*bNJ09wijNE%eh%_Gli!QQYJKqYYMC+9X^!GVynwY>I^LKm z*nqRJ4K4OyHE#3#I#$wt3d`|%)VP8&=^y z)I!hTRQxLvgSmuSsBBVx;f0>-Q2m3b`R_&r{s>mGzB$N+B0h?W>73S1~IwndPViI#BlwA}_Pub1z!jKU4jc@d;!O za~8Enr9`Dn8c`+dMD6Vsv=~L*w;OqxEN|M=7rp*BJtwewE&W%c#V%9@UC;CbT(HgN zDP(PP$ZMZO1$G84UO__>HDE3?)SeEa0^EuUXa}l-KSBlcOJoW&>iI4z;Bv}{Y16=k zBDxmY1>;9mVhB~r`%r;>2es!1P!pU)?d{vBz=~OogKp}PHOvasJl&|XFo+7|8^{oo z#d3ZB|Gu?8d!at%i zZ=!s9aCM>%gq1CwAg*um!7mC}_eP z@ng6Z+i(Os@EmHMHXa&!Zglge_Lsc&1E`7}M5Z)H(p*pta~@aYG{W48n{Ye6fyz8W z+U>XyKRmBm!U3Xv4X(ujY{L;`Dsv9CwY68X|JaJE+>cR*^?2U2Imd-g zWBE1tfs2qXb2F-cC#nLEc|MEU>*J^rzJuDTnvdq612-c@F<-<_;Nz(AZ=eFYjJ(YB zrN-Q#@Bex(cGB@MD#N*?bset3>v0#Jz+>2fKcGCi?>xSR)0Z2w7fY%CI{Y4L+*!1^ ze1$O|$BnoKA3}E3yoPtOzPW;vbr*gOH9;BaXsApoB$K%tU&*22x zM{yed87;ntzsKoq`7Qbz*3d5DWV1`A4k@C!32X7*)zrU_izn$A!m3a5ZxP;yoHMhC z^r({AgcETX^#ptjXW~n!1#@aj7cnEA2i_|cn0_4XK)uAxe-T^YMNy?8i|LIjg2NjtT0f|&(tTQjGdmu7=&kB>{Q z$)#w=Qfx6^&wr)WVmd-e*T(v6cdqDmEUB)6*pQ7l$)vyEv0-isMf=A-wd8H{CA6_z zn#o4%4meTk+#YgGdn{oi=~%+CO4lYGE?hUBY-ws@6T*%^q{r3G@yuYO7$l3b*y|&eha+O^?Q13Hg$3|lj8+B~lNx3%ePufFIxS7t+HWoVO EKX!OSdH?_b delta 4419 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 delta 4478 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 OmUHEW>Cwy6#{Ca)geC|8 diff --git a/tabcmd/locales/ja/LC_MESSAGES/tabcmd.mo b/tabcmd/locales/ja/LC_MESSAGES/tabcmd.mo index 7d06038c6d3d0505c10eda266bf184663cd3364d..8bec794465ea14416b700943ed5259295490cd99 100644 GIT binary patch delta 3772 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 h_|Kz;4s70B`+vHLWKWOp5N>cy; diff --git a/tabcmd/locales/ko/LC_MESSAGES/tabcmd.mo b/tabcmd/locales/ko/LC_MESSAGES/tabcmd.mo index 54c8d41cffc8916eb2e18c5e5ddb8640a1b41025..432aa94dfe7055f9329c88820e1479ffba8b2839 100644 GIT binary patch delta 3758 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 a1Yhiz6-$ooHZ&OuWE diff --git a/tabcmd/locales/pt/LC_MESSAGES/tabcmd.mo b/tabcmd/locales/pt/LC_MESSAGES/tabcmd.mo index 2b6036af3e07644934115957dbfd020780d42deb..8929f104fbb80f43797ea57afc70272e3cb6ebac 100644 GIT binary patch delta 3727 zcmZwJ3vg7`9mnw#76^hC2q6i?BzFM~#AH)3krDz1fk2s528mQ#O5E(;WVhMu4ZC*< zOly}Ju~QkqX?O4u#b)r)R>TLZZGA9hu${JQZB1LPgD~v~?bzB(WjaG>ap?EA_Zn-b z%(9<*&Yt@}|MNfRUf4fW^qX8!_H@a_1BO2@^Y=>rUYw-XCx70ZX3Sigr*JxsVGyTW zZp>_~!)k0p3%jr!clq9rrL>>HnfNo*eQ#rxFE-X5xU17{MSdR*LE6&3~v~UQy z!Mube_zu?K2dD`y{|w1s5VepFv@njkZ;#*qeJmt`LFPAa`vWeZ0++MQMOcSQs1t*@ z3(N2jYN8jg0?!~hn2%5sO`G9OyvTPws=p5v|87*`4`C_uo0qvz#&4oB8%0g1hHjXL z3$Yn3+=|+gEUMH)e)}krgZUNe{!^%gFX2^KMzHzVikk0s%qqYgTr}VT)XHALS{y|M zD4XRa(tv8Wq4w~Let*C3E}TPu4z(pmP!&3Xs?bTK$mV@)#j#n`pT(MHMk`=DYGqqc zXJ8O3@m{X-Ad(OQ^GOC-N~z_)?&sqE`Axzx^+?XqOR{oXir`0y@2y@E!JSyRt zlo7M0jtgb93fTn{Mpa@ERm%OS#2!KI`Aet(CsBL*PgG))n2m#OYLPk2QdFEy)LH05 zCGr4ri^=0mJ^#PvLO1*gwX%!IJIPd%6)!up5S2g^YT^!5AR8^rqAECyijzk^<_*4- zzz3-D0fNga)VL*TGrzf+3r&zfo$}qjhf#q>P&fVqLpYT(EWo9xm2E|h+lze66MSic zSN;C8s6+ym*FP5(uNkx2s|{Q{h!JECa|xTVn!2vWPE=wK;I()hwKeBZl`7_>>I{@( zG0w-ycnxYx7GpiG#wEB7$M6U9sJ}8k#L3x@CvY8ZWO)ZzRqD*hO%LKUn+dw)G@Ava&0^$yQ&I#i;^k&ijX*XQsIegUh9 z+Jb$kgdRt2#V>Iwj^TP-%u7Rw-hqmYHa#EB`HO%g&<`Yv5n5Rk#JG;xH=CVO)X7F^SnrTs+N1 zk`2mZH781$kKmW_0Nz#aG$wqb3PH!g;wwD;jg{5peG@;6Ww zE4kjQSSL~>vkl3?3?pkXBba7>6X2QHj)T~aqqq#4Ie{wOHq;Goq56wit`c2^3^g%a zj>C8po<=3mz=6@0IXDaVqAEO$ddz>0Sq=EJ-w_~s8|`^Gj1ioP6I;DgU4|2B*Wz@n zM;)qG)Z?`g52J(SSV>l8cpY*s&3aS<8LYyGmQ()-7cbKBHLT`n?!zJET$+V9cw5kk zlWFfkRpQ%Ni6^iEPvZtWk9s`Uws}v>S5fyphBf#k&c)Y}-86q`%X&XlQZMbzGE8DW zs`T%o4$(@E_$jop4Og+zUAP++=nSe-6|22havkoaeJiH%EK(G6+ZwL|_u^}`k7c>I zkBht8y+FaW-hV`HLG969cnBZGui)Bs-b9a~_Vh=nQon}mmU$1AP|fGPL%azs+WRnw zPoW7%qnWgwN{7<1+?-i6a?eelk*}I@t|(tu(lsI1QdN@wVd>GL{KI8ePRNf`OqoPi zX?|*TRbY#qN;#=ecR1RWvbSaIv>S>iw}%t)XjjBZx^~j-a(52c#tnBz`lBIlbkt7R zt{v)4Ihlb^|I!nVCo(BJly<{zCY`GZHkbF>Zphw2q;%X#hLVok)#GH6(R@cRH6iPT z9SEmLKGd6Vy2FW3w;c;_k2|TfANte3l2y``@_lT|NALwrz5HO zfbJX*yr?j5;m$-n**D(*Nq2g{j>LQ7k=(KQ(Ll!S$t_s$LcaK_Zv^rO7TzAnhwA@5 zAs=l#H!;7b=_i-v53Yz$&Yf8>KewoH+2nR=VMlY5*0km}H#Ox~uGv$ZU0Yb9HNM0a zJndRekJVWyx;4J2O)+QC>bKMBaIbA87!*(Tj{j=0Zp$m74Q@5_UKf>W#axOm`^msE6HdEZkHW?j)_S e^>Hmep3>sTS+(9+tJTkPh1C$N4dq_#Sp6Tvi8A&8 delta 4474 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 Vz5lFj4We9Q8++@+xl2{++2Ko+Vb5CbHA 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 t