くりーむわーかー

プログラムとか。作ってて ・試しててハマった事など。誰かのお役に立てば幸いかと。 その他、いろいろエトセトラ。。。

プログラミング言語 最近の流行り廃り 2020

前に見てたの思い出したので今年(もう去年か)はどうなったのか確認してみた。2020のアンケートもそろそろ出るんじゃないかと思うんだけど、まだ2019までしかなさそうですね。


2020/5/28

と思ってたら昨日出てた。見た目すごい気合入ってる。

https://insights.stackoverflow.com/survey/2020


Googleトレンド

sample

まだ、Pythonの方が検索されてるのね。どこかでhaskelみたいな関数型やんなきゃダメだろーみたいな事言ってる人見たのでhaskelどんなもんかと思ったのですが、結構全然アレなのかしら。

StackOverFlowのアンケート(2020)

https://insights.stackoverflow.com/survey/2020

言語でまとめ

pg-order

フレームワークでまとめ

fr-order

プログラミング言語

sample-pg

去年からJavaをPythonが抜かしたのね。

WebFramework

sample-fr

jQueryは根強いですね。一時代を築いただけの事はある。レガシー的に残ってるのか、全然まだ第一線なのか。Angularも叩かれてる印象が強いのですが、使われ具合だとまだまだ健在?

MostLovedを見るとReactとVueがほぼっぽいし、jQueryはレガシー扱いになってそう?そもそも考え方違うしケースバイケース的なやつ?とりあえずの流行りはReactとVueでしょうか。

好きなフレームワーク

sample-loved-fr

嫌いなフレームワーク

sample-dreaded-fr

Database

sample-db

MySQLがちょっと復活。やっぱり一強。DBランキングだとOracle強いんだけど何でなんでしょ。対象にしてる人達が違うのかな?

MariaDBは個人的に頑張ってほしい。

Platform

sample-pf

開発者さんたちの環境的にはLinuxとWindowsって均衡してるんですね。世の中的にはWindowsダントツだったと思うけど。

そういえば、dockerってどうなんでしょ。たしか日本のdocker本番利用って15%くらいで伸び悩んでましたよね。あと、docker自体もクラウド環境での基盤?事業は売却して、開発者向けに注力するみたいなのをどこかで読んだ気がする。dockerは開発者さんのローカル環境で生き残ってく感じになるのでしょうか?CentOS8なんかも標準でPodmanになったみたいですし。先行き不透明。


Pythonの勢いはまだまだ健在?やっぱWebはjavascript祭りですね。ReactよりVue好きなんだけどなー。どっちも良いのですが。何かVueの方が好き。そういえば、nuxtのcore-js3.0で動かない問題はどうなるんだろうか。core-jsのメンテナ不在らしいですね。OSSのリスキーな面が推されちゃってる感じ。

あと、アンケート結果のMostLovedにも載ってたけど、Rustが割と良さそうな感じがするので、ちょっと本腰入れて使ってみようかな。。。

AWS CentOS8の公式イメージ

まだ無いらしい。

CentOSのForum上でも微妙に話題になってはいる。

誰かやってくれ~みたいな感じ?

今のところ、MarcketPlaceに2つの会社が上げてくれてる。コミュニティ上にも何個かはある。

ただ、公式イメージはない。

現状、自分でやる場合は↓の「CentOS-8-ec2-8.1.1911-20200113.3.x86_64.qcow2」使って自分でAMI登録しなさいって事みたい。

https://cloud.centos.org/centos/8/x86_64/images/

コミュニティ上のやつは、上げた人が自分用に作ってる感じなので、不要なパッケージとかも入ってたりするので、ちょっと微妙?まー十分ありがたいのですが。

日本人的に「公式」って言葉に弱いので、そろそろ対応して貰えると嬉しいんだけどなー。

あと、Stream版ってどうなんでしょ。開発に貢献したい人用な感じがするので、手を出すのはちょっと躊躇する。。。

Nuxtの開発環境をDockerで

DockerでNuxtのローカルの開発環境作りたくなった。

やってみたのですが、なかなか思い通りにいかなかったので記載。

やりたい事としては、nodeとかnode_modulesとかはdocker側において、ソースはローカル。

で、ローカルのソースを修正したら、nuxtというかVueのホットリロードを動かしたい。

ひとまずソースの構成。

.
├── app
│   ├── Dockerfile
│   └── webapp # nuxtのアプリ
└── docker-compose.yml

nuxtのアプリを作る

cd app
npx create-nuxt-app webapp # 質問は適当に動けばとりあえず。。。

で、ここでは「npm install」はしない。やった場合は後述。

Dockerfile

FROM node:14.1.0-alpine

WORKDIR /app

# 多分、nuxt動かすだけなら、@vue/cliとか@vue/cli-initはいらないと思う。
RUN apk update && \
    npm install -g npm && \
    npm install -g @vue/cli && \
    npm install -g @vue/cli-init && \
    npm install -g create-nuxt-app

ENV HOST 0.0.0.0

CMD ["npm", "run", "dev"]

Docker-compse

version: '3'
services:
  webapp:
    build: ./app
    ports:
      - 13000:3000
    volumes:
      - ./app/webapp:/app
    tty: true

ホスト側のPortは適当に。tty:trueはあっても無くてもどっちでも。docker内のコンソール出力を全部見たいのでひとまず付ける。

そしたら「docker-compose build」

build終わったら下記でコンテナ内で「npm install」する。

docker-compose run webapp ash
npm install
exit

そしたら「docker-compose up」

これで、上記のポートの割り当てだったら「http://localhost:13000」でnuxtのデモ画面が出る。

そのまま、ローカルのファイルを修正すればDocker側にも反映されてホットリロードされると。

全ソースはここに上げてます


で、ここから出来なかった事。

本当はbuildのところもdockerfile側に置きたい。↓の感じ。

COPY ./webapp/package.json /app/package.json
COPY ./webapp/package-lock.json /app/package-lock.json
RUN npm install

↑は上手くいくのですが、nuxtの実行をすると、「.nuxt」ってディレクトリ作られるじゃないですか?

こいつがかなりやっかいで、実行時に動的に作ってるらしく、ローカルのディレクトリと共有してると権限がおかしくなって動かなくなるのです。

dockerignoreとかマウントしてからvolumeで部分的に上書きして~とかローカルのuidと合わせて~とか色々やってみたのですが、どうにも上手くいかない。

今のところ上手くいった方法が上述のnpm installはbuild後にupする前にコンテナ内で実行しておくという手順。

んーカッコ悪いんだけど、開発環境としてローカル側にソース置きたい場合はこれしかやりようがなさそう。


途中でnpm installとかnpm run devしちゃって「node_modules」「.nuxt」出来ちゃってる場合はコンテナ内に入る前に全部消す。

sudo rm -rf .nuxt
sudo rm -rf node_modules

Python Djangoで単体テストの結果をマージ

Djangoで単体テストやってる時の話。規模が大きくなると実行対象分割して実行させたくなる。分割の仕方は色々あると思うので割愛。

で、分割実行した場合って結果のcovrageとかも分割されるので、結果をどうにかマージしたい。

jenkinsなんかに表示させてる場合、xunit形式の結果と.coverageが必要になる。

これをどうマージするのかという話。


coverage

Coverage.pyというのがあり、それを使う。というかDjangoの中でも使ってる模様。

普通の単体テストは「python manage.py test」みたいに実行すると思うのですが、

色々やりにくいので、Coverage.pyを通して実行するように変える。↓の感じ。

coverage run --source='.' manage.py test app/tests

で、これだとcoverageのデータファイルが全部「.coverage」になっちゃうので、ファイル名を変えるために下記にする。

COVERAGE_FILE=.coverage_datafile coverage run --source='.' manage.py test app/tests

環境変数の「COVERAGE_FILE」にファイル名指定しておいてから実行するらしい。

そうすると分割したテスト毎にファイル名固定出来るのであとはそれを最後に下記でマージする。

coverage combine .coverage_*

「.coverage_」でファイルを全部指定みたいな。上を実行すると「.coverage」ってデータファイルにまとまるので、あとは、「coverage html」とか「coverage xml」何かで必要なレポート形式に変換する。


xunit

xunitも同様にマージが必要。とりあえず、テストの実行時に下記のオプション指定して結果のファイル名を実行毎に指定してあげる。

manage.py test app/tests/target --with-xunit --xunit-file nose_result_xxx.xml

そしたら、こっちも実行毎にファイルが出来るので、これをマージする。

で、pythonでこれをマージするツール無いかなーって探してみたのですが、下記しかない。

https://pypi.org/project/xunitmerge/

ただ、このツール開発止まってるぽくて更新6年くらい止まってるんですよね。。。

ついでに、python3系で出来ない書き方してるようでそのままだと動かない。

下のプルリクの修正が必要みたい。

https://github.com/miki725/xunitmerge/pull/9

本体に取り込まれる事は無さそうな気がするので、自分でリポジトリ作ってそっち直して、そっちからPIPでインストールする。

GitHubとかGitLabとかリモートリポジトリからpipインストールする場合は↓の感じ。

※別に直で実行してもOK。

pip install  -b release git+https://github.com/***/***/xunitmerge

実行できるようにしたら、下記でマージする。

xunitmerge nosetests_*.xml nosetests.xml

「nosetests_」で始まるファイルを「nosetests.xml」にマージするみたいな。

あとはこれらをjenkinsなりに食わせればOKという寸法です。


最終的にDjangoのtest実行する時のコマンドはもろもろオプションとかつけた感じにすると下記の感じ。

COVERAGE_FILE=.coverage_datafile coverage run --source='.' manage.py test app/tests --settings=dapp.settings_hoge.py --keepdb --with-xunit --xunit-file nosetests_xxx.xml

VirtualBox CentOS7のディスクを拡張する

タイトル通り。やり方はググれば色々出てくるのですが、何となく古い気がするので記載。

コマンドで拡張して、OSに認識させてー。みたいな感じなのですが、

今のVirtualBoxなら拡張はGUIからいける。

ファイル⇒仮想メディアマネージャー。

vbox01

拡張したいvdi選択して、プロパティクリック⇒増やしたいサイズに変更して適用。

vbox02

これでディスクの拡張はおしまい。楽。

そしたら、拡張した分をOS側に認識させる。

CentOS7だったら、上記拡張後に左上のアプリケーション⇒ユーティリティ⇒ディスクで拡張分の

ディスクサイズが未使用領域として見えてるはず。これを使えるようにする。


ここから先は「root」でやる。

fdiskで対話的に作業する。これってGUIで作業できないんだろうか。。。


$ fdisk /dev/sda

コマンド (m でヘルプ): p  #テーブルの確認はp
コマンド (m でヘルプ): d  #dでいったん現状のメインのパーティションを削除
パーティション番号 (1,2, default 2): 2  #大体2番になってると思うけど↑で出た一覧参照
コマンド (m でヘルプ): n # 新しいパーティションを作成
Select (default p): p #プライマリ
パーティション番号 (2-4, default 2): # 2でよいのでエンター
Last sector, +sectors or +size{K,M,G} (2099200-62914559, 初期値 62914559): #デフォでよいのでエンター
コマンド (m でヘルプ): w # 保存して終了

# 終わったらOS再起動

途中で削除してて、最初ビビったんだけど、設定変えてるだけだからデータは大丈夫らしい。

起動し終わったらLVMの再設定。

$ pvresize /dev/sda2
$ lvextend -l +100%FREE /dev/centos/root
$ xfs_growfs /dev/centos/root

CSS 直前の要素のセレクタ & beforeとafterで一言

とある要素の直前の要素をCSSセレクタで指定したくなった。

<div>hoge</div> ←これを選択したい
<div class="fuga">fuga</div> ←ここから見て
<div>moge</div>

結論から言うとCSSセレクタではこれは無理っぽい。

兄弟要素(階層が同じ要素)の弟(後に出てくる要素)は選択できるんだけど、

兄(前に出てくる要素)を選択するセレクタはないらしい。。。

DOMの構造見直すか、JavaScript使ってどうにかするしかあるまい。

jQueryなら「.prev()」とかでいけるかな?jQuery使ってないけど。


で、ここから調べてる中で「コレ間違ってるんじゃないかな?」って思った話。

「CSS 直前の要素」でググって出てくるサイトは一杯あるのですが、

疑似要素のbeforeとafterでちょいちょいヒットしてる。

見てみると、beforeの説明でこんな内容になってる。

:before 要素の直前

とか

before / afterでそれぞれ要素の前後に[擬似要素]を追加することができます。

ん?って感じ。

↑の説明だと、構造的に下記をイメージしますよね?

<::before />
<div />
<::after />

要素の直前だからね。実際↑書いてるサイトの構造のイメージはそうなってた。

でも、MDNにはこう書いてある

In CSS, ::before creates a pseudo-element that is the first child of the selected element.

CSS における ::before は、選択した要素の最初の子要素として擬似要素を作成します。

子要素として 擬似要素を作成します

ですよね。

chromeあたりの開発ツールで見ると分かるのですが、どう見ても指定してる要素の

子要素として作ってるよね?

構造的には下記。


<div class="hoge">
  <.hoge::before />
  <something.... />
  <.hoge::after />
</div>

直前の要素って説明は間違ってると思うのです。

書くなら「before:直下の最初の子要素」とか「after:直下の最後の子要素」が正確な表現かしら?

.net バージョンの確認

公式にはいちをこんなページがあるのでそれを見た方がよいかも。

昔、MSDNにこのコマンドファイル載ってたのですが、そのページ見つけられなくなった。。。

いちを↑のコマンドファイル実行でインストールされてるバージョンの確認はできる。

で、実行PG側から今動いてるフレームワークのバージョンが何かを見たい場合は下記。

string clrVersionBuildtime = System.Reflection.Assembly.GetExecutingAssembly().ImageRuntimeVersion;
string clrVersion = System.Environment.Version.ToString();
Console.WriteLine(String.Format("ビルドバージョン:{0}", clrVersionBuildtime));
Console.WriteLine(String.Format("動作時バージョン:{0}", clrVersion));

v-calendarのdate-pickerで外から表示する月を変える

Vueのコンポーネントで、v-calendarっていうやつがある。

相当色んな事が出来て、今まで見てきたカレンダー的モジュールの中では一番じゃないだろうかと個人的に思ってる。

中のソースもめっちゃ勉強になる。

で、これのDatePickerを使う場合に、外から日付を渡して表示する場所を変えたかったりする。

一筋縄でいかなかったのでちょっと記載。


多分普通に使う分には↓の感じ。

<vc-date-picker v-model="dateval" />

適当なdataをv-modelで指定してあげれば、それに応じた日付にはしてくれると思う。

ただ、このdatevalを外で変えた場合に、カレンダーのページがその日付の月になってない。

これをやるのに、shoPageRangeっていうの呼ぶらしい。公式のドキュメントにもそんな感じで書いてある。

これのissue

まー上手くいかないと。popoverの場合は上手くいかない。is-inlineだとうまくいくっぽい。

どうもpopoverの場合、$refs.calendarの$refsがcalendarじゃなくてpopoverになってるみたいですね。

で、ソース色々見てたら、少なくとも最新のバージョンではどうも違うっぽい。正解はこっちだと思う。

<vc-date-picker v-model="dateval" ref="calendar"/>

methods:{
  changePage(){
    this.dateval = "何かの日付"
    this.$refs.calendar.adjustPageRange()//コッチ
  }
}

datepicker使う場合は少なくとも「adjustPageRange」っぽいですね。

内部的なカレンダーの日付のページにこれで合わせてくれる模様。

コード的にはここ

あと、カレンダーが非表示の状態だと動かないっぽい?

なので、最終的にはこんな感じにしておく必要がありそう。

<vc-date-picker v-model="dateval" ref="calendar" @popoverDidShow="handleShow"/>

methods:{
  changePage(){
    this.dateval = "何かの日付"
  },
  handleShow(){
    カレンダーが表示されたときに呼ぶ
    this.$refs.calendar.adjustPageRange()
  }
}

Python import thisの裏

import thisは色んな人が解説書いてるので少し違った個人の視点をば。

import thisのソースってこんな感じ。

s = """Gur Mra bs Clguba, ol Gvz Crgref

Ornhgvshy vf orggre guna htyl.
Rkcyvpvg vf orggre guna vzcyvpvg.
Fvzcyr vf orggre guna pbzcyrk.
Pbzcyrk vf orggre guna pbzcyvpngrq.
Syng vf orggre guna arfgrq.
Fcnefr vf orggre guna qrafr.
Ernqnovyvgl pbhagf.
Fcrpvny pnfrf nera'g fcrpvny rabhtu gb oernx gur ehyrf.
Nygubhtu cenpgvpnyvgl orngf chevgl.
Reebef fubhyq arire cnff fvyragyl.
Hayrff rkcyvpvgyl fvyraprq.
Va gur snpr bs nzovthvgl, ershfr gur grzcgngvba gb thrff.
Gurer fubhyq or bar-- naq cersrenoyl bayl bar --boivbhf jnl gb qb vg.
Nygubhtu gung jnl znl abg or boivbhf ng svefg hayrff lbh'er Qhgpu.
Abj vf orggre guna arire.
Nygubhtu arire vf bsgra orggre guna *evtug* abj.
Vs gur vzcyrzragngvba vf uneq gb rkcynva, vg'f n onq vqrn.
Vs gur vzcyrzragngvba vf rnfl gb rkcynva, vg znl or n tbbq vqrn.
Anzrfcnprf ner bar ubaxvat terng vqrn -- yrg'f qb zber bs gubfr!"""

d = {}
for c in (65, 97):
    for i in range(26):
        d[chr(i+c)] = chr((i+13) % 26 + c)

print("".join([d.get(c, c) for c in s]))

文字列表示してるだけなのですが、カエサル式(シーザー式)暗号っていうのやってます。

65がasciiコードでいう「A」で97が「a」。でそれぞれ26文字分繰り返して13文字分ずらした文字に直して出力。みたいな。


こういうの見ると「遊び心」があるー。って感じするじゃん?

何か洒落てる感じするじゃないですか。

「遊び心」が大事だよねって思うじゃないですか。

で、遊ぶってすごいなと思うわけです。

例えば将棋とかチェスとか、野球とかサッカーとかバスケみたいなスポーツでもいいし、大工さんだったりF1だったり、別にゲームでもいい、例えば地球防衛軍とかバイオハザードとか。

何でもそうだと思うのですが、本気で遊べるためには、その何かに精通してなきゃ無理だと思うんですよ。

それなりに精通してないと遊ぶ余裕が全くないし、動かすだけで精一杯。

遊び心が出せるって事はそれに精通してるって事。

そのくらい知識とか経験とかちゃんと身に着けなよって言われた気がしたのです。

まー気のせいだ。。。

Pythonのクラス変数を定数(再代入禁止の変数)として扱う - 名前空間を分けたい

Pythonには他の言語でいう定数がない。

慣習的に定数扱いにしたい場合は大文字で書くみたいなのはある。

FOO = 100

みたいな。。。

ちんまりしたアプリだったら別に上記のくらいのルールでもいいかもだけど、

そこそこ大きいアプリになって色んな開発者が長期に渡って触る可能性がある場合。

定数を定数として扱わなくなる危険性があるので、ちゃんと再代入は禁止できるようにしたい。

で、これをやるのによく見るのって下の感じ。

# 「const.py」ってファイルで作成

class _const:
    def __setattr__(self, name, value):
        if name in self.__dict__:
            # 定義されたら例外出す
            raise TypeError(f'Can\'t rebind const ({name})')
        self.__dict__[name] = value

import sys
sys.modules["const"]=_const()

# ↑を作ったら↓

import const

const.FOO = 'hoge'
const.FOO = 'fuga' # 例外でる

これで再代入を禁止した定数っぽいものが作れると。参考元


ただ、これって「const」クラスの「インスタンス変数」として突っ込んでるだけ。ってそれがダメなわけじゃないですが、大量に定義したい時なんかはちょっと・・・。

あと、試してないのですが、名前空間一つになっちゃうと思うので、色んなPGで使うと変数名かぶったりした時にやられたりしないのかしら?

という事で、定数をある程度まとまった役割(名前空間)で分けたい場合に例えば、、、

class Moge:
   FOO = 100

# ↑こういう風にまとめて、
# ↓こういう風に使いたい

do_something(Moge.FOO)

って感じにしたいのですが、前述のやり方だと

class Moge:
   const.FOO = 100

みたいになっちゃうので無理。

何かやり方ないかなと思ってたら、PythonのClass定義は、それ自体もインスタンスだったなと思い出しまして、こんな風にしてみたら意外と出来た。


# クラス定義そのものに対してのsetter制御用メタクラス
class ConstMeta(type):
    def __setattr__(self, name, value):
        if name in self.__dict__:
            raise TypeError(f'Can\'t rebind const ({name})')
        else:
            self.__setattr__(name, value)

# 定数定義
class MyConstClass(metaclass=ConstMeta):
    X = 10
    Y = 20

MyConstClass.X # 10
MyConstClass.X = 30 # 例外
MyConstClass.Z = 40 # これは別の例外

これで定数を役割なんかでまとめた分類が出来るという寸法です。

Metaクラスってクラス定義に対しての特殊メソッドを定義出来るので、

↑の感じでクラス変数(属性)へのsetterをねじ込んだ感じ。

ただ、この場合は本当に定数だけのクラスじゃないとダメだと思う。

問合せ