SCSSを scss-lint でチェックしてるんだけど、デフォルトで推奨されているコメントが //
となっている。
しかし、NERDCommenter でコメントアウトした際には /* */
となっていて面倒なのでSCSSのデフォルトのコメント設定を変更したい。
.vimrc に以下のように追記する
let g:NERDCustomDelimiters = { \ 'scss': { 'left': '//'} \}
SCSSを scss-lint でチェックしてるんだけど、デフォルトで推奨されているコメントが //
となっている。
しかし、NERDCommenter でコメントアウトした際には /* */
となっていて面倒なのでSCSSのデフォルトのコメント設定を変更したい。
let g:NERDCustomDelimiters = { \ 'scss': { 'left': '//'} \}
年末年始対応の時期ですね。
svg画像を 著作権表示 - Wikipedia より。
企業で働くエンジニアは、あけおめ対策をはじめとした年末年始の対応準備に時間を割いていることでしょう。
その中でも、毎年恒例の著作権表記、特に年号更新の対応に追われる方が多いでしょう。
アレ、不要なので辞めましょう。
著作権表示(ちょさくけんひょうじ)は、著作物の複製物につける著作権者や著作物の発行年等に関する表示である。著作者が著作権を取得するため、著作物の創作のほか、何らかの手続き等(方式)が必要な法域においては、著作権表示は重要な意味があるが、現在は、ほぼ全ての法域で著作権は、著作物の創作とともに発生するので、重要性は失われている。
著作権表示 - Wikipedia より引用
日本国内に於いては、1971年7月24日にパリで改正された万国著作権条約に受諾しており、現在はこちらの内容に批准しています。 その第三条四項には以下のように定められています。
4 各締約国は、他の締約国の国民の発行されていない著作物を、方式の履行を要することなく保護するための法的手段を確保する。
千九百七十一年七月二十四日にパリで改正された万国著作権条約 - Wikisource より引用
ここでいう "方式" とは、著作権の無方式主義と方式主義のことです。
無方式主義 著作物を著作もしくは発表した時点で自動的に著作権が発生し、それ以外には何らの方式(又は手続)の履行を要求しない法制 方式主義 納入、登録、表示、官庁への納入、登録、登録手数料の支払い、自国内における製造もしくは発行などといった「方式」を履行することにより著作権の発生要件とする法制
著作権表示 - Wikipedia より引用
またまたWikipedia引用ですみません。ちなみに私はこの件について8年程前から疑問を抱き、毎年この時期になる度に当該Wikipediaページをwatchして参りました(編集は一切してない)。昔に比べると非常に明瞭になっており、私以外にもこの件で戦ってきた人が居るのかと思うと非常に感慨深いものがあります。 当時はガラケー全盛期の為、All rights reserved. を書くだけでフッターに無駄な改行が入ったのです。
要するに、「万国著作権条約に締約している国の国民は、何もせずとも著作物の権利を保護する法的手段を持っている。」ということになります。
何もせずとも、です。
つまり要らないのです。
前述の通り不要なのですが、方式主義に於いて認められているのは © であり、(c) は認められていません。
その為、.txt ファイルとかに (c) と書いていても無効なので書くのは辞めましょう。
こちらは万国著作権条約には関係ありません。万国著作権条約制定前に策定されたブエノスアイレス条約という条約があるのですが、この条約では「権利を所有している」表記が必要でした(方式主義)。
アメリカ合衆国をはじめとした国々が締約し、「権利を所有している」表記として、All rights reserved. が使われました。 現在では、アメリカを含め殆どの国がベルヌ条約*1及び万国著作権条約にも締約している為、この表記は現在は不要です。
ちなみに、 日本はこのブエノスアイレス条約に締約していません。
したがって、 日本では全く意味がありません。
アメリカ企業の権利表記を日本企業がコピペしたものが蔓延したんでしょうねぇ...
All rights reserved. の直訳は、「すべての権利を保有している」です。
イマドキのWebサービスに於いて、そのようなケースが果たして本当に成立しているのでしょうか?
意味の無い All rights reserved. を書くことで、逆に訴訟や炎上リスクを招く可能性もありそうです。
規約の話ではありますが、mixiの規約改定時に問題になりましたね。
ミクシィの利用規約改定問題が示すCGM時代の権利処理のあり方 - ビジネススタイル - nikkei BPnet
他の例として、有名なCGMサービスとして ボケてがありますが、全ページのフッターに All rights reserved. と書いてあります。
しかし、利用規約には、
第17条 弊社の財産権
( 1 ) 利用者が送信(発信)したコンテンツおよび情報を除き、本サービスに含まれる一切のコンテンツおよび情報に関する財産権は弊社に帰属します。
と書いてあり、Allとは一体...うごごごごご...と思ったりします。*2
利用者が投稿したコンテンツおよび(他者の著作物を含む)画像の権利の帰属を宣言しない辺り、ボケてはしっかりしている方かも知れません。
はい。専門家ではありません。ぜひとも専門家からの意見もいただきたいところです。 弁護士ドットコム - 無料法律相談や弁護士、法律事務所の検索 でニュースとして取り上げていただけること、お待ちしております。
とはいえ根拠も無いままではアレなので、ここは最強法務部と名高い任天堂法務部のチェックを通ったであろう任天堂公式サイトを確認してみましょう。
お、超シンプルです。私が思う理想形です。
先日 サムスンから賠償金5億4800万ドルせしめた Appleはというと、
Apple より
あ、年号もAll right reserved. がありました。
本気で何も書いてない...
思ったよりバラバラの模様です。
原理主義的な話を散々述べましたが、本懐は「毎年毎年、年号を更新するだけの無駄なクソ作業を無くしたい」です。
現実として、社内の一エンジニアや受託エンジニアでまるっと無くすというのは現実的ではないでしょう。
その場合の対応として、以下の解決策を検討しましょう。
Date()
関数などから現在の年号を表記するなどして動的に出力しましょう。
404.html とか 500.html などは、コンテンツなんてあってないようなページなので、© 会社名 または© 会社名 All rights reserved. にして年号は無くしましょう。
クライアント側で実行するJavaScriptでの年号出力は推奨しませんが、どうしても上長がOKしてくれない場合や、一時的なキャンペーンページなどの静的ページではJavaScriptでの実行もアリかもしれません。JavaScript無効設定での著作権表記について問題視する上長ならば、著作権表記自体の不要性やコストについても議論の余地がありそうです。
いずれにせよ手動更新は辞めましょう。
以下のサイトを判断材料にしてもらいましょう。
こんなことに時間を浪費しているうちはスピーディな開発なんて出来やしない。
フロントエンド開発に便利なNode.js環境で、ファイル変更時に自動でSass(SCSS)からCSSファイルを生成したい。
上位互換記事を書きました。
gulp-sassで自動でSass/SCSSからcssファイルを生成したり、他にもいろいろする - 人生リアルタイムアタック
以下のようなディレクトリ構成を想定。
. ├── css │ └── // cssファイルの生成先 └── assets └── sass └── main.scss
gulpとgulp-sassをインストールする
$ npm install gulp gulp-sass
まずは最も簡単な例として、*.scssに変更があれば自動で*.cssを生成する例。
var gulp = require('gulp'); var sass = require('gulp-sass'); // Sassコンパイルタスク gulp.task('sass', function(){ gulp.src('./assets/sass/**/*.scss') .pipe(sass()) .pipe(gulp.dest('./css/')); }); // watchタスク(**/*.scss変更時に実行するタスク) gulp.task('sass-watch', ['sass'], function(){ var watcher = gulp.watch('./src/sass/**/*.scss', ['sass']); watcher.on('change', function(event) { console.log('File ' + event.path + ' was ' + event.type + ', running tasks...'); }); }); // gulpのデフォルト動作としてsass-watchを実行 gulp.task('default', ['sass-watch']);
$ gulp
を実行するだけで、後はSCSS変更時に自動でCSSが生成されるようになる。
**/*.scss
としている場合、hoge/hoge.scss
のcssの出力先も hoge/hoge.css
としてくれる。親切。
gulpfile.js内の .pipe(sass())
を、 .pipe(sass({outputStyle: 'expanded'}))
にすると、よくみるcssフォーマットで生成されるようになる。
gulp-plumber を使う。
var gulp = require('gulp'); var sass = require('gulp-sass'); var plumber = require('gulp-plumber'); // sassコンパイルタスク gulp.task('sass', function(){ gulp.src('./src/sass/**/*.scss') .pipe(plumber()) // ←ここが追加 .pipe(sass()) .pipe(gulp.dest('./css/')); }); // watchタスク(Sassファイル変更時に実行するタスク) gulp.task('sass-watch', ['sass'], function(){ var watcher = gulp.watch('./src/sass/**/*.scss', ['sass']); watcher.on('change', function(event) { console.log('File ' + event.path + ' was ' + event.type + ', running tasks...'); }); }); gulp.task('default', ['sass-watch']);
こうするとエラー時にも落ちない。
var gulp = require('gulp'); var sass = require('gulp-sass'); var bs = require('browser-sync').create(); // browser-sync gulp.task('bs', function(){ var bsOptions = {} bsOptions.files = ['template/**/*.html', 'css/**/*.css']; bsOptions.port = 3000; bs.init(bsOptions); }); // sassコンパイルタスク gulp.task('sass', function(){ gulp.src('./src/sass/**/*.scss') .pipe(sass()) .pipe(gulp.dest('./css/')); }); // watchタスク(Sassファイル変更時に実行するタスク) gulp.task('sass-watch', ['sass'], function(){ var watcher = gulp.watch('./src/sass/**/*.scss', ['sass']); watcher.on('change', function(event) { console.log('File ' + event.path + ' was ' + event.type + ', running tasks...'); }); }); gulp.task('default', ['bs', 'sass-watch']);
こんな感じかなー
Flask 最近書いてるんだけれども、今更閉じタグなんて書きたくないんじゃ!ということで、様々HTML Template触った結果最も書きやすかったHamlを使いたい。
ということで hamlish-jinja を使う。
Flaskのdefault template engineであるjinjaのoptionsに、hamlish-jinjaを渡したclassを生成して実行する。
from flask import Flask, render_template from werkzeug import ImmutableDict class FlaskWithHamlish(Flask): jinja_options = ImmutableDict( extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_', 'hamlish_jinja.HamlishExtension'] ) app = FlaskWithHamlish(__name__) @app.route('/') def index(): return render_template('index.haml') if __name__ == '__main__': app.run()
hamlish-jinjaには幾つかのオプションが用意されている。 以下はその一例。
https://github.com/Pitmairen/hamlish-jinja#configuration
あくまでHamlishであって、Hamlと全く同じではない。
Hamlで可能な記述(hamlish-jinjaでは不可)
%meta {name:'viewport', content:'width=device-width, initial-scale=1'}
hamlish-jinjaで可能な記述
%meta name='viewport' content='width=device-width, initial-scale=1'
他の方法でできるからいいじゃんという話になっている。
Added doctype strings. by totkeks · Pull Request #15 · Pitmairen/hamlish-jinja · GitHub
このケースでは、app.py側に以下のように書いたらいいじゃんという話。
import jinja2 jinja_env.globals['html5'] = jinja2.Markup('<!DOCTYPE html>')
つまり、hamlとまったく同じ記述ができるというわけではなく、あくまでもhamlっぽく書けるという話。
hamlish-jinjaでのコメントは ;
です。なんでや。
;Test comment
↓ を使いましょう。
hamlish-jinja/haml2hamlish.py at master · Pitmairen/hamlish-jinja · GitHub
それでもhamlishなtemplateは記述量の少なさから得られる恩恵が大きいのでもうちょっと使って見る予定。 とはいえ、hamlと完全互換では無いので、そこの差異を認識した上で利用するのが望ましそう。
HTTPSで提供しているサービスのローカル開発環境にPythonでアクセスを試みたらエラーが出た。
Traceback (most recent call last): File "/main.py", line 36, in <module> main() File "/main.py", line 18, in main soup = BeautifulSoup(opener.open(conf['login_url']).read().decode('utf-8'), 'html.parser') File "/usr/local/var/pyenv/versions/3.5.0/lib/python3.5/urllib/request.py", line 465, in open response = self._open(req, data) File "/usr/local/var/pyenv/versions/3.5.0/lib/python3.5/urllib/request.py", line 483, in _open '_open', req) File "/usr/local/var/pyenv/versions/3.5.0/lib/python3.5/urllib/request.py", line 443, in _call_chain result = func(*args) File "/usr/local/var/pyenv/versions/3.5.0/lib/python3.5/urllib/request.py", line 1283, in https_open context=self._context, check_hostname=self._check_hostname) File "/usr/local/var/pyenv/versions/3.5.0/lib/python3.5/urllib/request.py", line 1242, in do_open raise URLError(err) urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:646)>
PEP 0476に従い、Python2.7.9以降はSSL証明書が正しくない場合にはデフォルトでSSL認証エラーを出すようになった模様。 PEP 476 -- Enabling certificate verification by default for stdlib http clients | Python.org
開発環境にアクセスするだけのコードだったので、
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
上記を書いて実行したらアクセス可能になった。
セキュリティ上は安全と保証されないことを認識の上でご利用ください。
Pythonで要ログインのサービスをスクレイピングをする際にはbuild_openerを利用するが、User-agentも指定する必要があるケースがある。
通常のbuild_opener
# coding: utf-8 import http.cookiejar import yaml from bs4 import BeautifulSoup from urllib import parse, request def main(): # yaml conf = yaml.load(open('conf.yaml').read()) # login opener = request.build_opener(request.HTTPCookieProcessor(http.cookiejar.CookieJar())) post = { 'username': conf['username'], 'password': conf['password'] } query = urllib.parse.urlencode(post).encode('utf-8') opener.open(conf['login_url'], query) # 以下スクレイピング処理など... soup = BeautifulSoup(opener.open(conf['scrap_url']).read().decode('utf-8'), 'html.parser')
もしUser-agentの指定が必要な場合には以下のようにするとよい。
# coding: utf-8 import http.cookiejar import yaml from bs4 import BeautifulSoup from urllib import parse, request def main(): # yaml conf = yaml.load(open('conf.yaml').read()) # login opener = request.build_opener(request.HTTPCookieProcessor(http.cookiejar.CookieJar())) opener.addheaders = [('User-agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.73 Safari/537.36')] post = { 'username': conf['username'], 'password': conf['password'] } query = urllib.parse.urlencode(post).encode('utf-8') opener.open(conf['login_url'], query) # 以下スクレイピング処理など... soup = BeautifulSoup(opener.open(conf['scrap_url']).read().decode('utf-8'), 'html.parser')
urllib.request.build_opener()で作成したインスタンスは OpenDirectorオブジェクト と呼ばれるものであり、urllib.request.urlopen()と引数、返り値が一緒である。*1 加えて、addheaders()でOpenDirectorインスタンスにヘッダーを指定できるので、こちらを利用してUser-agentを指定すればよい。
公式にも以下のURLに例が載っているので、こちらを参考にすると他の用途も掲載されている。 http://docs.python.jp/3.4/library/urllib.request.html#examples
$ memcached-tool localhost dump
文字化けする場合には strings
による文字列変換を行う。
$ memcached-tool localhost dump | strings